diff --git a/.gitignore b/.gitignore index 823d175eb670..812ffd4e04c7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ lib/* *.log *.log.* *.csv -config.json src/test/data/sandbox/ preferences.json .DS_Store @@ -18,3 +17,4 @@ classes/ /bin/ src/main/resources/docs/ out/ +forumData/ diff --git a/README.adoc b/README.adoc index 142ae1b17fbd..944b6becaf3b 100644 --- a/README.adoc +++ b/README.adoc @@ -1,11 +1,9 @@ -= Address Book (Level 4) += Forum Book 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://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]] -https://gitter.im/se-edu/Lobby[image:https://badges.gitter.im/se-edu/Lobby.svg[Gitter chat]] +image:https://travis-ci.org/CS2113-AY1819S1-T13-2/main.svg?branch=master["Build Status", link="https://travis-ci.org/CS2113-AY1819S1-T13-2/main"] +https://ci.appveyor.com/project/xllx1/main[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]] +https://coveralls.io/github/CS2113-AY1819S1-T13-2/main?branch=master[image:https://coveralls.io/repos/github/CS2113-AY1819S1-T13-2/main/badge.svg?branch=master[Coverage Status]] ifdef::env-github[] image::docs/images/Ui.png[width="600"] @@ -15,24 +13,26 @@ 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. +== Objective +* This is a CLI (Command Line Interface) Forum Book application written in OOP fashion. +* This project aims to provide a convenient place for NUS students to discuss the modules details before bidding + +== Supported Platform + +* Main stream OSes, Windows, MacOS, Linux +* Java 9 runtime and above is required +* Keyboard and monitor obviously == Site Map * <> * <> -* <> * <> * <> == Acknowledgements +* This forum book is build on top of AddressBook-Level4 project that was created by https://github.com/se-edu/[SE-EDU] initiative * 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/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/junit5[JUnit5] diff --git a/_reposense/config.json b/_reposense/config.json new file mode 100644 index 000000000000..be019eafe1fd --- /dev/null +++ b/_reposense/config.json @@ -0,0 +1,24 @@ +{ + "authors": [ + { + "githubId": "Meowzz95", + "displayName": "Zhao Mingda", + "authorNames": [ + "Meowzz95", + "mimimi" + ] + }, + { + "githubId": "xllx1", + "displayName": "Cai Xiaolin" + }, + { + "githubId": "HansKoh", + "displayName": "Xu Hanhui" + }, + { + "githubId": "E0191729", + "displayName": "Dinesh Durai" + } + ] +} diff --git a/build.gradle b/build.gradle index f8e614f8b49b..b576cfc87877 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ if (JavaVersion.current() == JavaVersion.VERSION_1_10 } // Specifies the entry point of the application -mainClassName = 'seedu.address.MainApp' +mainClassName = 'com.t13g2.forum.MainApp' sourceCompatibility = JavaVersion.VERSION_1_9 targetCompatibility = JavaVersion.VERSION_1_9 @@ -66,6 +66,7 @@ dependencies { implementation group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '2.3.0' implementation group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.0' implementation group: 'javax.activation', name: 'activation', version: '1.1.1' + implementation 'com.google.code.gson:gson:2.8.5' testImplementation group: 'junit', name: 'junit', version: '4.12' testImplementation group: 'org.testfx', name: 'testfx-core', version: testFxVersion, { @@ -82,7 +83,7 @@ dependencies { } shadowJar { - archiveName = 'addressbook.jar' + archiveName = 'ForumBook.jar' destinationDir = file("${buildDir}/jar/") } @@ -157,16 +158,16 @@ test { } if (runNonGuiTests) { - test.include 'seedu/address/**' + test.include 'com/t13g2/forum/**' } if (runGuiTests) { test.include 'systemtests/**' - test.include 'seedu/address/ui/**' + test.include 'com/t13g2/forum/ui/**' } if (!runGuiTests) { - test.exclude 'seedu/address/ui/**' + test.exclude 'com/t13g2/forum/ui/**' } } } @@ -207,9 +208,8 @@ asciidoctor { idprefix: '', // for compatibility with GitHub preview idseparator: '-', 'site-root': "${sourceDir}", // must be the same as sourceDir, do not modify - 'site-name': 'AddressBook-Level4', - 'site-githuburl': 'https://github.com/se-edu/addressbook-level4', - 'site-seedu': true, // delete this line if your project is not a fork (not a SE-EDU project) + 'site-name': 'ForumBook', + 'site-githuburl': 'https://github.com/CS2113-AY1819S1-T13-2/main', ] options['template_dirs'].each { diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc index e647ed1e715a..a58286c87e93 100644 --- a/docs/AboutUs.adoc +++ b/docs/AboutUs.adoc @@ -4,53 +4,46 @@ :imagesDir: images :stylesDir: stylesheets -AddressBook - Level 4 was developed by the https://se-edu.github.io/docs/Team.html[se-edu] 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]. +ForumBook was developed by CS2113 T13 Group 2 team. + +{empty} == 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]] [<>] - -Role: Project Advisor - ''' -=== John Roe -image::lejolly.jpg[width="150", align="left"] -{empty}[http://github.com/lejolly[github]] [<>] +=== Zhao Mingda +image::meowzz95.png[width="150", align="left"] +{empty}[https://github.com/Meowzz95[github]] [https://github.com/CS2113-AY1819S1-T13-2/main/tree/master/docs/team/meowzz95.adoc[Project Portfolio page]] -Role: Team Lead + -Responsibilities: UI +Role: Project Leader + +Responsibility: storage implementation ''' -=== Johnny Doe -image::yijinl.jpg[width="150", align="left"] -{empty}[http://github.com/yijinl[github]] [<>] +=== Xu Hanhui +image::hanskoh.png[width="150", align="left"] +{empty}[https://github.com/HansKoh[github]] [https://github.com/CS2113-AY1819S1-T13-2/main/tree/master/docs/team/hanskoh.adoc[Project Portfolio page]] Role: Developer + -Responsibilities: Data +Responsibilities: CRUD feature ''' -=== Johnny Roe -image::m133225.jpg[width="150", align="left"] -{empty}[http://github.com/m133225[github]] [<>] +=== Dinesh Mangalanathadurai +image::e0191729.png[width="150", align="left"] +{empty}[http://github.com/E0191729[github]] [https://github.com/CS2113-AY1819S1-T13-2/main/tree/master/docs/team/e0191729.adoc[Project Portfolio page]] Role: Developer + -Responsibilities: Dev Ops + Threading +Responsibilities: + Key focus on user management ''' -=== Benson Meier -image::yl_coder.jpg[width="150", align="left"] -{empty}[http://github.com/yl-coder[github]] [<>] +=== Cai Xiaolin +image::xllx1.png[width="150", align="left"] +{empty}[https://github.com/xllx1[github]] [https://github.com/CS2113-AY1819S1-T13-2/main/tree/master/docs/team/xllx1.adoc[Project Portfolio page]] Role: Developer + -Responsibilities: UI +Responsibilities: admin management feature ''' diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index ea58481e4740..6748ceb59850 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 4 - Developer Guide += Forum Book - Developer Guide :site-section: DeveloperGuide :toc: :toc-title: @@ -12,9 +12,9 @@ ifdef::env-github[] :note-caption: :information_source: :warning-caption: :warning: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level4/tree/master +:repoURL: https://github.com/CS2113-AY1819S1-T13-2/main/ -By: `Team SE-EDU`      Since: `Jun 2016`      Licence: `MIT` +By: `Team CS2113 T13-2`      Since: `Aug 2018`      Licence: `MIT` == Setting up @@ -49,7 +49,7 @@ This will generate all resources required by the application and tests. === Verifying the setup -. Run the `seedu.address.MainApp` and try a few commands +. Run the `MainApp` and try a few commands . <> to ensure they all pass. === Configurations to do before writing code @@ -111,7 +111,7 @@ The *_Architecture Diagram_* given above explains the high-level design of the A [TIP] The `.pptx` files used to create diagrams in this document can be found in the link:{repoURL}/docs/diagrams/[diagrams] folder. To update a diagram, modify the diagram in the pptx file, select the objects of the diagram, and choose `Save as picture`. -`Main` has only one class called link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp`]. It is responsible for, +`Main` has only one class called link:{repoURL}/src/main/java/t13g2/forum/MainApp.java[`MainApp`]. It is responsible for, * At app launch: Initializes the components in the correct sequence, and connects them up with each other. * At shut down: Shuts down the components and invokes cleanup method where necessary. @@ -141,17 +141,17 @@ image::LogicClassDiagram.png[width="800"] [discrete] ==== Events-Driven nature of the design -The _Sequence Diagram_ below shows how the components interact for the scenario where the user issues the command `delete 1`. +The _Sequence Diagram_ below shows how the components interact for the scenario where the user issues the command `deleteModule mCode/CS2113`. -.Component interactions for `delete 1` command (part 1) -image::SDforDeletePerson.png[width="800"] +.Component interactions for `deleteModule mCode/CS2113` command (part 1) +image::SDDeleteModule.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 `ForumBookChangedEvent` when the Forum Book 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. -.Component interactions for `delete 1` command (part 2) +.Component interactions for `delete m/CS2113 i/1` command (part 2) image::SDforDeletePersonEventHandling.png[width="800"] [NOTE] @@ -165,11 +165,11 @@ The sections below give more details of each component. .Structure of the UI Component image::UiClassDiagram.png[width="800"] -*API* : link:{repoURL}/src/main/java/seedu/address/ui/Ui.java[`Ui.java`] +*API* : link:{repoURL}/src/main/java/t13g2/forum/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` 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`] +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/t13g2/forum/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`] The `UI` component, @@ -185,144 +185,240 @@ The `UI` component, image::LogicClassDiagram.png[width="800"] *API* : -link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`] +link:{repoURL}/src/main/java/t13g2/forum/logic/Logic.java[`Logic.java`] -. `Logic` uses the `AddressBookParser` class to parse the user command. +. `Logic` uses the `ForumBookParser` 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 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. +Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("deleteModule mCode/CS2113")` API call. -.Interactions Inside the Logic Component for the `delete 1` Command -image::DeletePersonSdForLogic.png[width="800"] - -[[Design-Model]] -=== Model component - -.Structure of the Model Component -image::ModelClassDiagram.png[width="800"] - -*API* : link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model.java`] - -The `Model`, - -* stores a `UserPref` object that represents the user's preferences. -* stores the Address Book 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. - -[NOTE] -As a more OOP model, we can store a `Tag` list in `Address Book`, which `Person` can reference. This would allow `Address Book` to only require one `Tag` object per unique `Tag`, instead of each `Person` needing their own `Tag` object. An example of how such a model may look like is given below. + - + -image:ModelClassBetterOopDiagram.png[width="800"] +.Interactions Inside the Logic Component for the `deleteModule mCode/CS2113` Command +image::DeleteModuleSdForLogic.png[width="800"] [[Design-Storage]] -=== Storage component -.Structure of the Storage Component -image::StorageClassDiagram.png[width="800"] +// tag::storage_component[] +=== Storage component -*API* : link:{repoURL}/src/main/java/seedu/address/storage/Storage.java[`Storage.java`] 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 Forum Book data in encrypted json format and read it back. + +// end::storage_component[] [[Design-Commons]] === Common classes -Classes used by multiple components are in the `seedu.addressbook.commons` package. +Classes used by multiple components are in the `t13g2.forum.commons` package. == Implementation This section describes some noteworthy details on how certain features are implemented. -// tag::undoredo[] -=== Undo/Redo feature +// tag::curd[] +=== CURD feature ==== Current Implementation +CURD refers to `create`, `update`, `read` and `delete`. This feature is implemented to achieve the basic functionalities of the Forum Book. It extends `ForumBook` with various commands and supports the following operations: -The undo/redo mechanism is facilitated by `VersionedAddressBook`. -It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. -Additionally, it implements the following operations: +* `createThread`: Create a new thread under a specific module that exists with comment. +* `createComment`: Create a new comment under a specific thread that exists. +* `updateThread`: Update an existing thread title created(unblocked) by its user. +* `updateComment`: Update an existing comment content created(unblocked) by its user. +* `listModule`: List out all the modules in the Forum Book. +* `selectModule`: Select a specific module and list out all the threads under the module. +* `selectThread`: Select a specific thread and list out all the comments under the thread. +* `deleteThread`: Delete a specific thread. +* `deleteComment`: Delete a specific comment. -* `VersionedAddressBook#commit()` -- Saves the current address book state in its history. -* `VersionedAddressBook#undo()` -- Restores the previous address book state from its history. -* `VersionedAddressBook#redo()` -- Restores a previously undone address book state from its history. +Given below is an example usage scenario and how the CURD can be operated by user at each step. -These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively. +Step 1. The user launches the application, executes `createThread mCode/CS2113 tTitle/Exam Information cContent/What is the topic coverage for the final?` to create and add the thread into storage file. The createThread command calls `UnitOfWork.commit()`, saving the modified forum book state into ForumBookStorage. -Given below is an example usage scenario and how the undo/redo mechanism behaves at each step. +Step 2. The user executes `createComment tId/123 cContent/This is a new comment content` to create and add the comment into storage file. The createComment command calls `UnitOfWork.commit()`, saving the modified forum book state into ForumBookStorage. -Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state. +Step 3. The user executes `updateThread tId/123 tTitle/This is a new thread title` to update the title of the specific thread from storage file. The updateThread command calls `UnitOfWork.getForumThreadRepository().getThread(threadId)`,`forumThread.setTitle()` and lastly `UnitOfWork.commit()`, saving the modified forum book state into ForumBookStorage. -image::UndoRedoStartingStateListDiagram.png[width="800"] +Step 4. The user executes `updateComment cId/123 cContent/This is a new comment content` to update the content of the specific comment from storage file. The updateComment command calls `UnitOfWork.getCommentRepository().getComment(commentId)`,`comment.setContent()` and lastly `UnitOfWork.commit()`, saving the modified forum book state into ForumBookStorage. -Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state. +Step 5. The user executes `listModule` to retrieve all the existing modules from storage file. The `listModule` command calls `UnitOfWork.getModuleRepository().getAllModule()` which returns the module list to be shown in the panel. -image::UndoRedoNewCommand1StateListDiagram.png[width="800"] +Step 6. The user executes `selectModule mCode/CS2113` to retrieve the module with module code CS2113 and its thread list from storage file. The `selectModule` command calls `UnitOfWork.getModuleRepository().getModuleByCode(moduleCode)` and `UnitOfWork.getForumThreadRepository().getThreadsByModule(module)` to return the module and thread list to be shown in the panel. -Step 3. The user executes `add n/David ...` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`. +Step 7. The user executes `selectThread tId/123` to retrieve the thread with ID 123 and its comments from storage file. The `selectModule` command calls `UnitOfWork.getForumThreadRepository().getThread(threadId)` and `UnitOfWork.getCommentRepository().getCommentsByThread(threadId)` to return the thread and comment list to be shown in the panel. -image::UndoRedoNewCommand2StateListDiagram.png[width="800"] +Step 8. The user executes `deleteThread tId/123` to delete/remove the thread with ID 123 from storage file. The deleteThread command calls `UnitOfWork.getForumThreadRepository().deleteThread(threadId)` and `UnitOfWork.commit()` to save the modified forum book state. + +Step 9. The user executes `deleteComment cId/123` to delete/remove the comment with ID 123 from storage file. The deleteComment command calls `UnitOfWork.getCommentRepository().deleteComment(commentId)` and `UnitOfWork.commit()` to save the modified forum book state. [NOTE] -If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`. +If the syntax of a command is wrong, the program will prompt the user to try again and show a suggested command format. +// end::curd[] -Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state. +// tag::storage[] +=== Storage -image::UndoRedoExecuteUndoStateListDiagram.png[width="800"] +==== Design Consideration -[NOTE] -If the `currentStatePointer` is at index 0, pointing to the initial address book state, then there are no previous address book states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo. +As the basis of the whole program, storage should be robust, efficient and stable at all the time. +Data consistency and multi-thread access should be specially taken care of. -The following sequence diagram shows how the undo operation works: +==== Overview -image::UndoRedoSequenceDiagram.png[width="800"] +ForumBook's storage consists of six(6) parts. -The `redo` command does the opposite -- it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state. +* User +** Stores user information like username, password, email etc. +* Announcement +** Stores announcement set by admin, multiple announcements can be saved in the storage. +* Module +** Stores module information like module name, code etc. +* ForumThread +** Stores threads posted by users +* Comment +** Stores comments under threads +* RunningId +** Used for generating auto incremented ID, each the above entity has a unique ID -[NOTE] -If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone address book states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo. +These components are stored separately in six files for performance, see below for detailed process of loading and saving. + +==== Storage Structure + +To avoid unnecessary disk IO, each part of the storage is saved in a file located in `forumData` directory. +All data manipulation must be done within an `IUnitOfWork` where developer has to commit if the data +should be persistent on disk, or rollback if the exception is thrown somewhere during the transaction. + +`IStorage` defines interface to access file systems, this handles how our program actually get/read data. +By default, we have `JsonFileStorage` which stores and reads data from local hard disk. More storage options + can be achieved by implementing this interface. eg: `FtpStorage`. + +`IEncryptor` defines interface to encrypt application data, it should be injected to `IStorage` providing a encryption/ +decryption layer just before data writes and just after data reads. By default, `JsonFileStorage` uses `SimpleEncryptor` +which is a simple 'OR' encryptor. A more secure encryption algorithm can be achieved by implementing `IEncryptor` +interface. + +`IForumBookStorage` defines interface to access data entities + +`I*Repository` defines interface to how we can manipulate different entities. +Each entity is managed by a repository, eg: `IUserRepository` + +`*Storage` is a thin wrapper for the `List` containing data objects, it keeps track of whether the underling list +has been modified so that it can save some unnecessary disk IO if nothing changed when a `commit()` is issued. + +Data are saved in encrypted Json format, the encryption algorithm is provided by `IEncryptor` + +`RunningId` does not work as the other entities do, it has its own logic to make sure IDs are not repeated. +// end::storage[] +// tag::UserManagement1[] +=== User management + +==== Current Implementation +The user management is facilitated by various commands. It extends `ForumBook` with a user management tool. Additionally, it implements the following operations: + +* `AddUserCommand` -- Add user to forum book. + +* `LoginCommand`: login to forum book. + +* `LogoutCommand`: logout from the forum book. + +* `UserDeleteCommand`: Self delete a user from the forum book. + +Given below is an example usage scenario and how the user management behaves at each step. + +----------------------------------------------------------------------------------------------------------------------------------------------------- + +Given below is an example usage scenario and how the user management can be operated by user at each step. + +Step 1. The user executes `addUser uName/UserName uPass/password` to add a new user into forum userStorage file. The addUser command calls 'unitOfWork.getUserRepository().getUserByUsername(userToAdd.getUsername())' to check if the name entered by the user is available. If there is not duplicate, User can be registered. If the registration is successful, addUser command calls `UnitOfWork.commit()` to save the modified forum book state into UserStorage. + +Step 2. The user executes `login uName/UserName uPass/password` to login to the forum. The login command calls 'unitOfWork.getUserRepository().authenticate(userName, userPassword)' to check if the login can be authorise. If success, login command calls `Context.getInstance().setCurrentUser(exist)` to create an instance for the authorised user. -Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged. +Step 3. The user executes `logout` to exit the forum or to switch user, logout command calls 'EventsCenter.getInstance().post(new UserLoginEvent("", false, false))' to close the instance created by the user. Next/ another user is able to login after a successful logout. -image::UndoRedoNewCommand3StateListDiagram.png[width="800"] +ToDo: +Step 4. The user executes `UserDeleteComment ` to remove himself/herself from the forum book. User data will be removed from the storage. -Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. We designed it this way because it no longer makes sense to redo the `add n/David ...` command. This is the behavior that most modern desktop applications follow. +----------------------------------------------------------------------------------------------------------------------------------------------------- + +// end::UserManagement1[] +// tag::adminManagement[] +=== Admin management -image::UndoRedoNewCommand4StateListDiagram.png[width="800"] +==== Current Implementation +The admin management is facilitated by various commands. It extends `ForumBook` with a admin management tool. Additionally, it implements the following operations: + +* `AnnounceCommand` -- Posts new announcement. + +* `CheckAnnouncementCommand`: Checks for latest announcement. + +* `BlockUserFromCreatingCommand`: Blocks an existing user from posting either new threads or comments. + +* `SetAdminCommand`: Sets an existing user as admin or reverts an existing admin to user. + +* `CreateModuleCommand`: Creates a module by admin. + +* `UpdateModuleCommand`: Updates an existing module by admin. + +* `DeleteModuleCommand`: Deletes an existing module by admin. + +* `AdminUpdatePasswordCommand`: Updates an existing user's password by admin. + +* `DeleteUserCommand`: Deletes an existing user by admin. + +Given below is an example usage scenario and how the admin management behaves at each step. + + +Step 1. The admin launches the application, executes `announce aTitle/Urgent! aContent/System maintenance from 3PM to 6PM.` to add the announcement to storage file. The `announce` command calls `UnitOfWork.getAnnouncementRepository.addAnnouncement(announcement)` and then `UnitOfWork.commit()`, causing a modified forum book state to be saved into `ForumBookStorage` + +image::SDAnnounce.png[width="800"] + +Step 2. The admin/user executes `checkAnnounce` to check for the latest announcement in storage file. The `checkAnnounce` calls the `UnitOfWork.getAnnouncementRepository().getLatestAnnouncement()` which returns an announcement to be shown in the message dialog. + +image::SDCheckAnnounce.png[width="800"] -The following activity diagram summarizes what happens when a user executes a new command: +Step 3. The admin executes `blockUser uName/john block/true` to block john from creating new threads or comments. The `block` calls `User.setIsBlock(true)` and then `UnitOfWork.commit()`, causing another modified forum book state to be saved into `ForumBookStorage`. -image::UndoRedoActivityDiagram.png[width="650"] +image::SDBlockUserFromCreating.png[width="800"] -==== Design Considerations +Step 4. The admin executes `setAdmin uName/john set/true` to set a certain user as admin or to revert an admin to user. The `setAdmin` calls the `User.setAdmin(true)` and then `UnitOfWork.commit()`, causing another modified forum book state to be saved into `ForumBookStorage`. -===== Aspect: How undo & redo executes +image::SDSetAdmin.png[width="800"] -* **Alternative 1 (current choice):** Saves the entire address book. -** 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). -** Cons: We must ensure that the implementation of each individual command are correct. +Step 5. The admin executes `createModule mCode/CS2113 mTitle/Software Engineering and OOP` to create the specific module. The `createModule` calls the `UnitOfWork.getModuleRepository().addModule(module)` and then `UnitOfWork.commit()`, causing another modified forum book state to be save into `ForumBookStorage`. -===== Aspect: Data structure to support the undo/redo commands +image::SDCreateModule.png[width="800"] -* **Alternative 1 (current choice):** Use a list to store the history of address book states. -** Pros: Easy for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project. -** Cons: Logic is duplicated twice. For example, when a new command is executed, we must remember to update both `HistoryManager` and `VersionedAddressBook`. -* **Alternative 2:** Use `HistoryManager` for undo/redo -** Pros: We do not need to maintain a separate list, and just reuse what is already in the codebase. -** Cons: Requires dealing with commands that have already been undone: We must remember to skip these commands. Violates Single Responsibility Principle and Separation of Concerns as `HistoryManager` now needs to do two different things. -// end::undoredo[] +Step 6. The admin executes `updateModule mId/3 mTitle/Software Eng and OOP` to update the specific module. The `updateModule` calls the `UnitOfWork.getModuleRepository().updateModule(module)` and then `UnitOfWork.commit()`, causing another modified forum book state to be save into `ForumBookStorage`. + +image::SDUpdateModule.png[width="800"] + +Step 7. The admin executes `deleteModule mCode/CS2113` to delete specific module. The `deleteModule` calls the `UnitOfWork.getModuleRepository().removeModule(module);` and then `UnitOfWork.commit()`, causing another modified forum book state to be save into `ForumBookStorage`. + +image::SDDeleteModule.png[width="800"] + +Step 8. The admin executes `updatePass uName/john uPass/098` to update the user john's password. The `updatePass` calls the `UnitOfWork.getUserRepository().updateUser(user)` and then `UnitOfWork.commit()`, causing another modified forum book state to be save into `ForumBookStorage`. + +image::SDUpdatePass.png[width="800"] + +Step 9. The admin executes `deleteUser uName/john` to delete the user john. The `deleteUser` calls the ` UnitOfWork.getUserRepository().deleteUser(userToDelete)` and then `UnitOfWork.commit()`, causing another modified forum book state to be save into `ForumBookStorage`. + +image::SDDeleteUser.png[width="800"] + +[NOTE] +If the syntax of a command is wrong, the program will prompt the user to try again and show a suggested command format. +// end::adminManagement[] // tag::dataencryption[] -=== [Proposed] Data Encryption +=== Data Encryption + +Data encryption is done in a transparent layer. -_{Explain here how the data encryption feature will be implemented}_ +All data in this application is encrypted. + +A very simple, naive, and insecure encryption is implemented in `SimpleEncryptor`, this is only for demoing the ability of +encrypting data in this application. However, a more secure algorithm can be easily added into the app by +implementing the `IEncryptor` interface and provide it into `IStorage`. // end::dataencryption[] @@ -399,10 +495,6 @@ If set, the name will be displayed near the top of the page. Setting this will add a "View on GitHub" link in the navigation bar. |_not set_ -|`site-seedu` -|Define this attribute if the project is an official SE-EDU project. -This will render the SE-EDU navigation bar at the top of the page, and add some SE-EDU-specific navigation items. -|_not set_ |=== @@ -426,7 +518,6 @@ Attributes left unset in `.adoc` files will use their *default value*, if any. This will cause the associated item in the navigation bar to be highlighted. One of: `UserGuide`, `DeveloperGuide`, ``LearningOutcomes``{asterisk}, `AboutUs`, `ContactUs` -_{asterisk} Official SE-EDU projects only_ |_not set_ |`no-site-header` @@ -484,14 +575,14 @@ We have two types of tests: . *GUI Tests* - These are tests involving the GUI. They include, .. _System Tests_ that test the entire App by simulating user actions on the GUI. These are in the `systemtests` package. -.. _Unit tests_ that test the individual components. These are in `seedu.address.ui` package. +.. _Unit tests_ that test the individual components. These are in `t13g2.forum.ui` package. . *Non-GUI Tests* - These are tests not involving the GUI. They include, .. _Unit tests_ targeting the lowest level methods/classes. + -e.g. `seedu.address.commons.StringUtilTest` +e.g. `t13g2.forum.commons.StringUtilTest` .. _Integration tests_ that are checking the integration of multiple code units (those code units are assumed to be working). + -e.g. `seedu.address.storage.StorageManagerTest` +e.g. `StorageManagerTest` .. Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together. + -e.g. `seedu.address.logic.LogicManagerTest` +e.g. `LogicManagerTest` === Troubleshooting Testing @@ -534,428 +625,469 @@ b. Require developers to download those libraries manually (this creates extra w [[GetStartedProgramming]] [appendix] -== Suggested Programming Tasks to Get Started +== Product Scope -Suggested path for new programmers: +*Target user profile*: -1. First, add small local-impact (i.e. the impact of the change does not go beyond the component) enhancements to one component at a time. Some suggestions are given in <>. +* has a need to share and read comments related to modules +* prefer desktop apps over other types +* can type fast +* prefers typing over mouse input +* is reasonably comfortable using CLI apps -2. Next, add a feature that touches multiple components to learn how to implement an end-to-end feature across all components. <> explains how to go about adding such a feature. +*Value proposition*: Read a share comments faster than a typical mouse/GUI driven app -[[GetStartedProgramming-EachComponent]] -=== Improving each component +// tag::user_Stories_And_Cases[] +[appendix] +== User Stories -Each individual exercise in this section is component-based (i.e. you would not need to modify the other components to get it to work). +Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (unlikely to have) - `*` -[discrete] -==== `Logic` component +[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 -*Scenario:* You are in charge of `logic`. During dog-fooding, your team realize that it is troublesome for the user to type the whole command in order to execute a command. Your team devise some strategies to help cut down the amount of typing necessary, and one of the suggestions was to implement aliases for the command words. Your job is to implement such aliases. +|`* * *` |student who is taking a certain module in current semester |create a new forumThread |share the exam information with others -[TIP] -Do take a look at <> before attempting to modify the `Logic` component. +|`* * *` |student who is going to take a certain module in future semesters |select that module and corresponding threads and comments under the module |learn more about the module in advance -. 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. -+ -**** -* 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. -* 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. -** 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. -**** +|`* * *` |student |list all existing modules |check what modules are available to interact with other students -[discrete] -==== `Model` component +|`* * *` |forum thread owner |update my thread title |correct my typing error in this thread title -*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. +|`* * *` |forum thread owner |delete my thread |close down the thread for further discussion under this thread -[TIP] -Do take a look at <> before attempting to modify the `Model` component. +|`* * *` |comment owner |update my comment content |correct my typing error or my thoughts in this comment -. Add a `removeTag(Tag)` method. The specified tag will be removed from everyone in the address book. -+ -**** -* 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. -** 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. -* 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)`. -** 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. -**** +|`* * *` |comment owner |delete my comment | -[discrete] -==== `Ui` component +|`* * *` |ForumBook admin |announce |show some important information to users -*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. +|`* * *` |User |add myself as a user | register and use the forum book -[TIP] -Do take a look at <> before attempting to modify the `UI` component. +|`* * *` |User |login and logout |share my comments in the forum book and exit when i want to -. 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. -+ -**Before** -+ -image::getting-started-ui-tag-before.png[width="300"] -+ -**After** -+ -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. -** 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. -** 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. -**** - -. Modify link:{repoURL}/src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java[`NewResultAvailableEvent`] such that link:{repoURL}/src/main/java/seedu/address/ui/ResultDisplay.java[`ResultDisplay`] can show a different style on error (currently it shows the same regardless of errors). -+ -**Before** -+ -image::getting-started-ui-result-before.png[width="200"] -+ -**After** -+ -image::getting-started-ui-result-after.png[width="200"] -+ -**** -* Hints -** link:{repoURL}/src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java[`NewResultAvailableEvent`] is raised by link:{repoURL}/src/main/java/seedu/address/ui/CommandBox.java[`CommandBox`] which also knows whether the result is a success or failure, and is caught by link:{repoURL}/src/main/java/seedu/address/ui/ResultDisplay.java[`ResultDisplay`] which is where we want to change the style to. -** Refer to link:{repoURL}/src/main/java/seedu/address/ui/CommandBox.java[`CommandBox`] for an example on how to display an error. -* Solution -** Modify link:{repoURL}/src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java[`NewResultAvailableEvent`] 's constructor so that users of the event can indicate whether an error has occurred. -** 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. -** 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. -+ -**Before** -+ -image::getting-started-ui-status-before.png[width="500"] -+ -**After** -+ -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. -* 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. -** 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. -** See this https://github.com/se-edu/addressbook-level4/pull/803[PR] for the full solution. -**** +|`* * *` |User |delete myself from being a user | -[discrete] -==== `Storage` component +|`* * *` |ForumBook admin |block users |prevent users from creating and updating threads and comments -*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. +|`* *` |ForumBook admin |change user password |help the user to reset the password once they forget their password -[TIP] -Do take a look at <> before attempting to modify the `Storage` component. +|`* *` |ForumBook admin |set admin |have more admins to manage the ForumBook better + +|======================================================================= + +_{More to be added}_ + +[appendix] +== Use Cases + +(For all use cases below, the *System* is the `ForumBook` and the *Actor* is the `user`, unless specified otherwise) + +[discrete] +=== Use case: List all threads under CS2113 -. Add a new method `backupAddressBook(ReadOnlyAddressBook)`, so that the address book can be saved in a fixed temporary location. +*MSS* + +1. User requests to list all modules +2. ForumBook shows a list of modules +3. User requests to list all threads under module CS2113 +4. ForumBook shows a list of threads under module CS2113 + -**** -* 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. -* Solution -** See this https://github.com/se-edu/addressbook-level4/pull/594[PR] for the full solution. -**** +Use case ends. -[[GetStartedProgramming-RemarkCommand]] -=== Creating a new command: `remark` +*Extensions* -By creating this command, you will get a chance to learn how to implement a feature end-to-end, touching all major components of the app. +[none] +* 2a. The list is empty. ++ +Use case ends. -*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. +* 3a. The given module code is invalid. ++ +[none] +** 3a1. ForumBook shows an error message. ++ +Use case ends. -==== Description -Edits the remark for a person specified in the `INDEX`. + -Format: `remark INDEX r/[REMARK]` +=== Use case: Create new thread under CS2113 -Examples: +*MSS* -* `remark 1 r/Likes to drink coffee.` + -Edits the remark for the first person to `Likes to drink coffee.` -* `remark 1 r/` + -Removes the remark for the first person. +1. User requests to list all modules +2. ForumBook shows a list of modules +3. User requests to create new thread under module CS2113 +4. ForumBook adds the new thread and shows a success message ++ +Use case ends. -==== Step-by-step Instructions +*Extensions* -===== [Step 1] Logic: Teach the app to accept 'remark' which does nothing -Let's start by teaching the application how to parse a `remark` command. We will add the logic of `remark` later. +[none] +* 2a. The list is empty. ++ +[none] +** 2a1. ForumBook shows empty list of module ++ +Use case ends. -**Main:** +* 3a. The given module code is invalid. ++ +[none] +** 3a1. ForumBook shows an error message. ++ +Use case ends. -. Add a `RemarkCommand` that extends link:{repoURL}/src/main/java/seedu/address/logic/commands/Command.java[`Command`]. 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`. +=== Use case: Create new comment -**Tests:** +*MSS* -. Add `RemarkCommandTest` that tests that `execute()` 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`. +1. User requests to list all modules +2. ForumBook shows a list of modules +3. User requests to create new comment +4. ForumBook adds the new comment and shows a success message ++ +Use case ends. -===== [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.` +*Extensions* -**Main:** +[none] +* 2a. The list is empty. ++ +[none] +** 2a1. ForumBook shows empty list of module ++ +Use case ends. -. 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`. +* 3a. The given thread id is invalid. ++ +[none] +** 3a1. ForumBook shows an error message. ++ +Use case ends. -**Tests:** +=== Use case: Delete thread and comment -. 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. +*MSS* -===== [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. +1. User requests to delete a thread +2. ForumBook deletes the thread and shows success message +3. User requests to delete a comment +4. ForumBook deletes the comment and shows success message ++ +Use case ends. -**Main:** +*Extensions* -. 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. +[none] +* 2a. current user is not the thread owner. ++ +[none] +** 2a1. ForumBook shows error message ++ +Use case ends. -**Tests:** +* 3a. current user is not the comment owner. ++ +[none] +** 3a1. ForumBook shows an error message. ++ +Use case ends. -. Modify link:{repoURL}/src/test/java/guitests/guihandles/PersonCardHandle.java[`PersonCardHandle`] so that future tests can read the contents of the remark label. +=== Use case: Update thread and comment -===== [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. +*MSS* -**Main:** +1. User requests to update a thread +2. ForumBook updates the thread and shows success message +3. User requests to update a comment +4. ForumBook updates the comment and shows success message ++ +Use case ends. -. 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). -. Modify `RemarkCommand` to now take in a `Remark` instead of a `String`. +*Extensions* -**Tests:** +[none] +* 2a. current user is not the thread owner. ++ +[none] +** 2a1. ForumBook shows error message ++ +Use case ends. -. Add test for `Remark`, to test the `Remark#equals()` method. +* 3a. current user is not the comment owner. ++ +[none] +** 3a1. ForumBook shows an error message. ++ +Use case ends. -===== [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`]. +_{More to be added}_ +// end::user_Stories_And_Cases[] -**Main:** +// tag::others[] +[appendix] +== Non Functional Requirements -. 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.) +. Should work on any <> as long as it has Java `9` or higher installed. +. Should be able to hold up to 1000 threads with comments 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. -===== [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. +[appendix] +== Glossary -**Main:** +[[mainstream-os]] Mainstream OS:: +Windows, Linux, Unix, OS-X -. Add a new Xml field for `Remark`. -**Tests:** +[appendix] +== Instructions for Manual Testing -. Fix `invalidAndValidPersonAddressBook.xml`, `typicalPersonsAddressBook.xml`, `validAddressBook.xml` etc., such that the XML tests will not fail due to a missing `` element. +Given below are instructions to test the app manually. -===== [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`]. +[NOTE] +These instructions only provide a starting point for testers to work on; testers are expected to do more _exploratory_ testing. + +=== Launch and Shutdown -**Tests:** +. Initial launch -. 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. -. Try and use the method on any sample `Person` in link:{repoURL}/src/test/java/seedu/address/testutil/TypicalPersons.java[`TypicalPersons`]. +.. Download the jar file and copy into an empty folder +.. Double-click the jar file + + Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum. -===== [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. +. Getting sample data file -**Main:** +.. Download [https://github.com/CS2113-AY1819S1-T13-2/main/blob/master/sampleData/forumData.zip[sample forumData zip folder]] and unzip +.. Replace the default data folder generated by the application with the forumData folder you have downloaded. +.. On relaunching the application, new data should be loaded. -. Modify link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`]'s constructor to bind the `Remark` field to the `Person` 's remark. +. Saving window preferences -**Tests:** +.. Resize the window to an optimum size. Move the window to a different location. Close the window. +.. Re-launch the app by double-clicking the jar file. + + Expected: The most recent window size and location is retained. -. Modify link:{repoURL}/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java[`GuiTestAssert#assertCardDisplaysPerson(...)`] so that it will compare the now-functioning remark label. +// tag::UserManagement2[] +=== Registering and logging in -===== [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. +. Registering a new user -**Main:** +.. Prerequisites: username must not be registered before. +.. Test case: `addUser uName/john uPass/123` + Expected: the user `john` will be added to the UserStorage if there is no duplicate in the UserStorage. -. Replace the logic in `RemarkCommand#execute()` (that currently just throws an `Exception`), with the actual logic to modify the remarks of a person. +. Loggin in -**Tests:** +.. Test case: `login uName/abcd uPass/123` + Expected: Log in with a random username and password that has not been registered. An error message will be shown in the result display panel. +.. Test case: `login uName/john uPass/234` + Expected: Log in with a registered username and a wrong password. An error message will be shown in the result display panel. +.. Test case: `login uName/john uPass/123` + Expected: Log in with a registered username and correct password, a success message will be shown in the result display panel. -. Update `RemarkCommandTest` to test that the `execute()` logic works. +// end::UserManagement2[] +=== Announcing new announcement -==== Full Solution +. Announcing a new announcement by admin. -See this https://github.com/se-edu/addressbook-level4/pull/599[PR] for the step-by-step solution. +.. Prerequisites: Current user must login as an admin. +.. Test case: `announce aTitle/Urgent! aContent/System Maintenance from 4pm to 5pm.` + + Expected: Announcement will show up in a pop up window as well as the result display panel. +.. Test case: `announce aTitle/ aContent/` + + Expected: No announcement will be posted. Error details shown in the result display panel. -[appendix] -== Product Scope +=== Checking new announcement -*Target user profile*: +. Checking for latest announcement. -* has a need to manage a significant number of contacts -* prefer desktop apps over other types -* can type fast -* prefers typing over mouse input -* is reasonably comfortable using CLI apps +.. Prerequisites: Users have to login in order to do `checkAnnounce` +.. Test case: `checkAnnounce` + + Expected: The latest announcement will show up in a pop up window and in the result display panel. However, if the latest announcement is null, an error message "There is no announcement at the moment" will be shown in the result display panel. -*Value proposition*: manage contacts faster than a typical mouse/GUI driven app +=== Blocking user from posting -[appendix] -== User Stories +. Blocking a given user by admin. -Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (unlikely to have) - `*` +.. Prerequisites: Current user must login as an admin. The given user should not be an admin and should be in the UserStorage. +.. Test case: `blockUser uName/john block/true` + + Expected: The given user will be blocked and a success message will be shown in the result display panel. +.. Test case: `blockUser uName/abcd block/true` + + Expected: Since the given user has not been added to the UserStorage, an error message will be shown in the result display panel. -[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 +=== Setting a user as admin or setting an admin as user +  +. Setting a user as admin or revert an admin to a user. -|`* * *` |user |add a new person | +.. Prerequisites: Current user must login as an admin. Admin is unable to set/revert himself/herself to admin/user. The given user must not been blocked and must be in UserStorage. +.. Test case: `setAdmin uName/john set/true` + + Expected: The given user will be set to an admin and the success message will be shown in the result display panel. +.. Test case: `setAdmin uName/abcd set/true` + + Expected: Since the given user has not been added to the UserStorage, an error message will be shown in the result display panel. -|`* * *` |user |delete a person |remove entries that I no longer need +=== Creating a module -|`* * *` |user |find a person by name |locate details of persons without having to go through the entire list +. Creating a module by admin. -|`* *` |user |hide <> by default |minimize chance of someone else seeing them by accident +.. Prerequisites: Current user must login as an admin. The module must not be in the ModuleStorage. +.. Test case: `createModule mCode/CS2113 mContent/Software Engineering and OOP` + + Expected: A new module will be added to the ModuleStorage, and a success message will be shown in the result display panel. +.. Test case: `createModule mCode/ mTitle/` + + Expected: No module will be added. Error details shown in the result display panel. -|`*` |user with many persons in the address book |sort persons by name |locate a person easily -|======================================================================= +=== Creating a thread -_{More to be added}_ +. Creating a thread under certain module by user or admin. -[appendix] -== Use Cases +.. Prerequisites: User must login to proceed. User should not be blocked by admin. +.. Test case: `createThread mCode/CS2113 tTitle/Exam Information cContent/All the best for the final guys` + + Expected: A new thread will be added to the ForumThreadStorage, and a success message will be shown in the result display panel. +.. Test case: `createThread mCode/ tTitle/ cContent/` + + Expected: No module will be added. Error details shown in the result display panel. -(For all use cases below, the *System* is the `AddressBook` and the *Actor* is the `user`, unless specified otherwise) +=== Creating a comment -[discrete] -=== Use case: Delete person +. Creating a comment under certain forum thread by user or admin. -*MSS* +.. Prerequisites: User must login to proceed. User should not be blocked by admin. +.. Test case: `createComment tId/1 cContent/This is a new comment` + + Expected: A new thread will be added to the CommentStorage, and a success message will be shown in the result display panel. +.. Test case: `createComment tId/ cContent/` + + Expected: No comment will be added. Error details shown in the result display panel. -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 -+ -Use case ends. +=== Updating a thread title -*Extensions* +. Updating the title of a forum thread by thread creator or admin. -[none] -* 2a. The list is empty. -+ -Use case ends. +.. Prerequisites: User must login to proceed. User is the owner/creator of the forum thread. +.. Test case: (If thread ID 123 is under current module) + `updateThread tId/123 tTitle/This is a new title` + + Expected: The new thread title will be updated in the ForumThreadStorage, and a success message will be shown in the result display panel. +.. Test case: (If thread ID 123 does not exist in the forum book) + `updateThread tId/123 tTitle/This is a new title` + + Expected: No thread title will be updated. Error details of invalid thread id will be shown in the result display panel. +.. Test case: (If thread ID 123 is not under current module) + `updateThread tId/123 tTitle/This is a new title` + + Expected: No thread title will be updated. Error details of entity is not under scope will be shown in the result display panel. +.. Test case: `updateThread tId/ tTitle/` + + Expected: No thread title will be updated. Error details shown in the result display panel. -* 3a. The given index is invalid. -+ -[none] -** 3a1. AddressBook shows an error message. -+ -Use case resumes at step 2. +=== Updating a comment content -_{More to be added}_ +. Updating the content of a comment by comment creator or admin. -[appendix] -== Non Functional Requirements +.. Prerequisites: User must login to proceed. User is the owner/creator of the comment. +.. Test case: (If comment ID 123 is under current forum thread) + `updateThread cId/123 cContent/This is a new content` + + Expected: The new comment content will be updated in the CommentStorage, and a success message will be shown in the result display panel. +.. Test case: (If comment ID 123 does not exist in the forum book) + `updateThread cId/123 cContent/This is a new content` + + Expected: No comment content will be updated. Error details of invalid comment id will be shown in the result display panel. +.. Test case: (If comment ID 123 is not under current forum thread) + `updateThread cId/123 cContent/This is a new content` + + Expected: No comment content will be updated. Error details of entity is not under scope will be shown in the result display panel. +.. Test case: `updateThread cId/ cContent/` + + Expected: No comment content will be updated. Error details shown in the result display panel. -. Should work on any <> as long as it has Java `9` or higher installed. -. Should be able to hold up to 1000 persons 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. +=== Deleting a thread -_{More to be added}_ +. Deleting a forum thread by thread creator or admin. -[appendix] -== Glossary +.. Prerequisites: User must login to proceed. User is the owner/creator of the forum thread. +.. Test case: (If thread ID 123 is under current module) + `deleteThread tId/123` + + Expected: The new thread title will be deleted in the ForumThreadStorage, and a success message will be shown in the result display panel. +.. Test case: (If thread ID 123 does not exist in the forum book) + `deleteThread tId/123` + + Expected: No thread title will be deleted. Error details of invalid thread id will be shown in the result display panel. +.. Test case: (If thread ID 123 is not under current module) + `deleteThread tId/123` + + Expected: No thread title will be deleted. Error details of entity is not under scope will be shown in the result display panel. +.. Test case: `deleteThread tId/` + + Expected: No thread title will be deleted. Error details shown in the result display panel. -[[mainstream-os]] Mainstream OS:: -Windows, Linux, Unix, OS-X +=== Deleting a comment -[[private-contact-detail]] Private contact detail:: -A contact detail that is not meant to be shared with others +. Deleting a comment by comment creator or admin. -[appendix] -== Product Survey +.. Prerequisites: User must login to proceed. User is the owner/creator of the comment. +.. Test case: (If comment ID 123 is under current forum thread) + `deleteComment cId/123` + + Expected: The new comment content will be deleted in the CommentStorage, and a success message will be shown in the result display panel. +.. Test case: (If comment ID 123 does not exist in the forum book) + `deleteComment cId/123` + + Expected: No comment content will be deleted. Error details of invalid comment id will be shown in the result display panel. +.. Test case: (If comment ID 123 is not under current forum thread) + `deleteComment cId/123` + + Expected: No comment content will be deleted. Error details of entity is not under scope will be shown in the result display panel. +.. Test case: `deleteComment cId/` + + Expected: No comment content will be deleted. Error details shown in the result display panel. -*Product Name* +=== Listing all modules -Author: ... +. Listing all the modules in the forun book by user or admin. -Pros: +.. Prerequisites: User must login to proceed. +.. Test case: `listModule` + + Expected: A list of modules in the ModuleStorage will be shown in the result display panel. -* ... -* ... +=== Selecting a module to list all threads -Cons: +. Listing all the forum threads under certain module in the forun book by user or admin. -* ... -* ... +.. Prerequisites: User must login to proceed. The module code entered by user should exist in the ModuleStorage. +.. Test case: `selectModule mCode/CS2113` + + Expected: A list of forum threads under module CS2113 in the ForumThreadStorage will be shown in the result display panel. +.. Test case: `selectModule mCode/` + + Expected: No forum thread will be listed out. Error details shown in the result display panel. -[appendix] -== Instructions for Manual Testing +=== Selecting a thread to list all comments -Given below are instructions to test the app manually. +. Listing all the comments under certain forum thread in the forun book by user or admin. -[NOTE] -These instructions only provide a starting point for testers to work on; testers are expected to do more _exploratory_ testing. +.. Prerequisites: User must login to proceed. The thread Id entered by user should exist in the ForumThreadStorage. +.. Test case: `selectThread tId/123` + + Expected: A list of comments under thread ID 123 in the ForumThreadStorage will be shown in the result display panel. +.. Test case: `selectModule tId/` + + Expected: No comment will be listed out. Error details shown in the result display panel. -=== Launch and Shutdown +=== Updating a module -. Initial launch +. Updating a module by admin. -.. Download the jar file and copy into an empty folder -.. Double-click the jar file + - Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum. +.. Prerequisites: Current user must login as an admin. The module must be in ModuleStorage. +.. Test case: `updateModule mId/3 mCode/CS1223` + + Expected: The module `CS2113` will be updated to take the module code `CS1223`, and an success message will be shown in the result display panel. +.. Test case: `updateModule mCode/CS1223` + + Expected: Since the module id was not specified, The module will not be updated. This command should raise an error and show in the result display panel. -. Saving window preferences +=== Deleting a module -.. Resize the window to an optimum size. Move the window to a different location. Close the window. -.. Re-launch the app by double-clicking the jar file. + - Expected: The most recent window size and location is retained. +. Deleting a module by admin. -_{ more test cases ... }_ +.. Prerequisites: Current user must login as an admin. The module must be in ModuleStorage. +.. Test case: `deleteModule mCode/CS2113` + + Expected: The module `CS2113` will be deleted from the ModuleStorage, and an success message will be shown in the result display panel. +.. Test case: `deleteModule mCode/CS2113` + + Expected: Since the module `CS2113` has been deleted. This command should raise an error and show in the result display panel. -=== Deleting a person +=== Updating password -. Deleting a person while all persons are listed +. Updating a given user's password by admin. -.. Prerequisites: List all persons using the `list` command. Multiple persons 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. -.. Other incorrect delete commands to try: `delete`, `delete x` (where x is larger than the list size) _{give more}_ + - Expected: Similar to previous. +.. Prerequisites: Current user must login as an admin. The given user must be in UserStorage. +.. Test case: `updatePass uName/john uPass/456` + + Expected: The user `john`'s password will be updated to `456` +.. Test case: `updatePass uName/abcd uPass/123` + + Expected: Since the given user `abcd` has not been added to the UserStorage, an error message will be shown in the result display panel. -_{ more test cases ... }_ +=== Deleting a user(Admin) -=== Saving data +. Deleting a given user by admin. +.. Prerequisites: Current user must login as an admin. The given user must be in the UserStorage. +.. Test case: `deleteUser uName/john` + Expected: The user `john` will be deleted from the UserStorage and a success message will be shown in the result display panel. +.. Test case: `deleteUser uName/abcd` + Expected: Since the given user `abcd` does not exist in the UserStorage, an error message will be shown in the result display panel. -. Dealing with missing/corrupted data files +// tag::UserManagement3[] +=== Deleting a user(User) -.. _{explain how to simulate a missing/corrupted file and the expected behavior}_ +. Self Deleting a user. +.. Prerequisites: User who is interested in removing himself from the forum must login to his account. The given user must be in the UserStorage. +.. Test case: `deleteMe` -user logged in + Expected Success: The current user will be deleted from the UserStorage and a success message will be shown in the result display panel. +.. Test case: `deleteMe` -user not logged in + Expected Fail: Since the given user is not logged in, an error message will be shown in the result display panel. +// end::UserManagement3[].. _{explain how to simulate a missing/corrupted file and the expected behavior}_ +// end::others[] -_{ more test cases ... }_ diff --git a/docs/LearningOutcomes.adoc b/docs/LearningOutcomes.adoc index 83cda0927226..300148a0b13d 100644 --- a/docs/LearningOutcomes.adoc +++ b/docs/LearningOutcomes.adoc @@ -190,7 +190,6 @@ public void execute_invalidCommandFormat_throwsParseException() { == Write System Tests `[LO-SystemTesting]` -Note how tests below `src/test/java/systemtests` package (e.g link:{repoURL}/src/test/java/systemtests/AddCommandSystemTest.java[`AddCommandSystemTest.java`]) are system tests because they test the entire system end-to-end. *Resources* diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 7e0070e12f49..07c0eef5807d 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 4 - User Guide += ForumBook - User Guide :site-section: UserGuide :toc: :toc-title: @@ -12,249 +12,378 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level4 +:repoURL:https://github.com/CS2113-AY1819S1-T13-2/main/ -By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT` +By: `Team CS2113-AY1819S1-T13-2` Since: `Aug 2018` 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! +ForumBook (FB) is for those who *prefer to use a desktop app for module ForumBook*. More importantly, FB 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, FB can be a great place to learn and share comments regarding modules offered in NUS.This can be done faster than traditional GUI apps. Can't wait? Jump to the <> to get started. Enjoy! == Quick Start . Ensure you have Java version `9` or later installed in your Computer. -. 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 `ForumBook.jar` link:{repoURL}/releases[here]. +. Copy the file to the folder you want to use as the home folder for your Forum Book. . Double-click the file to start the app. The GUI should appear in a few seconds. + image::Ui.png[width="790"] + . Type the command in the command box and press kbd:[Enter] to execute it. + 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. -* **`delete`**`3` : deletes the 3rd contact shown in the current list -* *`exit`* : exits the app - +. There are two types of users in ForumBook: **user** and **admin** +* Without logging in, you could: + +1. Register using `addUser uName/john uPass/123` +2. Login using `login uName/john uPass/123` +* As a user, you could: + +1. Show help using `help` +2. List all the modules using `listModule` +3. Select a module to check the threads under that module using `selectModule mCode/CS2113` +4. Select a thread among the threads listed using `selectThread tId/1` +5. Create a comment under a thread using `createComment tId/1 cContent/This is a new comment` +6. Update a comment created by you using `updateComment cId/1 cContent/This is a new comment` +7. Delete a comment created by you using `deleteComment cId/1` +8. Create a thread under a module using `createThread mCode/CS2113 tTitle/About exams? cContent/Is there any exam?` +9. Update a thread created by you using `updateThread tId/1 tTitle/Is there any midterm?` +10. Delete a thread created by you using `deleteThread tId/1` +11. Check for latest announcement using `checkAnnounce` +12. Delete himself from the ForumBook using 'deleteMe' +13. Logout from ForumBook using `logout` +14. Exits the app using `exit` + +* As an admin, you could do anything that an ordinary user could do and the following: + +1. Post new announcement using `announce aTitle/Urgent! aContent/System maintenance from 3pm to 5pm` +2. Update a given user's password using `updatePass uName/john uPass/456` +3. Block a given user using `blockUser uName/john block/true` +4. Create a new module using `createModule mCode/MA1508E mTitle/Linear Algebra` +5. Delete a module using `deleteModule mCode/MA1508E` +6. Update a comment created by other user using `updateComment cId/1 cContent/This is a new comment by admin` +7. Delete a comment created by other user using `deleteComment cId/1` +8. Update a thread created by other user using `updateThread tId/1 tTitle/This is updated by admin` +9. Delete a thread created by other user using `deleteThread tId/1` +10. Set a user as an admin using `setAdmin uName/john set/true` +11. Delete a given user using `deleteUser uName/john` + +. Note that we populate ForumBook with default data: +1. Default admin: uName/admin uPass/admin +2. Default user: uName/user1 uPass/user1 +3. Default module: mCode/CS2113 mTitle/Software Eng +4. Default thread under CS2113: tTitle/Hey How is CS2113 +5. Default content under that thread: cContent/I am taking this module next sem, how is it? +6. Default announcement: aTitle/Welcome! aContent/Welcome to ForumBook . Refer to <> for details of each command. -[[Features]] == Features ==== *Command Format* -* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. -* Items in square brackets are optional e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`. -* Items with `…`​ after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. -* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. +* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `addUser uName/USER_NAME uPass/USER_PASSWORD`, `USER_NAME` and `USER_PASSWORD` are parameters supplied by user in `addUser uName/john uPass/123`. +* Parameters can be in any order e.g. if the command specifies `mCode/CS2113 tTitle/Is there mid-terms?`, `tTitle/Is there mid-terms? mCode/CS2113` is also acceptable. +* Command keywords are case sensitive. e.g. `adduser`, `DELETECOMMENT` is not recognised. ==== === Viewing help : `help` Format: `help` +// tag::UserManagement1[] +=== Register a new User : `addUser` + +Register a New User to the Forum. User Name is unique and case sensitive. + +Format: `addUser uName/USER NAME uPass/USER PASSWORD` + +Examples: + +* `addUser uName/user1 uPass/user1` +**** +* User Name and password is unique and case sensitive. +**** + +=== logIn to the forum : `login` + +Login to the forum with a registered user name and password. + +Format: `login uName/USER NAME uPass/USER PASSWORD` + +Examples: + +* `login uName/user1 uPass/user1` +// end::UserManagement1[] + +// tag::curd[] +=== Listing all the modules : `listModule` + +List all the existing modules in the forum book. + +Format: `listModule` + +Examples: + +* `listModule` + +=== Listing all the forumThreads : `selectModule` + +List all the existing forumThreads under a specific module that exists as well. + +Format: `selectModule mCode/MODULE CODE` + +Examples: + +* `selectModule mCode/CS2113` + +=== Listing all the comments : `selectThread` -=== Adding a person: `add` +List all the existing comments under a specific forumThread that exists as well. + +Format: `selectThread tId/THREAD ID` -Adds a person to the address book + -Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +Examples: + +* `selectThread tId/123` -[TIP] -A person can have any number of tags (including 0) +=== Creating a new forumThread : `createThread` + +Create a new forumThread under a specific module that exists + +Format: `createThread mCode/MODULE CODE tTitle/THREAD TITLE cContent/COMMENT CONTENT` 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` +* `createThread mCode/CS2113 tTitle/Exam Information cContent/All the best for the final guys` + +=== Creating a new comment : `createComment` -=== Listing all persons : `list` +Create a new comment under a specific forumThread that exists. + +Format: `createComment tId/THREAD ID cContent/COMMENT CONTENT` -Shows a list of all persons in the address book. + -Format: `list` +Examples: + +* `createComment tId/1 cContent/This is a new comment` -=== Editing a person : `edit` +=== Updating a forumThread title : `updateThread` -Edits an existing person in the address book. + -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +Update an existing forumThread title in the forum book. + +Format: `updateThread tId/THREAD ID tTitle/NEW THREAD TITLE` **** -* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. 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. +* Only admin and the forumThread creator(unblocked) are allowed to update the title. **** 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. -* `edit 2 n/Betsy Crower t/` + -Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. +* `updateThread tId/123 tTitle/This is a new title` -=== Locating persons by name: `find` +=== Updating a comment content : `updateComment` -Finds persons whose names contain any of the given keywords. + -Format: `find KEYWORD [MORE_KEYWORDS]` +Update an existing comment title in the forum book. + +Format: `updateComment cId/COMMENT ID cContent/NEW COMMENT CONTENT` **** -* The search is case insensitive. e.g `hans` will match `Hans` -* 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` +* Only admin and the comment creator(unblocked) are allowed to update the content. **** Examples: -* `find John` + -Returns `john` and `John Doe` -* `find Betsy Tim John` + -Returns any person having names `Betsy`, `Tim`, or `John` +* `updateComment tId/123 tTitle/This is a new title` -=== Deleting a person : `delete` +=== deleting a forumThread : `deleteThread` -Deletes the specified person from the address book. + -Format: `delete INDEX` +Delete an existing forumThread in the forum book. + +Format: `deleteThread tId/THREAD ID` **** -* Deletes the person at the specified `INDEX`. -* The index refers to the index number shown in the displayed person list. -* The index *must be a positive integer* 1, 2, 3, ... +* Only admin and the forumThread creator are allowed to delete the forumThread. **** Examples: -* `list` + -`delete 2` + -Deletes the 2nd person in the address book. -* `find Betsy` + -`delete 1` + -Deletes the 1st person in the results of the `find` command. +* `deleteThread tId/1` -=== Selecting a person : `select` +=== deleting a comment : `deleteComment` -Selects the person identified by the index number used in the displayed person list. + -Format: `select INDEX` +Delete an existing comment in the forum book. + +Format: `deleteComment cId/COMMENT ID` **** -* Selects the person and loads the Google search page the person at the specified `INDEX`. -* The index refers to the index number shown in the displayed person list. -* The index *must be a positive integer* `1, 2, 3, ...` +* Only admin and the comment creator are allowed to delete the comment. **** Examples: -* `list` + -`select 2` + -Selects the 2nd person in the address book. -* `find Betsy` + -`select 1` + -Selects the 1st person in the results of the `find` command. +* `deleteComment cId/1` +// end::curd[] -=== Listing entered commands : `history` +// tag::adminManagement[] +=== Announcing new command : `announce` -Lists all the commands that you have entered in reverse chronological order. + -Format: `history` +Announce the new announcement created by admin. The first character of announcement title and content must not be a whitespace. + +Format: `announce aTitle/ANNOUNCEMENT_TITLE aContent/ANNOUNCEMENT_CONTENT` -[NOTE] -==== -Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and next input respectively in the command box. -==== +Example: -// tag::undoredo[] -=== Undoing previous command : `undo` +* `announce aTitle/Urgent! aContent/System maintenance from 4pm to 5pm.` -Restores the address book to the state before the previous _undoable_ command was executed. + -Format: `undo` +=== Checking for the latest announcement : `checkAnnounce` -[NOTE] -==== -Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`). -==== +Check for the latest announcement. + +Format: `checkAnnounce` + +=== Blocking a user from creating thread or comment : `blockUser` + +Block a specific user that match the given argument by admin. User to be blocked must not be an admin. `block` only takes `true` or `false` + +Format: `blockUser uName/USER_NAME block/BLOCK_OR_UNBLOCK` + +Example: + +* `blockUser uName/john block/true` + +* `blockUser uName/john block/false` + +=== Setting a user as admin or revert an admin to user : `setAdmin` + +Set a user as an admin or revert an admin to user. The user to set as admin must not been blocked. `set` only takes `true` or `false` + +Format: `setAdmin uName/USER_NAME set/SET_OR_REVERT` Examples: -* `delete 1` + -`list` + -`undo` (reverses the `delete 1` command) + +* `setAdmin uName/john set/true` + +* `setAdmin uName/john set/false` + +=== Creating a new module : `createModule` + +Create a new module by admin. Module code should follow (2 or 3 capital letters) + (4 numbers) + (0 or 1 capital letter) and it should not be blank. E.g. MA1580E, CS2113 or USP1000A, USP1000. Module title should only contain letters and spaces.+ +Format: `createModule mCode/MODULE_CODE mTitle/MODULE_TITLE` -* `select 1` + -`list` + -`undo` + -The `undo` command fails as there are no undoable commands executed previously. +Example: -* `delete 1` + -`clear` + -`undo` (reverses the `clear` command) + -`undo` (reverses the `delete 1` command) + +* `createModule mCode/CS2113 mTitle/Software Engineering and OOP` -=== Redoing the previously undone command : `redo` +=== Updating a module : `updateModule` -Reverses the most recent `undo` command. + -Format: `redo` +Update an existing module by admin. Note that either one of mCode and mTitle has to be specified + +Format: `updateModule mId/MODULE_ID [mCode/MODULE_CODE] [mTitle/MODULE_TITLE]` Examples: -* `delete 1` + -`undo` (reverses the `delete 1` command) + -`redo` (reapplies the `delete 1` command) + +* `updateModule mId/3 mCode/CS1221` +* `updateModule mId/3 mTitle/Random CS module` +* `updateModule mId/3 mCode/CS1221 mTitle/Random CS module` + +=== Deleting a module : `deleteModule` + +Delete an existing module by admin. + +Format: `deleteModule mCode/MODULE_CODE` + +Example: + +* `deleteModule mCode/CS2113` -* `delete 1` + -`redo` + -The `redo` command fails as there are no `undo` commands executed previously. +=== Updating password : `updatePass` -* `delete 1` + -`clear` + -`undo` (reverses the `clear` command) + -`undo` (reverses the `delete 1` command) + -`redo` (reapplies the `delete 1` command) + -`redo` (reapplies the `clear` command) + -// end::undoredo[] +Update the given user's password by admin. + +Format: `updatePass uName/USER_NAME uPass/USER_PASSWORD` -=== Clearing all entries : `clear` +Example: -Clears all entries from the address book. + -Format: `clear` +* `updatePass uName/john uPass/098` +=== Delete a user(Admin) : `deleteUser` + +Delete a given user by admin. + +Format: `deleteUser uName/USER_NAME` + +Example: + +* `deleteUser uName/john` +// end::adminManagement[] + +// tag::UserManagement2[] +=== Delete a user(User) : `deleteMe` + +User deletes himself from the ForumBook. + +Format: `deleteMe` + +Example: + +* `deleteMe` + +=== Logout from the forum : `logout` + +Logout from the Forum. + +Format: `logout` +// end::UserManagement2[] === Exiting the program : `exit` Exits the program. + Format: `exit` + === Saving the data -Address book data are saved in the hard disk automatically after any command that changes the data. + +Forum book data are saved in the hard disk automatically after any command that changes the data. + There is no need to save manually. -// tag::dataencryption[] -=== Encrypting data files `[coming in v2.0]` +// tag::encryption[] +=== Security -_{explain how the user can enable/disable data encryption}_ -// end::dataencryption[] +All data including user credential and application data are encrypted on your disk. You don't need to worry +about other people who have access to your computer steal your information. +// end::encryption[] + +// tag::faq[] == 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 Forum Book folder.` -== Command Summary +*Q*: What if I forget my password? + +*A*: Ask an admin to help, he/she has the privilege to reset your password. -* *Add* `add n/NAME 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` -* *Clear* : `clear` -* *Delete* : `delete INDEX` + -e.g. `delete 3` -* *Edit* : `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]...` + -e.g. `edit 2 n/James Lee e/jameslee@example.com` -* *Find* : `find KEYWORD [MORE_KEYWORDS]` + -e.g. `find James Jake` -* *List* : `list` -* *Help* : `help` -* *Select* : `select INDEX` + -e.g.`select 2` -* *History* : `history` -* *Undo* : `undo` -* *Redo* : `redo` +*Q*: How do I uninstall this application? + +*A*: Just delete the folder containing this application, it does not touch any other part of your computer. + +*Q*: What if I want change my password? + +*A*: Ask an admin to help, he/she has the privilege to change your password. Alternatively, User can delete their account and re-create with your desired Password. +// end::faq[] + +== Command Summary +* *Help*: `help` +* *RegisterUser* : `addUser uName/USER NAME uPass/USER PASSWORD` + +e.g `addUser uName/MyName uPass/password` +* *Login* : `login uName/USER NAME uPass/USER PASSWORD` + +e.g `login uName/MyName uPass/password` +* *createThread* : `createThread mCode/MODULE CODE tTitle/THREAD TITLE cContent/COMMENT CONTENT` + +e.g `createThread mCode/CS2113 tTitle/Exam Information cContent/All the best for the final guys` +* *createComment* : `createComment tId/THREAD ID cContent/COMMENT CONTENT` + +e.g `createComment tId/1 cContent/This is a new comment` +* *updateThread* : `updateThread tId/THREAD ID tTitle/NEW THREAD TITLE` + +e.g `updateThread tId/123 tTitle/This is a new title` +* *updateComment* : `updateComment cId/COMMENT ID cContent/NEW COMMENT CONTENT` + +e.g `updateComment tId/123 tTitle/This is a new title` +* *deleteThread* : `deleteThread tId/THREAD ID` + +e.g `deleteThread tId/1` +* *deleteComment* : `deleteComment cId/COMMENT ID` + +e.g `deleteComment cId/1` +* *listModule*: `listModule` +* *selectModule* : `selectModule mCode/MODULE CODE` + +e.g `selectModule mCode/CS2113` +* *selectThread* : `selectThread tId/THREAD ID` + +e.g `selectThread tId/123` +* *Announce* : `announce aTitle/ANNOUNCEMENT_TITLE aContent/ANNOUNCEMENT_CONTENT` + +e.g `announce aTitle/Urgent! aContent/System maintenance from 4pm to 5pm.` +* *CheckAnnounce* : `checkAnnounce` +* *BlockUser* : `blockUser uName/USER_NAME block/BLOCK_UNBLOCK` + +e.g `blockUser uName/john block/false` +* *SetAdmin* : `setAdmin uName/USER_NAME set/SET_OR_REVERT` + +e.g `setAdmin uName/john set/true` +* *CreateModule* : `createModule mCode/MODULE_CODE mTitle/MODULE_TITLE` + +e.g `createModule mCode/CS2113 mTitle/Software Engineering and OOP` +* *UpdateModule* : `updateModule mId/MODULE_ID [mCode/MODULE_CODE] [mTitle/MODULE_TITLE]` + +e.g `updateModule mId/3 mCode/CS1221` + +e.g `updateModule mId/3 mTitle/Random CS module` + +e.g `updateModule mId/3 mCode/CS1221 mTitle/Random CS module` +* *DeleteModule* : `deleteModule mCode/MODULE_CODE` + +e.g `deleteModule mCode/CS2113` +* *UpdatePass* : `updatePass uName/USER_NAME uPass/USER_PASSWORD` + +e.g `updatePass uName/john uPass/098` +* *DeleteUser(Admin)* : `deleteUser uName/USER_NAME` + +e.g `deleteUser uName/john` +* *DeleteUser(User)* : `deleteMe` +* *Logout* : `logout` diff --git a/docs/diagrams/HighLevelSequenceDiagrams.pptx b/docs/diagrams/HighLevelSequenceDiagrams.pptx index 38332090a79a..7cc75a1aaadc 100644 Binary files a/docs/diagrams/HighLevelSequenceDiagrams.pptx and b/docs/diagrams/HighLevelSequenceDiagrams.pptx differ diff --git a/docs/diagrams/LogicComponentClassDiagram.pptx b/docs/diagrams/LogicComponentClassDiagram.pptx index 6fcc1136a5bb..ca9f69c463cd 100644 Binary files a/docs/diagrams/LogicComponentClassDiagram.pptx and b/docs/diagrams/LogicComponentClassDiagram.pptx differ diff --git a/docs/diagrams/LogicComponentSequenceDiagram.pptx b/docs/diagrams/LogicComponentSequenceDiagram.pptx index c5b6d5fad6e3..88f2da1d6236 100644 Binary files a/docs/diagrams/LogicComponentSequenceDiagram.pptx and b/docs/diagrams/LogicComponentSequenceDiagram.pptx differ diff --git a/docs/diagrams/ModelComponentClassBetterOopDiagram.pptx b/docs/diagrams/ModelComponentClassBetterOopDiagram.pptx index d0561dfd305a..aeeca397662a 100644 Binary files a/docs/diagrams/ModelComponentClassBetterOopDiagram.pptx and b/docs/diagrams/ModelComponentClassBetterOopDiagram.pptx differ diff --git a/docs/diagrams/StorageComponentClassDiagram.pptx b/docs/diagrams/StorageComponentClassDiagram.pptx index be29a9de7ca6..096b7310d1d3 100644 Binary files a/docs/diagrams/StorageComponentClassDiagram.pptx and b/docs/diagrams/StorageComponentClassDiagram.pptx differ diff --git a/docs/diagrams/UiComponentClassDiagram.pptx b/docs/diagrams/UiComponentClassDiagram.pptx index 384d0a00e6ea..59c4445b0553 100644 Binary files a/docs/diagrams/UiComponentClassDiagram.pptx and b/docs/diagrams/UiComponentClassDiagram.pptx differ diff --git a/docs/diagrams/UndoRedoActivityDiagram.pptx b/docs/diagrams/UndoRedoActivityDiagram.pptx index 16fec930cf3f..ea2b956e9d05 100644 Binary files a/docs/diagrams/UndoRedoActivityDiagram.pptx and b/docs/diagrams/UndoRedoActivityDiagram.pptx differ diff --git a/docs/diagrams/UndoRedoExecuteUndoStateListDiagram.pptx b/docs/diagrams/UndoRedoExecuteUndoStateListDiagram.pptx index 6fd31b5f3fbd..affeb21b0d85 100644 Binary files a/docs/diagrams/UndoRedoExecuteUndoStateListDiagram.pptx and b/docs/diagrams/UndoRedoExecuteUndoStateListDiagram.pptx differ diff --git a/docs/diagrams/UndoRedoNewCommand1StateListDiagram.pptx b/docs/diagrams/UndoRedoNewCommand1StateListDiagram.pptx index 1f3261976dce..ad8f339847e0 100644 Binary files a/docs/diagrams/UndoRedoNewCommand1StateListDiagram.pptx and b/docs/diagrams/UndoRedoNewCommand1StateListDiagram.pptx differ diff --git a/docs/diagrams/UndoRedoNewCommand2StateListDiagram.pptx b/docs/diagrams/UndoRedoNewCommand2StateListDiagram.pptx index e2907d4a9cae..51edbc64b375 100644 Binary files a/docs/diagrams/UndoRedoNewCommand2StateListDiagram.pptx and b/docs/diagrams/UndoRedoNewCommand2StateListDiagram.pptx differ diff --git a/docs/diagrams/UndoRedoNewCommand3StateListDiagram.pptx b/docs/diagrams/UndoRedoNewCommand3StateListDiagram.pptx index 4ecc659bd600..e3055c2c3172 100644 Binary files a/docs/diagrams/UndoRedoNewCommand3StateListDiagram.pptx and b/docs/diagrams/UndoRedoNewCommand3StateListDiagram.pptx differ diff --git a/docs/diagrams/UndoRedoSequenceDiagram.pptx b/docs/diagrams/UndoRedoSequenceDiagram.pptx index 5ccc1042caac..a374eb70fe5b 100644 Binary files a/docs/diagrams/UndoRedoSequenceDiagram.pptx and b/docs/diagrams/UndoRedoSequenceDiagram.pptx differ diff --git a/docs/diagrams/UndoRedoStartingStateListDiagram.pptx b/docs/diagrams/UndoRedoStartingStateListDiagram.pptx index 98ce067642ff..d0b819cb0c30 100644 Binary files a/docs/diagrams/UndoRedoStartingStateListDiagram.pptx and b/docs/diagrams/UndoRedoStartingStateListDiagram.pptx differ diff --git a/docs/images/DeleteModuleSdForLogic.png b/docs/images/DeleteModuleSdForLogic.png new file mode 100644 index 000000000000..15dbef0a9dbc Binary files /dev/null and b/docs/images/DeleteModuleSdForLogic.png differ diff --git a/docs/images/DeletePersonSdForLogic.png b/docs/images/DeletePersonSdForLogic.png deleted file mode 100644 index 0462b9b7be6e..000000000000 Binary files a/docs/images/DeletePersonSdForLogic.png and /dev/null differ diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png index f4ecf65b3193..84305f9a5752 100644 Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ diff --git a/docs/images/ModelClassBetterOopDiagram.png b/docs/images/ModelClassBetterOopDiagram.png index 9ba8eb5e31d0..94de94a89e39 100644 Binary files a/docs/images/ModelClassBetterOopDiagram.png and b/docs/images/ModelClassBetterOopDiagram.png differ diff --git a/docs/images/SDAnnounce.png b/docs/images/SDAnnounce.png new file mode 100644 index 000000000000..e09c7f30c40b Binary files /dev/null and b/docs/images/SDAnnounce.png differ diff --git a/docs/images/SDBlockUserFromCreating.png b/docs/images/SDBlockUserFromCreating.png new file mode 100644 index 000000000000..9534a7a0f6a8 Binary files /dev/null and b/docs/images/SDBlockUserFromCreating.png differ diff --git a/docs/images/SDCheckAnnounce.png b/docs/images/SDCheckAnnounce.png new file mode 100644 index 000000000000..6d19f8e953ab Binary files /dev/null and b/docs/images/SDCheckAnnounce.png differ diff --git a/docs/images/SDCreateModule.png b/docs/images/SDCreateModule.png new file mode 100644 index 000000000000..334179a0357e Binary files /dev/null and b/docs/images/SDCreateModule.png differ diff --git a/docs/images/SDDeleteModule.png b/docs/images/SDDeleteModule.png new file mode 100644 index 000000000000..8a7e753bedf5 Binary files /dev/null and b/docs/images/SDDeleteModule.png differ diff --git a/docs/images/SDDeleteUser.png b/docs/images/SDDeleteUser.png new file mode 100644 index 000000000000..78e9df4895ca Binary files /dev/null and b/docs/images/SDDeleteUser.png differ diff --git a/docs/images/SDSetAdmin.png b/docs/images/SDSetAdmin.png new file mode 100644 index 000000000000..802b8617afa5 Binary files /dev/null and b/docs/images/SDSetAdmin.png differ diff --git a/docs/images/SDUpdateModule.png b/docs/images/SDUpdateModule.png new file mode 100644 index 000000000000..dd4c2d254a3e Binary files /dev/null and b/docs/images/SDUpdateModule.png differ diff --git a/docs/images/SDUpdatePass.png b/docs/images/SDUpdatePass.png new file mode 100644 index 000000000000..160ce2f89fdd Binary files /dev/null and b/docs/images/SDUpdatePass.png differ diff --git a/docs/images/SDforDeletePerson.png b/docs/images/SDforDeletePerson.png index 1e836f10dcd8..681a97c20e7b 100644 Binary files a/docs/images/SDforDeletePerson.png and b/docs/images/SDforDeletePerson.png differ diff --git a/docs/images/SDforDeletePersonEventHandling.png b/docs/images/SDforDeletePersonEventHandling.png index ecec0805d32c..bf9e95766f52 100644 Binary files a/docs/images/SDforDeletePersonEventHandling.png and b/docs/images/SDforDeletePersonEventHandling.png differ diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png index 7a4cd2700cbf..5d0db3d6eaf5 100644 Binary files a/docs/images/StorageClassDiagram.png and b/docs/images/StorageClassDiagram.png differ diff --git a/docs/images/Ui.png b/docs/images/Ui.png index 5ec9c527b49c..0aa09f2b67c3 100644 Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ diff --git a/docs/images/UiClassDiagram.png b/docs/images/UiClassDiagram.png index 369469ef176e..d53ca583b0e6 100644 Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ diff --git a/docs/images/UndoRedoActivityDiagram.png b/docs/images/UndoRedoActivityDiagram.png index 55e4138cc64f..a00895cc66ea 100644 Binary files a/docs/images/UndoRedoActivityDiagram.png and b/docs/images/UndoRedoActivityDiagram.png differ diff --git a/docs/images/UndoRedoExecuteUndoStateListDiagram.png b/docs/images/UndoRedoExecuteUndoStateListDiagram.png index 29c365d6b4a1..a1415a1acda9 100644 Binary files a/docs/images/UndoRedoExecuteUndoStateListDiagram.png and b/docs/images/UndoRedoExecuteUndoStateListDiagram.png differ diff --git a/docs/images/UndoRedoNewCommand1StateListDiagram.png b/docs/images/UndoRedoNewCommand1StateListDiagram.png index 76e661d62027..c60a793383c2 100644 Binary files a/docs/images/UndoRedoNewCommand1StateListDiagram.png and b/docs/images/UndoRedoNewCommand1StateListDiagram.png differ diff --git a/docs/images/UndoRedoNewCommand2StateListDiagram.png b/docs/images/UndoRedoNewCommand2StateListDiagram.png index adcb9aeadc51..b87a8dfe411d 100644 Binary files a/docs/images/UndoRedoNewCommand2StateListDiagram.png and b/docs/images/UndoRedoNewCommand2StateListDiagram.png differ diff --git a/docs/images/UndoRedoNewCommand3StateListDiagram.png b/docs/images/UndoRedoNewCommand3StateListDiagram.png index aac9c5fe05db..592d35f0cbca 100644 Binary files a/docs/images/UndoRedoNewCommand3StateListDiagram.png and b/docs/images/UndoRedoNewCommand3StateListDiagram.png differ diff --git a/docs/images/UndoRedoSequenceDiagram.png b/docs/images/UndoRedoSequenceDiagram.png index 5c9d5936f098..e04cf0ae26ad 100644 Binary files a/docs/images/UndoRedoSequenceDiagram.png and b/docs/images/UndoRedoSequenceDiagram.png differ diff --git a/docs/images/UndoRedoStartingStateListDiagram.png b/docs/images/UndoRedoStartingStateListDiagram.png index 002f3e2bbf79..78afa140c050 100644 Binary files a/docs/images/UndoRedoStartingStateListDiagram.png and b/docs/images/UndoRedoStartingStateListDiagram.png differ diff --git a/docs/images/e0191729.png b/docs/images/e0191729.png new file mode 100644 index 000000000000..cda3c6066997 Binary files /dev/null and b/docs/images/e0191729.png differ diff --git a/docs/images/hanskoh.png b/docs/images/hanskoh.png new file mode 100644 index 000000000000..05aa23bf3fed Binary files /dev/null and b/docs/images/hanskoh.png differ diff --git a/docs/images/meowzz95.png b/docs/images/meowzz95.png new file mode 100644 index 000000000000..94110b4a79f8 Binary files /dev/null and b/docs/images/meowzz95.png differ diff --git a/docs/images/xllx1.png b/docs/images/xllx1.png new file mode 100644 index 000000000000..354f4dffaf5e Binary files /dev/null and b/docs/images/xllx1.png differ diff --git a/docs/team/e0191729.adoc b/docs/team/e0191729.adoc new file mode 100644 index 000000000000..ef4e55793f07 --- /dev/null +++ b/docs/team/e0191729.adoc @@ -0,0 +1,55 @@ += Dinesh Mangalanathadurai - Project Portfolio +:site-section: AboutUs +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: ForumBook + +--- + +== Overview + +ForumBook is a desktop forum application which allows students to exchange information of the courses offered by their school. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in OOP fashion. + +== Summary of contributions + +* *Code contributed*: [https://nuscs2113-ay1819s1.github.io/dashboard/#=undefined&search=xllx1[Functional code]] + +* *Main feature implemented:*: added *various commands to enable admin to manage ForumBook* +** What it does: allows admin to better manage ForumBook by providing the following commands: +*** `AddUser`: add user to the ForumBook database. +*** `Login`: allow user to login to the ForumBook to Read and Share comments. +*** `Logout`: allow user to logout of the ForumBook safely +*** `SelfDeleteUser`: user is able to delete himself from the ForumBook database. +** Justification: This user management feature provides the users the most basic commands required for the user to use the ForumBook. These user commands provide a convenient way for users to better manage the ForumBook. +** Highlights: This user management feature provides the most simplest and efficient way for users to use/manage ForumBook. User could easily add themselves to the ForumBook, login to use the other features, logout of the ForumBook and if there is a need to, delete himself from the ForumBook. It also made ForumBook more user-friendly as it provides a better way of viewing data by showing the login status of the current user in the label at the top right corner, as well as showing the latest announcement in a pop up window. +* *Other contributions*: + +** Project management: +*** Managed releases `v1.1`(1 releases) on GitHub +** Documentation: +*** Did cosmetic tweaks to existing contents of the User Guide: https://github.com/CS2113-AY1819S1-T13-2/main/pull/85[#85], https://github.com/CS2113-AY1819S1-T13-2/main/pull/107[#107], https://github.com/CS2113-AY1819S1-T13-2/main/pull/119[119], https://github.com/CS2113-AY1819S1-T13-2/main/pull/187[#187] +*** Did cosmetic tweaks to existing contents of the Developer Guide: https://github.com/CS2113-AY1819S1-T13-2/main/pull/8[#8], https://github.com/CS2113-AY1819S1-T13-2/main/pull/107[#107], https://github.com/CS2113-AY1819S1-T13-2/main/pull/119[119], https://github.com/CS2113-AY1819S1-T13-2/main/pull/187[#187] +** Community: +*** PRs reviewed (with non-trivial review comments): https://github.com/CS2113-AY1819S1-T13-2/main/issues/154[#154], https://github.com/CS2113-AY1819S1-T13-2/main/issues/45[#45], https://github.com/CS2113-AY1819S1-T13-2/main/issues/29[#29], +*** Reported bugs and suggestions for other teams in the class: https://github.com/CS2113-AY1819S1-T09-1/main/issues/123[#123], https://github.com/CS2113-AY1819S1-T09-1/main/issues/119[#119], https://github.com/CS2113-AY1819S1-T09-1/main/issues/116[#116], https://github.com/CS2113-AY1819S1-T09-1/main/issues/104[#104] + +== 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=UserManagement1] +include::../UserGuide.adoc[tag=UserManagement2] + +== 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=UserManagement1] +include::../DeveloperGuide.adoc[tag=UserManagement2] +include::../DeveloperGuide.adoc[tag=UserManagement3] diff --git a/docs/team/hanskoh.adoc b/docs/team/hanskoh.adoc new file mode 100644 index 000000000000..1d531205af27 --- /dev/null +++ b/docs/team/hanskoh.adoc @@ -0,0 +1,57 @@ += Xu Hanhui - Project Portfolio +:site-section: AboutUs +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: ForumBook + +--- + +== Overview + +ForumBook is a desktop forum application which allows students to exchange information of the courses offered by their school. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in OOP fashion. + +== Summary of contributions + +* *Code contributed*: [https://nuscs2113-ay1819s1.github.io/dashboard/#=undefined&search=hanskoh&sort=displayName&since=2018-09-12&until=2018-11-02&timeframe=day&reverse=false&repoSort=true[Functional code]] + +* *Main feature implemented:*: added *various commands(CRUD) to enable users and admin to use ForumBook* +** What it does: allows users to use ForumBook by providing the following commands: +*** `CreateThreadCommand`: unblocked users and admin are able to create a new thread under a specific module. +*** `CreateCommentCommand`: unblocked users and admin are able to create a new comment under a specific thread. +*** `UpdateThreadCommand`: thread owner and admin are able to update the thread title. +*** `UpdateCommentCommand`: comment owner and admin are able to update the comment content. +*** `DeleteThreadCommand`: thread owner and admin are able to delete the thread. +*** `DeleteCommentCommand`: comment owner and admin are able to delete the comment. +*** `ListModuleCommand`: all logged in users are able to list all the modules exist in the ForumBook. +*** `SelectModuleCommand`: all logged in users are able to select a specific module code to list all threads under that module. +*** `SelectThreadCommand`: all logged in users are able to select a specific thread to list all comments under that thread. +** Justification: This CRUD feature is the basic function of the ForumBook. It provides the essential commands for users to share and communicate through the ForumBook. +** Highlights: This CRUD feature would greatly satisfy all the users who can type fast when using this CLI ForumBook Application. The prefixes of all the parameters used in the commands are simple and meaningful. + +* *Other contributions*: + +** Project management: +*** Managed releases `v1.3` - `v1.4` (2 releases) on GitHub +** Documentation: +*** Did cosmetic tweaks to existing contents of the User Guide: https://github.com/CS2113-AY1819S1-T13-2/main/pull/3[#3], https://github.com/CS2113-AY1819S1-T13-2/main/pull/100[#100], https://github.com/CS2113-AY1819S1-T13-2/main/pull/151/files[#151] +*** Did cosmetic tweaks to existing contents of the Developer Guide: https://github.com/CS2113-AY1819S1-T13-2/main/pull/7[#7], https://github.com/CS2113-AY1819S1-T13-2/main/pull/65[#65], https://github.com/CS2113-AY1819S1-T13-2/main/pull/100[#100], https://github.com/CS2113-AY1819S1-T13-2/main/pull/118[#118] +** Community: +*** Reported bugs and suggestions for other teams in the class: https://github.com/CS2113-AY1819S1-F09-4/main/issues/154[#154], https://github.com/CS2113-AY1819S1-F09-4/main/issues/169[#169] + +== 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=curd] + +== 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=curd] diff --git a/docs/team/johndoe.adoc b/docs/team/johndoe.adoc deleted file mode 100644 index 453c2152ab9d..000000000000 --- a/docs/team/johndoe.adoc +++ /dev/null @@ -1,72 +0,0 @@ -= John Doe - Project Portfolio -:site-section: AboutUs -:imagesDir: ../images -:stylesDir: ../stylesheets - -== PROJECT: AddressBook - Level 4 - ---- - -== 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. - -== Summary of contributions - -* *Major enhancement*: added *the ability to undo/redo previous commands* -** What it does: allows the user to undo all previous commands one at a time. Preceding undo commands can be reversed by using the redo command. -** Justification: This feature improves the product significantly because a user can make mistakes in commands and the app should provide a convenient way to rectify them. -** Highlights: This enhancement affects existing commands and commands to be added in future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands. -** Credits: _{mention here if you reused any code/ideas from elsewhere or if a third-party library is heavily used in the feature so that a reader can make a more accurate judgement of how much effort went into the feature}_ - -* *Minor enhancement*: added a history command that allows the user to navigate to previous commands using up/down keys. - -* *Code contributed*: [https://github.com[Functional code]] [https://github.com[Test code]] _{give links to collated code files}_ - -* *Other contributions*: - -** Project management: -*** Managed releases `v1.3` - `v1.5rc` (3 releases) on GitHub -** Enhancements to existing features: -*** Updated the GUI color scheme (Pull requests https://github.com[#33], https://github.com[#34]) -*** Wrote additional tests for existing features to increase coverage from 88% to 92% (Pull requests https://github.com[#36], https://github.com[#38]) -** Documentation: -*** Did cosmetic tweaks to existing contents of the User Guide: https://github.com[#14] -** Community: -*** PRs reviewed (with non-trivial review comments): https://github.com[#12], https://github.com[#32], https://github.com[#19], https://github.com[#42] -*** Contributed to forum discussions (examples: https://github.com[1], https://github.com[2], https://github.com[3], https://github.com[4]) -*** Reported bugs and suggestions for other teams in the class (examples: https://github.com[1], https://github.com[2], https://github.com[3]) -*** Some parts of the history feature I added was adopted by several other class mates (https://github.com[1], https://github.com[2]) -** Tools: -*** Integrated a third party library (Natty) to the project (https://github.com[#42]) -*** Integrated a new Github plugin (CircleCI) to the team repo - -_{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/meowzz95.adoc b/docs/team/meowzz95.adoc new file mode 100644 index 000000000000..a50c40eb5882 --- /dev/null +++ b/docs/team/meowzz95.adoc @@ -0,0 +1,76 @@ += Zhao Mingda - Project Portfolio +:site-section: AboutUs +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: ForumBook + +--- + +== Overview + +ForumBook is a desktop forum application which allows students to exchange information of the courses offered by their school. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in OOP fashion. + +== Summary of contributions + +* *Code contributed*: [https://nuscs2113-ay1819s1.github.io/dashboard/#=undefined&search=meowzz95[Functional code]] + +* *Main feature implemented:*: A underlying storage system that powers the application and manager +classes that provide APIs for other developers to manipulate application database in a robust way. +** What it does: Takes care of data storage, data encryption, and provide APIs for accessing the data. +*** `IStorage`: A interface that defines a storage that handles read/write to storage device/service +*** `IEncryptor`: A interface that defines a encryptor who knows an algorithm to encrypt/decrypt data +*** `SimpleEncryptor`: A concrete implementation of `IEncryptor`, it uses a simple and insecure 'OR' encryption for demoing the ability of data encryption in this application +*** `JsonFileStorage`: A concrete implementation of `IStorage`, it takes an `IEntryptor`(or by default it uses `SimpleEncryptor`) and use it to write encrypted json data to hard disk / read encrypted json data from hard disk +*** `BaseEntityStorage`: A base class for all types of entity storage, it uses generics to define the underlying `List` and a flag to keep track of whether this storage has been modified. +*** `[Entity]Storage`: Storage classes who extend `BaseEntityStorage` eg: `UserStorage` +*** `RunningId`: Singleton that handles Id generating, this mimics an auto-increment primary key field in a relational database, but a much simplified implementation. +*** `StorageMapping`: Singleton that maps class to file path, avoid magic numbers(strings). +*** `IForumBookStorage`: A interface, it defines a manager class that controls the loading/committing/accessing of data. +*** `I[Entity]Repository`: Entity repository interfaces that define the APIs of manipulating application data +*** `[Entity]Repository`: Concrete implementations of `I[Entity]Repository` +*** `IUnitOfWork`: A interface, it defines a wrapper that groups one or more operations into a single transaction, ensure data consistency +*** `UnitOfWork`: A concrete implementation of `IUnitOfWork` +*** `SampleDataGenerator`: A helper class to generate sample data after a fresh copy of this application is started + + +** Justification: This structure enables the application to manage multiple entities in a robust way. +** Highlights: This design takes data consistency and potential future storage possibilities(eg:store everything in a server) into account. Unit of work pattern ensures that even if one of a series of operation fails, the whole set of operation will not be saved, our data is always in a good shape. + + +* *Minor feature implemented*: Added a `Context` class that manages user login status and provide API for other commands to check login status. + +* *Other contributions*: + +** Project management: +*** Managed releases `v1.1` - `v1.2` (2 releases) on GitHub +** Documentation: +*** Did cosmetic tweaks to existing contents of the User Guide: https://github.com/CS2113-AY1819S1-T13-2/main/pull/168[#168] +*** Did cosmetic tweaks to existing contents of the Developer Guide: https://github.com/CS2113-AY1819S1-T13-2/main/pull/5[#5], https://github.com/CS2113-AY1819S1-T13-2/main/pull/9[#9], https://github.com/CS2113-AY1819S1-T13-2/main/pull/17[#17], https://github.com/CS2113-AY1819S1-T13-2/main/pull/20[#20], https://github.com/CS2113-AY1819S1-T13-2/main/pull/64[#64], https://github.com/CS2113-AY1819S1-T13-2/main/pull/109[#109], https://github.com/CS2113-AY1819S1-T13-2/main/pull/121[#121], https://github.com/CS2113-AY1819S1-T13-2/main/pull/167[#167], https://github.com/CS2113-AY1819S1-T13-2/main/pull/169[#169] +*** Documented most(~95%) of new java code written. +** Community: +*** PRs reviewed : https://github.com/CS2113-AY1819S1-T13-2/main/pull/76[#76], https://github.com/CS2113-AY1819S1-T13-2/main/pull/77[#77], https://github.com/CS2113-AY1819S1-T13-2/main/pull/78[#78] +*** Reported bugs and suggestions for other teams in the class + +== 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=encryption] + +include::../UserGuide.adoc[tag=faq] + +== 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=storage_component] + +include::../DeveloperGuide.adoc[tag=storage] + +include::../DeveloperGuide.adoc[tag=dataencryption] diff --git a/docs/team/xllx1.adoc b/docs/team/xllx1.adoc new file mode 100644 index 000000000000..a6802d8a26ef --- /dev/null +++ b/docs/team/xllx1.adoc @@ -0,0 +1,57 @@ += Cai Xiaolin - Project Portfolio +:site-section: AboutUs +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: ForumBook + +--- + +== Overview + +ForumBook is a desktop forum application which allows students to exchange information of the courses offered by their school. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in OOP fashion. + +== Summary of contributions + +* *Code contributed*: [https://nuscs2113-ay1819s1.github.io/dashboard/#=undefined&search=xllx1[Functional code]] + +* *Main feature implemented:*: added *various commands to enable admin to manage ForumBook* +** What it does: allows admin to better manage ForumBook by providing the following commands: +*** `AnnounceCommand`: admin is able to create new announcement. +*** `CheckAnnouncementCommand`: both user and admin are able to check for latest announcement, which is shown in a pop up window. +*** `BlockUserFromPostingCommand`: admin is able to block a given user. +*** `SetAdminCommand`: admin is able to set a user as admin or revert an admin to user. +*** `CreateModuleCommand`: admin is able to create modules. +*** `DeleteModuleCommand`: admin is able to delete modules. +*** `AdminUpdatePasswordCommand`: admin is able to update a user's password. +*** `DeleteUserCommand`: admin is able to delete a certain user. +** Justification: This admin management feature improves the product significantly as a new user type, admin, is introduced. These admin commands provide a convenient way for admin to better manage the ForumBook. +** Highlights: This admin management feature provides a more efficient way for admin to manage ForumBook, admin could easily block a certain user, help a user to update his/her password, etc. It also made ForumBook more user-friendly as it provides a better way of viewing data by showing the login status of the current user in the label at the top right corner, as well as showing the latest announcement in a pop up window. + +* *Other contributions*: + +** Project management: +*** Managed releases `v1.3` - `v1.4` (2 releases) on GitHub +** Documentation: +*** Did cosmetic tweaks to existing contents of the User Guide: https://github.com/CS2113-AY1819S1-T13-2/main/pull/4[#4], https://github.com/CS2113-AY1819S1-T13-2/main/pull/77[#77], https://github.com/CS2113-AY1819S1-T13-2/main/pull/98[#98], https://github.com/CS2113-AY1819S1-T13-2/main/pull/114[#114], https://github.com/CS2113-AY1819S1-T13-2/main/pull/120[#120], https://github.com/CS2113-AY1819S1-T13-2/main/pull/122[#122], https://github.com/CS2113-AY1819S1-T13-2/main/pull/124[#124], https://github.com/CS2113-AY1819S1-T13-2/main/pull/149[#149] +*** Did cosmetic tweaks to existing contents of the Developer Guide: https://github.com/CS2113-AY1819S1-T13-2/main/pull/[#6], https://github.com/CS2113-AY1819S1-T13-2/main/pull/62[#62], https://github.com/CS2113-AY1819S1-T13-2/main/pull/73[#73], https://github.com/CS2113-AY1819S1-T13-2/main/pull/77[#77], https://github.com/CS2113-AY1819S1-T13-2/main/pull/102[#102], https://github.com/CS2113-AY1819S1-T13-2/main/pull/109[#109], https://github.com/CS2113-AY1819S1-T13-2/main/pull/119[#119], https://github.com/CS2113-AY1819S1-T13-2/main/pull/120[#120], https://github.com/CS2113-AY1819S1-T13-2/main/pull/124[#124] +** Community: +*** PRs reviewed (with non-trivial review comments): https://github.com/CS2113-AY1819S1-T13-2/main/pull/48[#48], https://github.com/CS2113-AY1819S1-T13-2/main/pull/50[#50], https://github.com/CS2113-AY1819S1-T13-2/main/pull/81[#81] +*** Reported bugs and suggestions for other teams: https://github.com/CS2113-AY1819S1-F10-3/main/issues/185[#185], https://github.com/CS2113-AY1819S1-F10-3/main/issues/189[#189], https://github.com/CS2113-AY1819S1-F10-3/main/issues/195[#195], https://github.com/CS2113-AY1819S1-F10-3/main/issues/199[#199], https://github.com/CS2113-AY1819S1-F10-3/main/issues/202[#202], https://github.com/CS2113-AY1819S1-F10-3/main/issues/203[#203], https://github.com/CS2113-AY1819S1-F10-3/main/issues/207[#207] + +== 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=adminManagement] + +== 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=adminManagement] diff --git a/sampleData/forumData.zip b/sampleData/forumData.zip new file mode 100644 index 000000000000..4b59487e2062 Binary files /dev/null and b/sampleData/forumData.zip differ diff --git a/src/main/java/seedu/address/AppParameters.java b/src/main/java/com/t13g2/forum/AppParameters.java similarity index 93% rename from src/main/java/seedu/address/AppParameters.java rename to src/main/java/com/t13g2/forum/AppParameters.java index ab552c398f3d..5cc88a272897 100644 --- a/src/main/java/seedu/address/AppParameters.java +++ b/src/main/java/com/t13g2/forum/AppParameters.java @@ -1,4 +1,4 @@ -package seedu.address; +package com.t13g2.forum; import java.nio.file.Path; import java.nio.file.Paths; @@ -6,10 +6,10 @@ import java.util.Objects; import java.util.logging.Logger; -import javafx.application.Application; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.util.FileUtil; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.util.FileUtil; +import javafx.application.Application; /** * Represents the parsed command-line parameters given to the application. */ diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/com/t13g2/forum/MainApp.java similarity index 73% rename from src/main/java/seedu/address/MainApp.java rename to src/main/java/com/t13g2/forum/MainApp.java index ecdd043a4f81..e20e7effde11 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/com/t13g2/forum/MainApp.java @@ -1,4 +1,4 @@ -package seedu.address; +package com.t13g2.forum; import java.io.IOException; import java.nio.file.Path; @@ -6,34 +6,36 @@ import java.util.logging.Logger; import com.google.common.eventbus.Subscribe; +import com.t13g2.forum.commons.core.Config; +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.core.Version; +import com.t13g2.forum.commons.events.ui.ExitAppRequestEvent; +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.commons.util.ConfigUtil; +import com.t13g2.forum.commons.util.StringUtil; +import com.t13g2.forum.logic.Logic; +import com.t13g2.forum.logic.LogicManager; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.ReadOnlyForumBook; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.util.SampleDataUtil; +import com.t13g2.forum.storage.ForumBookStorage; +import com.t13g2.forum.storage.JsonUserPrefsStorage; +import com.t13g2.forum.storage.Storage; +import com.t13g2.forum.storage.StorageManager; +import com.t13g2.forum.storage.UserPrefsStorage; +import com.t13g2.forum.storage.XmlForumBookStorage; +import com.t13g2.forum.ui.Ui; +import com.t13g2.forum.ui.UiManager; import javafx.application.Application; import javafx.application.Platform; import javafx.stage.Stage; -import seedu.address.commons.core.Config; -import seedu.address.commons.core.EventsCenter; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.core.Version; -import seedu.address.commons.events.ui.ExitAppRequestEvent; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.commons.util.ConfigUtil; -import seedu.address.commons.util.StringUtil; -import seedu.address.logic.Logic; -import seedu.address.logic.LogicManager; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.UserPrefs; -import seedu.address.model.util.SampleDataUtil; -import seedu.address.storage.AddressBookStorage; -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.ui.Ui; -import seedu.address.ui.UiManager; + /** * The main entry point to the application. @@ -54,7 +56,7 @@ public class MainApp extends Application { @Override public void init() throws Exception { - logger.info("=============================[ Initializing AddressBook ]==========================="); + logger.info("=============================[ Initializing ForumBook ]==========================="); super.init(); AppParameters appParameters = AppParameters.parse(getParameters()); @@ -62,8 +64,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); + ForumBookStorage forumBookStorage = new XmlForumBookStorage(userPrefs.getForumBookFilePath()); + storage = new StorageManager(forumBookStorage, userPrefsStorage); initLogging(config); @@ -74,6 +76,10 @@ public void init() throws Exception { ui = new UiManager(logic, config, userPrefs); initEventsCenter(); + + try (UnitOfWork uow = new UnitOfWork()) { + uow.init(); + } } /** @@ -82,20 +88,20 @@ public void init() throws Exception { * 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 forumBookOptional; + ReadOnlyForumBook initialData; try { - addressBookOptional = storage.readAddressBook(); - if (!addressBookOptional.isPresent()) { - logger.info("Data file not found. Will be starting with a sample AddressBook"); + forumBookOptional = storage.readForumBook(); + if (!forumBookOptional.isPresent()) { + logger.info("Data file not found. Will be starting with a sample ForumBook"); } - initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook); + initialData = forumBookOptional.orElseGet(SampleDataUtil::getSampleForumBook); } 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 ForumBook"); + initialData = new ForumBook(); } 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 ForumBook"); + initialData = new ForumBook(); } return new ModelManager(initialData, userPrefs); @@ -159,7 +165,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 ForumBook"); initializedPrefs = new UserPrefs(); } @@ -179,7 +185,7 @@ private void initEventsCenter() { @Override public void start(Stage primaryStage) { - logger.info("Starting AddressBook " + MainApp.VERSION); + logger.info("Starting ForumBook " + MainApp.VERSION); ui.start(primaryStage); } diff --git a/src/main/java/seedu/address/commons/core/ComponentManager.java b/src/main/java/com/t13g2/forum/commons/core/ComponentManager.java similarity index 86% rename from src/main/java/seedu/address/commons/core/ComponentManager.java rename to src/main/java/com/t13g2/forum/commons/core/ComponentManager.java index 05a400773ae8..93a9734829cd 100644 --- a/src/main/java/seedu/address/commons/core/ComponentManager.java +++ b/src/main/java/com/t13g2/forum/commons/core/ComponentManager.java @@ -1,6 +1,6 @@ -package seedu.address.commons.core; +package com.t13g2.forum.commons.core; -import seedu.address.commons.events.BaseEvent; +import com.t13g2.forum.commons.events.BaseEvent; /** * Base class for *Manager classes diff --git a/src/main/java/seedu/address/commons/core/Config.java b/src/main/java/com/t13g2/forum/commons/core/Config.java similarity index 95% rename from src/main/java/seedu/address/commons/core/Config.java rename to src/main/java/com/t13g2/forum/commons/core/Config.java index e978d621e086..2772883213a1 100644 --- a/src/main/java/seedu/address/commons/core/Config.java +++ b/src/main/java/com/t13g2/forum/commons/core/Config.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package com.t13g2.forum.commons.core; import java.nio.file.Path; import java.nio.file.Paths; @@ -13,7 +13,7 @@ public class Config { public static final Path DEFAULT_CONFIG_FILE = Paths.get("config.json"); // Config values customizable through config file - private String appTitle = "Address App"; + private String appTitle = "Forum Book"; private Level logLevel = Level.INFO; private Path userPrefsFilePath = Paths.get("preferences.json"); diff --git a/src/main/java/seedu/address/commons/core/EventsCenter.java b/src/main/java/com/t13g2/forum/commons/core/EventsCenter.java similarity index 92% rename from src/main/java/seedu/address/commons/core/EventsCenter.java rename to src/main/java/com/t13g2/forum/commons/core/EventsCenter.java index 799b976f7eb7..e0a1f619d922 100644 --- a/src/main/java/seedu/address/commons/core/EventsCenter.java +++ b/src/main/java/com/t13g2/forum/commons/core/EventsCenter.java @@ -1,10 +1,10 @@ -package seedu.address.commons.core; +package com.t13g2.forum.commons.core; import java.util.logging.Logger; import com.google.common.eventbus.EventBus; +import com.t13g2.forum.commons.events.BaseEvent; -import seedu.address.commons.events.BaseEvent; /** * Manages the event dispatching of the app. diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/com/t13g2/forum/commons/core/GuiSettings.java similarity index 98% rename from src/main/java/seedu/address/commons/core/GuiSettings.java rename to src/main/java/com/t13g2/forum/commons/core/GuiSettings.java index ed578f1a9bb6..36af385d389e 100644 --- a/src/main/java/seedu/address/commons/core/GuiSettings.java +++ b/src/main/java/com/t13g2/forum/commons/core/GuiSettings.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package com.t13g2.forum.commons.core; import java.awt.Point; import java.io.Serializable; diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/com/t13g2/forum/commons/core/LogsCenter.java similarity index 93% rename from src/main/java/seedu/address/commons/core/LogsCenter.java rename to src/main/java/com/t13g2/forum/commons/core/LogsCenter.java index 5316a1d87d3e..749f76eb823a 100644 --- a/src/main/java/seedu/address/commons/core/LogsCenter.java +++ b/src/main/java/com/t13g2/forum/commons/core/LogsCenter.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package com.t13g2.forum.commons.core; import java.io.IOException; import java.util.Arrays; @@ -8,14 +8,14 @@ import java.util.logging.Logger; import java.util.logging.SimpleFormatter; -import seedu.address.commons.events.BaseEvent; +import com.t13g2.forum.commons.events.BaseEvent; /** * Configures and manages loggers and handlers, including their logging level * Named {@link Logger}s can be obtained from this class
* These loggers have been configured to output messages to the console and a {@code .log} file by default, - * at the {@code INFO} level. A new {@code .log} file with a new numbering will be created after the log - * file reaches 5MB big, up to a maximum of 5 files.
+ * at the {@code INFO} level. A new {@code .log} file with a new numbering will be created after the log + * file reaches 5MB big, up to a maximum of 5 files.
*/ public class LogsCenter { private static final int MAX_FILE_COUNT = 5; @@ -77,7 +77,7 @@ private static void addConsoleHandler(Logger logger) { */ private static void removeHandlers(Logger logger) { Arrays.stream(logger.getHandlers()) - .forEach(logger::removeHandler); + .forEach(logger::removeHandler); } /** @@ -97,6 +97,7 @@ private static void addFileHandler(Logger logger) { /** * Creates a {@code FileHandler} for the log file. + * * @throws IOException if there are problems opening the file. */ private static FileHandler createFileHandler() throws IOException { diff --git a/src/main/java/com/t13g2/forum/commons/core/Messages.java b/src/main/java/com/t13g2/forum/commons/core/Messages.java new file mode 100644 index 000000000000..f063728d6f21 --- /dev/null +++ b/src/main/java/com/t13g2/forum/commons/core/Messages.java @@ -0,0 +1,29 @@ +package com.t13g2.forum.commons.core; + +/** + * Container for user visible messages. + */ +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_NOT_LOGIN = "Sorry! You have to login to proceed."; + public static final String MESSAGE_BLOCKED_USER = + "You have been blocked for creating and updating thread and comment!"; + public static final String MESSAGE_NOT_THREAD_OWNER = "Sorry! You are not the owner of this thread."; + public static final String MESSAGE_NOT_COMMENT_OWNER = "Sorry! You are not the owner of this comment."; + + public static final String MESSAGE_INVALID_MODULE_CODE = "Module Code does not exist in the forum book!"; + public static final String MESSAGE_INVALID_THREAD_ID = "Thread ID does not exist in the forum book!"; + public static final String MESSAGE_INVALID_COMMENT_ID = "Comment ID does not exist in the forum book!"; + + public static final String MESSAGE_INVALID_THREAD = + "Sorry! The entity you requested is not under the current scope." + + "\nPlease go to the corresponding thread list."; + public static final String MESSAGE_INVALID_COMMENT = + "Sorry! The entity you requested is not under the current scope." + + "\nPlease go to the corresponding comment list."; +} diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/com/t13g2/forum/commons/core/Version.java similarity index 98% rename from src/main/java/seedu/address/commons/core/Version.java rename to src/main/java/com/t13g2/forum/commons/core/Version.java index e117f91b3b2e..5381e2ee5545 100644 --- a/src/main/java/seedu/address/commons/core/Version.java +++ b/src/main/java/com/t13g2/forum/commons/core/Version.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package com.t13g2.forum.commons.core; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/main/java/seedu/address/commons/core/index/Index.java b/src/main/java/com/t13g2/forum/commons/core/index/Index.java similarity index 97% rename from src/main/java/seedu/address/commons/core/index/Index.java rename to src/main/java/com/t13g2/forum/commons/core/index/Index.java index 19536439c099..abaa38324030 100644 --- a/src/main/java/seedu/address/commons/core/index/Index.java +++ b/src/main/java/com/t13g2/forum/commons/core/index/Index.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core.index; +package com.t13g2.forum.commons.core.index; /** * Represents a zero-based or one-based index. diff --git a/src/main/java/seedu/address/commons/events/BaseEvent.java b/src/main/java/com/t13g2/forum/commons/events/BaseEvent.java similarity index 91% rename from src/main/java/seedu/address/commons/events/BaseEvent.java rename to src/main/java/com/t13g2/forum/commons/events/BaseEvent.java index 85e71cbb6b62..7848492c0fe4 100644 --- a/src/main/java/seedu/address/commons/events/BaseEvent.java +++ b/src/main/java/com/t13g2/forum/commons/events/BaseEvent.java @@ -1,4 +1,4 @@ -package seedu.address.commons.events; +package com.t13g2.forum.commons.events; /** * The base class for all event classes. diff --git a/src/main/java/com/t13g2/forum/commons/events/model/AddressBookChangedEvent.java b/src/main/java/com/t13g2/forum/commons/events/model/AddressBookChangedEvent.java new file mode 100644 index 000000000000..f27a5d259e80 --- /dev/null +++ b/src/main/java/com/t13g2/forum/commons/events/model/AddressBookChangedEvent.java @@ -0,0 +1,19 @@ +package com.t13g2.forum.commons.events.model; + +import com.t13g2.forum.commons.events.BaseEvent; +import com.t13g2.forum.model.ReadOnlyForumBook; + +/** Indicates the ForumBook in the model has changed*/ +public class AddressBookChangedEvent extends BaseEvent { + + public final ReadOnlyForumBook data; + + public AddressBookChangedEvent(ReadOnlyForumBook data) { + this.data = data; + } + + @Override + public String toString() { + return "number of persons " + data.getPersonList().size(); + } +} diff --git a/src/main/java/com/t13g2/forum/commons/events/model/LoginPopUpEvent.java b/src/main/java/com/t13g2/forum/commons/events/model/LoginPopUpEvent.java new file mode 100644 index 000000000000..b81bf205d8c4 --- /dev/null +++ b/src/main/java/com/t13g2/forum/commons/events/model/LoginPopUpEvent.java @@ -0,0 +1,6 @@ +package com.t13g2.forum.commons.events.model; + +//@@author E0191729 +/** Login pop up*/ +public class LoginPopUpEvent { +} diff --git a/src/main/java/com/t13g2/forum/commons/events/model/ShowAnnouncementEvent.java b/src/main/java/com/t13g2/forum/commons/events/model/ShowAnnouncementEvent.java new file mode 100644 index 000000000000..33fa11315f86 --- /dev/null +++ b/src/main/java/com/t13g2/forum/commons/events/model/ShowAnnouncementEvent.java @@ -0,0 +1,21 @@ +package com.t13g2.forum.commons.events.model; + +import com.t13g2.forum.commons.events.BaseEvent; + +//@@author xllx1 +/** Shows announcement pop up*/ +public class ShowAnnouncementEvent extends BaseEvent { + + public final String announcementTitle; + public final String announcementContent; + + public ShowAnnouncementEvent(String aTitle, String aContent) { + this.announcementTitle = aTitle; + this.announcementContent = aContent; + } + + @Override + public String toString() { + return "Showing announcement"; + } +} diff --git a/src/main/java/com/t13g2/forum/commons/events/model/UserLoginEvent.java b/src/main/java/com/t13g2/forum/commons/events/model/UserLoginEvent.java new file mode 100644 index 000000000000..081507322536 --- /dev/null +++ b/src/main/java/com/t13g2/forum/commons/events/model/UserLoginEvent.java @@ -0,0 +1,23 @@ +package com.t13g2.forum.commons.events.model; + +import com.t13g2.forum.commons.events.BaseEvent; + +//@@author xllx1 +/** Indicates the user has logged in*/ +public class UserLoginEvent extends BaseEvent { + + public final String userName; + public final boolean userType; + public final boolean isBlocked; + + public UserLoginEvent(String uName, boolean uType, boolean blocked) { + this.userName = uName; + this.userType = uType; + this.isBlocked = blocked; + } + + @Override + public String toString() { + return "User logged in, user name: " + userName + ", isBlocked: " + isBlocked; + } +} diff --git a/src/main/java/seedu/address/commons/events/storage/DataSavingExceptionEvent.java b/src/main/java/com/t13g2/forum/commons/events/storage/DataSavingExceptionEvent.java similarity index 78% rename from src/main/java/seedu/address/commons/events/storage/DataSavingExceptionEvent.java rename to src/main/java/com/t13g2/forum/commons/events/storage/DataSavingExceptionEvent.java index 7096107d8adf..6ddbfafa0442 100644 --- a/src/main/java/seedu/address/commons/events/storage/DataSavingExceptionEvent.java +++ b/src/main/java/com/t13g2/forum/commons/events/storage/DataSavingExceptionEvent.java @@ -1,6 +1,6 @@ -package seedu.address.commons.events.storage; +package com.t13g2.forum.commons.events.storage; -import seedu.address.commons.events.BaseEvent; +import com.t13g2.forum.commons.events.BaseEvent; /** * Indicates an exception during a file saving diff --git a/src/main/java/seedu/address/commons/events/ui/ExitAppRequestEvent.java b/src/main/java/com/t13g2/forum/commons/events/ui/ExitAppRequestEvent.java similarity index 68% rename from src/main/java/seedu/address/commons/events/ui/ExitAppRequestEvent.java rename to src/main/java/com/t13g2/forum/commons/events/ui/ExitAppRequestEvent.java index a280bc7b5569..0d97805be6bc 100644 --- a/src/main/java/seedu/address/commons/events/ui/ExitAppRequestEvent.java +++ b/src/main/java/com/t13g2/forum/commons/events/ui/ExitAppRequestEvent.java @@ -1,6 +1,6 @@ -package seedu.address.commons.events.ui; +package com.t13g2.forum.commons.events.ui; -import seedu.address.commons.events.BaseEvent; +import com.t13g2.forum.commons.events.BaseEvent; /** * Indicates a request for App termination diff --git a/src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java b/src/main/java/com/t13g2/forum/commons/events/ui/JumpToListRequestEvent.java similarity index 72% rename from src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java rename to src/main/java/com/t13g2/forum/commons/events/ui/JumpToListRequestEvent.java index a890f8b47350..ee111175f7f1 100644 --- a/src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java +++ b/src/main/java/com/t13g2/forum/commons/events/ui/JumpToListRequestEvent.java @@ -1,7 +1,7 @@ -package seedu.address.commons.events.ui; +package com.t13g2.forum.commons.events.ui; -import seedu.address.commons.core.index.Index; -import seedu.address.commons.events.BaseEvent; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.commons.events.BaseEvent; /** * Indicates a request to jump to the list of persons diff --git a/src/main/java/com/t13g2/forum/commons/events/ui/ModulePanelSelectionChangedEvent.java b/src/main/java/com/t13g2/forum/commons/events/ui/ModulePanelSelectionChangedEvent.java new file mode 100644 index 000000000000..11d94221f808 --- /dev/null +++ b/src/main/java/com/t13g2/forum/commons/events/ui/ModulePanelSelectionChangedEvent.java @@ -0,0 +1,27 @@ +package com.t13g2.forum.commons.events.ui; + +import com.t13g2.forum.commons.events.BaseEvent; +import com.t13g2.forum.model.forum.Module; + +/** + * Represents a selection change in the Module List Panel + */ +public class ModulePanelSelectionChangedEvent extends BaseEvent { + + + private final Module newSelection; + + public ModulePanelSelectionChangedEvent(Module newSelection) { + this.newSelection = newSelection; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + public Module getNewSelection() { + return newSelection; + } +} + diff --git a/src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java b/src/main/java/com/t13g2/forum/commons/events/ui/NewResultAvailableEvent.java similarity index 78% rename from src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java rename to src/main/java/com/t13g2/forum/commons/events/ui/NewResultAvailableEvent.java index a5e8b2e13883..ab721ef4fa22 100644 --- a/src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java +++ b/src/main/java/com/t13g2/forum/commons/events/ui/NewResultAvailableEvent.java @@ -1,6 +1,6 @@ -package seedu.address.commons.events.ui; +package com.t13g2.forum.commons.events.ui; -import seedu.address.commons.events.BaseEvent; +import com.t13g2.forum.commons.events.BaseEvent; /** * Indicates that a new result is available. diff --git a/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java b/src/main/java/com/t13g2/forum/commons/events/ui/PersonPanelSelectionChangedEvent.java similarity index 77% rename from src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java rename to src/main/java/com/t13g2/forum/commons/events/ui/PersonPanelSelectionChangedEvent.java index c5c8b9ce90ed..9fc548c9c370 100644 --- a/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java +++ b/src/main/java/com/t13g2/forum/commons/events/ui/PersonPanelSelectionChangedEvent.java @@ -1,7 +1,7 @@ -package seedu.address.commons.events.ui; +package com.t13g2.forum.commons.events.ui; -import seedu.address.commons.events.BaseEvent; -import seedu.address.model.person.Person; +import com.t13g2.forum.commons.events.BaseEvent; +import com.t13g2.forum.model.person.Person; /** * Represents a selection change in the Person List Panel diff --git a/src/main/java/seedu/address/commons/events/ui/ShowHelpRequestEvent.java b/src/main/java/com/t13g2/forum/commons/events/ui/ShowHelpRequestEvent.java similarity index 69% rename from src/main/java/seedu/address/commons/events/ui/ShowHelpRequestEvent.java rename to src/main/java/com/t13g2/forum/commons/events/ui/ShowHelpRequestEvent.java index 87d5c70a1b79..8111657a03ff 100644 --- a/src/main/java/seedu/address/commons/events/ui/ShowHelpRequestEvent.java +++ b/src/main/java/com/t13g2/forum/commons/events/ui/ShowHelpRequestEvent.java @@ -1,6 +1,6 @@ -package seedu.address.commons.events.ui; +package com.t13g2.forum.commons.events.ui; -import seedu.address.commons.events.BaseEvent; +import com.t13g2.forum.commons.events.BaseEvent; /** * An event requesting to view the help page. diff --git a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java b/src/main/java/com/t13g2/forum/commons/exceptions/DataConversionException.java similarity index 83% rename from src/main/java/seedu/address/commons/exceptions/DataConversionException.java rename to src/main/java/com/t13g2/forum/commons/exceptions/DataConversionException.java index 1f689bd8e3f9..58b6f168ba90 100644 --- a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java +++ b/src/main/java/com/t13g2/forum/commons/exceptions/DataConversionException.java @@ -1,4 +1,4 @@ -package seedu.address.commons.exceptions; +package com.t13g2.forum.commons.exceptions; /** * Represents an error during conversion of data from one format to another diff --git a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java b/src/main/java/com/t13g2/forum/commons/exceptions/IllegalValueException.java similarity index 92% rename from src/main/java/seedu/address/commons/exceptions/IllegalValueException.java rename to src/main/java/com/t13g2/forum/commons/exceptions/IllegalValueException.java index 19124db485c9..7a6d9638fb03 100644 --- a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java +++ b/src/main/java/com/t13g2/forum/commons/exceptions/IllegalValueException.java @@ -1,4 +1,4 @@ -package seedu.address.commons.exceptions; +package com.t13g2.forum.commons.exceptions; /** * Signals that some given data does not fulfill some constraints. diff --git a/src/main/java/seedu/address/commons/util/AppUtil.java b/src/main/java/com/t13g2/forum/commons/util/AppUtil.java similarity index 93% rename from src/main/java/seedu/address/commons/util/AppUtil.java rename to src/main/java/com/t13g2/forum/commons/util/AppUtil.java index da90201dfd64..0784d9dd6615 100644 --- a/src/main/java/seedu/address/commons/util/AppUtil.java +++ b/src/main/java/com/t13g2/forum/commons/util/AppUtil.java @@ -1,9 +1,10 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static java.util.Objects.requireNonNull; +import com.t13g2.forum.MainApp; + import javafx.scene.image.Image; -import seedu.address.MainApp; /** * A container for App specific utility functions diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/com/t13g2/forum/commons/util/CollectionUtil.java similarity index 96% rename from src/main/java/seedu/address/commons/util/CollectionUtil.java rename to src/main/java/com/t13g2/forum/commons/util/CollectionUtil.java index eafe4dfd6818..495d67c98ee7 100644 --- a/src/main/java/seedu/address/commons/util/CollectionUtil.java +++ b/src/main/java/com/t13g2/forum/commons/util/CollectionUtil.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static java.util.Objects.requireNonNull; diff --git a/src/main/java/seedu/address/commons/util/ConfigUtil.java b/src/main/java/com/t13g2/forum/commons/util/ConfigUtil.java similarity index 76% rename from src/main/java/seedu/address/commons/util/ConfigUtil.java rename to src/main/java/com/t13g2/forum/commons/util/ConfigUtil.java index f7f8a2bd44c0..fd6728ab03d7 100644 --- a/src/main/java/seedu/address/commons/util/ConfigUtil.java +++ b/src/main/java/com/t13g2/forum/commons/util/ConfigUtil.java @@ -1,11 +1,11 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -import seedu.address.commons.core.Config; -import seedu.address.commons.exceptions.DataConversionException; +import com.t13g2.forum.commons.core.Config; +import com.t13g2.forum.commons.exceptions.DataConversionException; /** * A class for accessing the Config File. diff --git a/src/main/java/com/t13g2/forum/commons/util/Extensions.java b/src/main/java/com/t13g2/forum/commons/util/Extensions.java new file mode 100644 index 000000000000..3f44490fd2eb --- /dev/null +++ b/src/main/java/com/t13g2/forum/commons/util/Extensions.java @@ -0,0 +1,31 @@ +//@@author Meowzz95 +package com.t13g2.forum.commons.util; + +import java.util.List; + +import com.t13g2.forum.model.forum.BaseModel; + +/** + * This class provides utility methods + */ +public class Extensions { + /** + * Utility methods to update a object in a list + * + * @param list + * @param object + * @param + */ + public static void updateObjectInList(List list, T object) { + int index = -1; + for (int i = 0; i < list.size(); i++) { + if (list.get(i).getId() == object.getId()) { + index = i; + break; + } + } + if (index >= 0) { + list.set(index, object); + } + } +} diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/com/t13g2/forum/commons/util/FileUtil.java similarity index 96% rename from src/main/java/seedu/address/commons/util/FileUtil.java rename to src/main/java/com/t13g2/forum/commons/util/FileUtil.java index b1e2767cdd92..5037a06775ed 100644 --- a/src/main/java/seedu/address/commons/util/FileUtil.java +++ b/src/main/java/com/t13g2/forum/commons/util/FileUtil.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import java.io.IOException; import java.nio.file.Files; @@ -18,7 +18,7 @@ public static boolean isFileExists(Path file) { } /** - * Returns true if {@code path} can be converted into a {@code Path} via {@link Paths#get(String)}, + * Returns true if {@code path} can be converted into a {@code Path} via , * otherwise returns false. * @param path A string representing the file path. Cannot be null. */ diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/com/t13g2/forum/commons/util/JsonUtil.java similarity index 97% rename from src/main/java/seedu/address/commons/util/JsonUtil.java rename to src/main/java/com/t13g2/forum/commons/util/JsonUtil.java index 8ecd614f550a..898b01414ac5 100644 --- a/src/main/java/seedu/address/commons/util/JsonUtil.java +++ b/src/main/java/com/t13g2/forum/commons/util/JsonUtil.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static java.util.Objects.requireNonNull; @@ -19,9 +19,8 @@ import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; - -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.exceptions.DataConversionException; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.exceptions.DataConversionException; /** * Converts a Java object instance to JSON and vice versa diff --git a/src/main/java/com/t13g2/forum/commons/util/RestrictiveCommandUtil.java b/src/main/java/com/t13g2/forum/commons/util/RestrictiveCommandUtil.java new file mode 100644 index 000000000000..72118b2eaa01 --- /dev/null +++ b/src/main/java/com/t13g2/forum/commons/util/RestrictiveCommandUtil.java @@ -0,0 +1,26 @@ +package com.t13g2.forum.commons.util; + +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; + +/** + * A Utility class to restrict commands + */ +public class RestrictiveCommandUtil { + + public static final String MESSAGE_NOT_LOGIN = "Sorry! You have to login to proceed."; + public static final String MESSAGE_BLOCKED_USER = "You have been blocked for creating new thread and comment!"; + public static final String MESSAGE_NOT_THREAD_OWNER = "Sorry! You are not the owner of this thread."; + public static final String MESSAGE_NOT_COMMENT_OWNER = "Sorry! You are not the owner of this comment."; + + /** + * check for login status + * @throws CommandException + */ + public static boolean checkLogin() throws CommandException { + if (!Context.getInstance().isLoggedIn()) { + return false; + } + return true; + } +} diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/com/t13g2/forum/commons/util/StringUtil.java similarity index 88% rename from src/main/java/seedu/address/commons/util/StringUtil.java rename to src/main/java/com/t13g2/forum/commons/util/StringUtil.java index 61cc8c9a1cb8..f661c6949c4d 100644 --- a/src/main/java/seedu/address/commons/util/StringUtil.java +++ b/src/main/java/com/t13g2/forum/commons/util/StringUtil.java @@ -1,7 +1,6 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; import java.io.PrintWriter; import java.io.StringWriter; @@ -28,8 +27,8 @@ public static boolean containsWordIgnoreCase(String sentence, String word) { requireNonNull(word); String preppedWord = word.trim(); - checkArgument(!preppedWord.isEmpty(), "Word parameter cannot be empty"); - checkArgument(preppedWord.split("\\s+").length == 1, "Word parameter should be a single word"); + AppUtil.checkArgument(!preppedWord.isEmpty(), "Word parameter cannot be empty"); + AppUtil.checkArgument(preppedWord.split("\\s+").length == 1, "Word parameter should be a single word"); String preppedSentence = sentence; String[] wordsInPreppedSentence = preppedSentence.split("\\s+"); diff --git a/src/main/java/seedu/address/commons/util/XmlUtil.java b/src/main/java/com/t13g2/forum/commons/util/XmlUtil.java similarity index 98% rename from src/main/java/seedu/address/commons/util/XmlUtil.java rename to src/main/java/com/t13g2/forum/commons/util/XmlUtil.java index a78cd15b7f0c..dc0f6fb057fb 100644 --- a/src/main/java/seedu/address/commons/util/XmlUtil.java +++ b/src/main/java/com/t13g2/forum/commons/util/XmlUtil.java @@ -1,11 +1,10 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static java.util.Objects.requireNonNull; import java.io.FileNotFoundException; import java.nio.file.Files; import java.nio.file.Path; - import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; diff --git a/src/main/java/seedu/address/logic/CommandHistory.java b/src/main/java/com/t13g2/forum/logic/CommandHistory.java similarity index 97% rename from src/main/java/seedu/address/logic/CommandHistory.java rename to src/main/java/com/t13g2/forum/logic/CommandHistory.java index 39bca9b8df57..c49a51df0d21 100644 --- a/src/main/java/seedu/address/logic/CommandHistory.java +++ b/src/main/java/com/t13g2/forum/logic/CommandHistory.java @@ -1,4 +1,4 @@ -package seedu.address.logic; +package com.t13g2.forum.logic; import static java.util.Objects.requireNonNull; diff --git a/src/main/java/seedu/address/logic/ListElementPointer.java b/src/main/java/com/t13g2/forum/logic/ListElementPointer.java similarity index 99% rename from src/main/java/seedu/address/logic/ListElementPointer.java rename to src/main/java/com/t13g2/forum/logic/ListElementPointer.java index ca4085d98a11..115dcb5e04fc 100644 --- a/src/main/java/seedu/address/logic/ListElementPointer.java +++ b/src/main/java/com/t13g2/forum/logic/ListElementPointer.java @@ -1,4 +1,4 @@ -package seedu.address.logic; +package com.t13g2.forum.logic; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/com/t13g2/forum/logic/Logic.java similarity index 75% rename from src/main/java/seedu/address/logic/Logic.java rename to src/main/java/com/t13g2/forum/logic/Logic.java index 8b34b862039a..405f1cfe56ea 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/com/t13g2/forum/logic/Logic.java @@ -1,10 +1,11 @@ -package seedu.address.logic; +package com.t13g2.forum.logic; + +import com.t13g2.forum.logic.commands.CommandResult; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.person.Person; import javafx.collections.ObservableList; -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; /** * API of the Logic component diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/com/t13g2/forum/logic/LogicManager.java similarity index 71% rename from src/main/java/seedu/address/logic/LogicManager.java rename to src/main/java/com/t13g2/forum/logic/LogicManager.java index 9aff86fc33dc..7882ac6ff3a9 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/com/t13g2/forum/logic/LogicManager.java @@ -1,17 +1,18 @@ -package seedu.address.logic; +package com.t13g2.forum.logic; import java.util.logging.Logger; +import com.t13g2.forum.commons.core.ComponentManager; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.logic.commands.Command; +import com.t13g2.forum.logic.commands.CommandResult; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.parser.AddressBookParser; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.person.Person; + import javafx.collections.ObservableList; -import seedu.address.commons.core.ComponentManager; -import seedu.address.commons.core.LogsCenter; -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.exceptions.ParseException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; /** * The main LogicManager of the app. diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/com/t13g2/forum/logic/commands/AddCommand.java similarity index 75% rename from src/main/java/seedu/address/logic/commands/AddCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/AddCommand.java index d88e831ff1ce..e2adcd762f97 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/AddCommand.java @@ -1,16 +1,16 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_EMAIL; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_PHONE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_TAG; 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_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import seedu.address.logic.CommandHistory; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.person.Person; /** * Adds a person to the address book. @@ -56,7 +56,7 @@ public CommandResult execute(Model model, CommandHistory history) throws Command } model.addPerson(toAdd); - model.commitAddressBook(); + model.commitForumBook(); return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); } diff --git a/src/main/java/com/t13g2/forum/logic/commands/AddUserCommand.java b/src/main/java/com/t13g2/forum/logic/commands/AddUserCommand.java new file mode 100644 index 000000000000..a1065facaff6 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/AddUserCommand.java @@ -0,0 +1,70 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_PASSWORD; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author e0191729 +/** + * Add a person to the ForumBook + */ +public class AddUserCommand extends Command { + /** + * + */ + public static final String COMMAND_WORD = "addUser"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Add user to forum book. " + + "\nParameters: " + + PREFIX_USER_NAME + "USER NAME " + + PREFIX_USER_PASSWORD + "PASSWORD \n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_USER_NAME + "John Doe " + + PREFIX_USER_PASSWORD + "1234 "; + + + public static final String MESSAGE_SUCCESS = "WELCOME : %1$s. You had been successfully been registered."; + public static final String MESSAGE_DUPLICATE_PERSON = "This user name already exists, Please use another name."; + private final User userToAdd; + + public AddUserCommand(User newUser) { + requireNonNull(newUser); + this.userToAdd = newUser; + + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + boolean exist = false; + /* Check if user Name is available. + * */ + UnitOfWork unitOfWork = new UnitOfWork(); + //try () { + try { + if (unitOfWork.getUserRepository().getUserByUsername(userToAdd.getUsername()) != null) { + exist = true; + } + } catch (EntityDoesNotExistException ex) { + exist = false; + } catch (Exception e) { + exist = true; + e.printStackTrace(); + } + + if (!exist) { + unitOfWork.getUserRepository().addUser(userToAdd); + unitOfWork.commit(); + } else { + throw new CommandException(MESSAGE_DUPLICATE_PERSON); + } + + return new CommandResult(String.format(MESSAGE_SUCCESS, userToAdd.getUsername())); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/AdminUpdatePasswordCommand.java b/src/main/java/com/t13g2/forum/logic/commands/AdminUpdatePasswordCommand.java new file mode 100644 index 000000000000..4d27d2aed9a5 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/AdminUpdatePasswordCommand.java @@ -0,0 +1,70 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_PASSWORD; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author xllx1 +/** + * Updates a certain user's password. + */ +public class AdminUpdatePasswordCommand extends Command { + + public static final String COMMAND_WORD = "updatePass"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Updates a certain user's password. " + + "\nParameters: " + + PREFIX_USER_NAME + "USER NAME " + + PREFIX_USER_PASSWORD + "USER PASSWORD " + + "\nExample: " + COMMAND_WORD + " " + + PREFIX_USER_NAME + "john " + + PREFIX_USER_PASSWORD + "456"; + + public static final String MESSAGE_SUCCESS = "Password for %1$s is now %2$s"; + public static final String MESSAGE_INVALID_USER = "No user named \"%1$s\" found. Please try again!"; + + + private final String userNameToUpdate; + private final String userPassToUpdate; + + /** + * Creates an AdminUpdatePasswordCommand to update password for the the specified {@code toUpdate}. + */ + public AdminUpdatePasswordCommand(String uName, String uPass) { + requireNonNull(uName); + requireNonNull(uPass); + this.userNameToUpdate = uName; + this.userPassToUpdate = uPass; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } else if (!Context.getInstance().isCurrentUserAdmin()) { + throw new CommandException(User.MESSAGE_NOT_ADMIN); + } + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + User userToUpdate = unitOfWork.getUserRepository().getUserByUsername(userNameToUpdate); + userToUpdate.setPassword(userPassToUpdate); + unitOfWork.getUserRepository().updateUser(userToUpdate); + unitOfWork.commit(); + } catch (EntityDoesNotExistException e) { + throw new CommandException(String.format(MESSAGE_INVALID_USER, userNameToUpdate)); + } catch (Exception e) { + e.printStackTrace(); + } + return new CommandResult(String.format(MESSAGE_SUCCESS, userNameToUpdate, userPassToUpdate)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/AnnounceCommand.java b/src/main/java/com/t13g2/forum/logic/commands/AnnounceCommand.java new file mode 100644 index 000000000000..086769916ac6 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/AnnounceCommand.java @@ -0,0 +1,66 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ANNOUNCE_CONTENT; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ANNOUNCE_TITLE; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.model.ShowAnnouncementEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.model.forum.User; + +//@@author xllx1 +/** + * Announce new announcement. + */ +public class AnnounceCommand extends Command { + + public static final String COMMAND_WORD = "announce"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Post new announcement. " + + "\nParameters: " + + PREFIX_ANNOUNCE_TITLE + "TITLE " + + PREFIX_ANNOUNCE_CONTENT + "CONTENT " + + "\nExample: " + COMMAND_WORD + " " + + PREFIX_ANNOUNCE_TITLE + "Urgent! " + + PREFIX_ANNOUNCE_CONTENT + "System maintenance from tomorrow 3PM to 5PM."; + + public static final String MESSAGE_SUCCESS = "New announcement posted: %1$s"; + + private final Announcement toAnnounce; + + /** + * Creates an AnnounceCommand to announce the specified {@code toAnnounce}. + */ + public AnnounceCommand(Announcement toAnnounce) { + requireNonNull(toAnnounce); + this.toAnnounce = toAnnounce; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } else if (!Context.getInstance().isCurrentUserAdmin()) { + throw new CommandException(User.MESSAGE_NOT_ADMIN); + } + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + toAnnounce.setCreatedByUserId(Context.getInstance().getCurrentUser().getId()); + unitOfWork.getAnnouncementRepository().addAnnouncement(toAnnounce); + unitOfWork.commit(); + EventsCenter.getInstance().post(new ShowAnnouncementEvent(toAnnounce.getTitle(), toAnnounce.getContent())); + } catch (Exception e) { + e.printStackTrace(); + } + return new CommandResult(String.format(MESSAGE_SUCCESS, toAnnounce)); + } +} + diff --git a/src/main/java/com/t13g2/forum/logic/commands/BlockUserFromCreatingCommand.java b/src/main/java/com/t13g2/forum/logic/commands/BlockUserFromCreatingCommand.java new file mode 100644 index 000000000000..61bdc467f78e --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/BlockUserFromCreatingCommand.java @@ -0,0 +1,85 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_BLOCK; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author xllx1 +/** + * Allow admin to block user from posting a new thread. + */ +public class BlockUserFromCreatingCommand extends Command { + + public static final String COMMAND_WORD = "blockUser"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Blocks a certain user from posting new thread." + + "\nParameters: " + + PREFIX_USER_NAME + "USER NAME " + + PREFIX_BLOCK + "BLOCK OR UNBLOCK" + + "\nExample: " + COMMAND_WORD + " " + + PREFIX_USER_NAME + "john " + + PREFIX_BLOCK + "true"; + + public static final String MESSAGE_SUCCESS = "User %1$s successfully: %2$s"; + public static final String MESSAGE_USER_IS_ADMIN = "The user \"%s\" is an admin, no point blocking."; + public static final String MESSAGE_INVALID_USER = "The user \"%s\" does not exist."; + public static final String MESSAGE_DUPLICATE_BLOCK = "The user \"%s\" has already been blocked."; + public static final String MESSAGE_DUPLICATE_UNBLOCK = "The user \"%s\" has not been block."; + public static final String MESSAGE_BLOCK_CONSTRAINTS = "Invalid parameter: block can only take true or false."; + + private final String userNameToBlock; + private final boolean block; + + /** + * Creates an BlockUserFromCreatingCommand to block the specified {@code User} + */ + public BlockUserFromCreatingCommand(String userName, boolean block) { + requireNonNull(userName); + requireNonNull(block); + userNameToBlock = userName; + this.block = block; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + User user = null; + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } else if (!Context.getInstance().isCurrentUserAdmin()) { + throw new CommandException(User.MESSAGE_NOT_ADMIN); + } + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + user = unitOfWork.getUserRepository().getUserByUsername(userNameToBlock); + if (user.isAdmin()) { + throw new CommandException(String.format(MESSAGE_USER_IS_ADMIN, userNameToBlock)); + } else if (block && user.isBlock()) { + throw new CommandException(String.format(MESSAGE_DUPLICATE_BLOCK, userNameToBlock)); + } else if (!block && !user.isBlock()) { + throw new CommandException(String.format(MESSAGE_DUPLICATE_UNBLOCK, userNameToBlock)); + } else { + user.setBlock(block); + unitOfWork.getUserRepository().updateUser(user); + unitOfWork.commit(); + } + } catch (CommandException e) { + throw e; + } catch (EntityDoesNotExistException e) { + throw new CommandException(String.format(MESSAGE_INVALID_USER, userNameToBlock)); + } catch (Exception e) { + e.printStackTrace(); + } + return new CommandResult(String.format(MESSAGE_SUCCESS, (block ? "blocked" : "unblocked"), userNameToBlock)); + } + +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/CheckAnnouncmentCommand.java b/src/main/java/com/t13g2/forum/logic/commands/CheckAnnouncmentCommand.java new file mode 100644 index 000000000000..56b0785f8727 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/CheckAnnouncmentCommand.java @@ -0,0 +1,52 @@ +package com.t13g2.forum.logic.commands; + +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.model.ShowAnnouncementEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author xllx1 +/** + * Allow user to check if there is any announcement + */ +public class CheckAnnouncmentCommand extends Command { + public static final String COMMAND_WORD = "checkAnnounce"; + + public static final String MESSAGE_SUCCESS = "Showing new announcement: %1$s"; + public static final String MESSAGE_FAIL = "There is no announcement at the moment"; + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + Announcement announcement = null; + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } + + Announcement latestAnnouncement = null; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + latestAnnouncement = unitOfWork.getAnnouncementRepository().getLatestAnnouncement(); + } catch (EntityDoesNotExistException e) { + latestAnnouncement = null; + } catch (Exception e) { + e.printStackTrace(); + } + + if (latestAnnouncement != null) { + EventsCenter.getInstance().post(new ShowAnnouncementEvent(latestAnnouncement.getTitle(), + latestAnnouncement.getContent())); + } else { + throw new CommandException(MESSAGE_FAIL); + } + return new CommandResult(String.format(MESSAGE_SUCCESS, latestAnnouncement)); + } +} diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/com/t13g2/forum/logic/commands/ClearCommand.java similarity index 65% rename from src/main/java/seedu/address/logic/commands/ClearCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/ClearCommand.java index 1f85bcfe85a8..b9671f0fbdab 100644 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/ClearCommand.java @@ -1,10 +1,10 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; -import seedu.address.logic.CommandHistory; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.Model; /** * Clears the address book. @@ -18,8 +18,8 @@ public class ClearCommand extends Command { @Override public CommandResult execute(Model model, CommandHistory history) { requireNonNull(model); - model.resetData(new AddressBook()); - model.commitAddressBook(); + model.resetData(new ForumBook()); + model.commitForumBook(); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/com/t13g2/forum/logic/commands/Command.java similarity index 76% rename from src/main/java/seedu/address/logic/commands/Command.java rename to src/main/java/com/t13g2/forum/logic/commands/Command.java index 34e99d786ec6..5daf90395cbf 100644 --- a/src/main/java/seedu/address/logic/commands/Command.java +++ b/src/main/java/com/t13g2/forum/logic/commands/Command.java @@ -1,8 +1,8 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; -import seedu.address.logic.CommandHistory; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Model; /** * Represents a command with hidden internal logic and the ability to be executed. diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/com/t13g2/forum/logic/commands/CommandResult.java similarity index 88% rename from src/main/java/seedu/address/logic/commands/CommandResult.java rename to src/main/java/com/t13g2/forum/logic/commands/CommandResult.java index abdc267a2c44..21395d081dac 100644 --- a/src/main/java/seedu/address/logic/commands/CommandResult.java +++ b/src/main/java/com/t13g2/forum/logic/commands/CommandResult.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; diff --git a/src/main/java/com/t13g2/forum/logic/commands/CreateCommentCommand.java b/src/main/java/com/t13g2/forum/logic/commands/CreateCommentCommand.java new file mode 100644 index 000000000000..2773bd1b3c93 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/CreateCommentCommand.java @@ -0,0 +1,93 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_BLOCKED_USER; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_THREAD_ID; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_LOGIN; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_CONTENT; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_ID; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author HansKoh +/** + * Create a new comment to the forum book under certain module + */ +public class CreateCommentCommand extends Command { + public static final String COMMAND_WORD = "createComment"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Creates a comment to a thread. " + + "\nParameters: " + + PREFIX_THREAD_ID + "THREAD ID " + + PREFIX_COMMENT_CONTENT + "COMMENT...\n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_THREAD_ID + "1 " + + PREFIX_COMMENT_CONTENT + "This is a new comment"; + + public static final String MESSAGE_SUCCESS = "New comment added: %1$s"; + private final int threadId; + private final String contentToAdd; + private Comment comment; + private int moduleId; + private int commentId; + + /** + * Creates a CreateCommentCommand to create the specified {@code Comment} + */ + public CreateCommentCommand(int threadId, String contentToAdd) { + requireNonNull(threadId); + requireNonNull(contentToAdd); + this.threadId = threadId; + this.contentToAdd = contentToAdd; + this.comment = new Comment(); //instantiate a new comment + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(MESSAGE_NOT_LOGIN); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + if (Context.getInstance().isCurrentUserBlocked()) { + throw new CommandException(MESSAGE_BLOCKED_USER); + } + //get the respective module by moduleCode + ForumThread forumThread = unitOfWork.getForumThreadRepository().getThread(threadId); + comment.setThreadId(forumThread.getId()); //set thread ID to the comment + comment.setCreatedByUserId(Context.getInstance().getCurrentUser().getId()); //set owner ID to the comment + comment.setContent(contentToAdd); //pass content to the comment + commentId = comment.getId(); + moduleId = forumThread.getModuleId(); + //add this comment to unitOfWork meaning save it to the memory repository + unitOfWork.getCommentRepository().addComment(comment); + unitOfWork.commit(); //commit meaning add the forum thread update to local database + } catch (EntityDoesNotExistException e) { + throw new CommandException(MESSAGE_INVALID_THREAD_ID); + } catch (CommandException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + } + String message = "\n" + + "Module ID: " + moduleId + "\n" + + "Thread ID: " + threadId + "\n" + + "Comment ID: " + commentId + "\n" + + "Comment Content: " + contentToAdd; + return new CommandResult(String.format(MESSAGE_SUCCESS, message)); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof CreateCommentCommand // instanceof handles nulls + && comment.equals(((CreateCommentCommand) other).comment)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/CreateModuleCommand.java b/src/main/java/com/t13g2/forum/logic/commands/CreateModuleCommand.java new file mode 100644 index 000000000000..220155b0c0c5 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/CreateModuleCommand.java @@ -0,0 +1,78 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_TITLE; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author xllx1 +/** + * Creates a module to the forum book by admin + */ +public class CreateModuleCommand extends Command { + public static final String COMMAND_WORD = "createModule"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Creates a module. " + + "\nParameters: " + + PREFIX_MODULE_CODE + "MODULE CODE " + + PREFIX_MODULE_TITLE + "MODULE TITLE " + + "\nExample: " + COMMAND_WORD + " " + + PREFIX_MODULE_CODE + "CS2113 " + + PREFIX_MODULE_TITLE + "Software Engineering and OOP"; + + public static final String MESSAGE_SUCCESS = "%1$s now is added to module"; + public static final String MESSAGE_DUPLICATE_MODULE = "%1$s has been added previously"; + + private final Module moduleToAdd; + + /** + * Creates an CreateModuleCommand to create the specified {@code module}. + */ + public CreateModuleCommand(Module module) { + requireNonNull(module); + moduleToAdd = module; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } else if (!Context.getInstance().isCurrentUserAdmin()) { + throw new CommandException(User.MESSAGE_NOT_ADMIN); + } + + boolean exist = true; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().getModuleByCode(moduleToAdd.getModuleCode()); + throw new CommandException(String.format(MESSAGE_DUPLICATE_MODULE, + moduleToAdd.getModuleCode())); + } catch (CommandException e) { + throw e; + } catch (EntityDoesNotExistException e) { + exist = false; + } catch (Exception e) { + e.printStackTrace(); + } + + if (!exist) { + try (UnitOfWork unitOfWork = new UnitOfWork()) { + moduleToAdd.setCreatedByUserId(Context.getInstance().getCurrentUser().getId()); + unitOfWork.getModuleRepository().addModule(moduleToAdd); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + return new CommandResult(String.format(MESSAGE_SUCCESS, moduleToAdd.getModuleCode())); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/CreateThreadCommand.java b/src/main/java/com/t13g2/forum/logic/commands/CreateThreadCommand.java new file mode 100644 index 000000000000..a896b880f410 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/CreateThreadCommand.java @@ -0,0 +1,97 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_BLOCKED_USER; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_MODULE_CODE; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_LOGIN; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_CONTENT; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_TITLE; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author HansKoh +/** + * Create a new thread to the forum book under certain module + */ +public class CreateThreadCommand extends Command { + + public static final String COMMAND_WORD = "createThread"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Creates a thread to the forum book. " + + "\nParameters: " + + PREFIX_MODULE_CODE + "MODULE CODE " + + PREFIX_THREAD_TITLE + "THREAD TITLE " + + PREFIX_COMMENT_CONTENT + "COMMENT...\n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_MODULE_CODE + "CS2113 " + + PREFIX_THREAD_TITLE + "EXAM DISCUSSION " + + PREFIX_COMMENT_CONTENT + "Hi fellows, what is the topic coverage for the final?"; + + public static final String MESSAGE_SUCCESS = "New thread added: %1$s"; + private String moduleCode; + private ForumThread forumThread; + private Comment comment; + + /** + * Creates a CreateThreadCommand to create the specified {@code ForumThread} + */ + public CreateThreadCommand(String moduleCode, ForumThread forumThread, Comment comment) { + requireNonNull(moduleCode); + requireNonNull(forumThread); + requireNonNull(comment); + this.moduleCode = moduleCode; + this.forumThread = forumThread; + this.comment = comment; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(MESSAGE_NOT_LOGIN); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + if (Context.getInstance().isCurrentUserBlocked()) { + throw new CommandException(MESSAGE_BLOCKED_USER); + } + //get the respective module by moduleCode + Module module = unitOfWork.getModuleRepository().getModuleByCode(moduleCode); + forumThread.setModuleId(module.getId()); //pass the module ID to this forum thread + forumThread.setCreatedByUserId(Context.getInstance().getCurrentUser().getId()); + comment.setThreadId(forumThread.getId()); //pass the thread ID to this comment + comment.setCreatedByUserId(Context.getInstance().getCurrentUser().getId()); + //add this forum thread to unitOfWork meaning save it to the memory repository + unitOfWork.getForumThreadRepository().addThread(forumThread); + //add this comment to unitOfWork meaning save it to the memory repository + unitOfWork.getCommentRepository().addComment(comment); + unitOfWork.commit(); //commit meaning add the forum thread update to local database + } catch (EntityDoesNotExistException e) { + throw new CommandException(MESSAGE_INVALID_MODULE_CODE); + } catch (CommandException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + } + String message = "\n" + + "Module: " + moduleCode + "\n" + + "Thread Title: " + forumThread.getTitle() + "\n" + + "Comment: " + comment.getContent(); + return new CommandResult(String.format(MESSAGE_SUCCESS, message)); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof CreateThreadCommand // instanceof handles nulls + && forumThread.equals(((CreateThreadCommand) other).forumThread)); + } +} diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/com/t13g2/forum/logic/commands/DeleteCommand.java similarity index 82% rename from src/main/java/seedu/address/logic/commands/DeleteCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/DeleteCommand.java index a20e9d49eac7..76a015d7721e 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/DeleteCommand.java @@ -1,15 +1,15 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; import java.util.List; -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.CommandHistory; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.person.Person; /** * Deletes a person identified using it's displayed index from the address book. @@ -42,7 +42,7 @@ public CommandResult execute(Model model, CommandHistory history) throws Command Person personToDelete = lastShownList.get(targetIndex.getZeroBased()); model.deletePerson(personToDelete); - model.commitAddressBook(); + model.commitForumBook(); return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete)); } diff --git a/src/main/java/com/t13g2/forum/logic/commands/DeleteCommentCommand.java b/src/main/java/com/t13g2/forum/logic/commands/DeleteCommentCommand.java new file mode 100644 index 000000000000..0068ef5c5ffa --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/DeleteCommentCommand.java @@ -0,0 +1,84 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_COMMENT; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_COMMENT_ID; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_COMMENT_OWNER; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_LOGIN; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_ID; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + + +//@@author HansKoh +/** + * Delete a certain comment. Only admin could delete comments from others, + * user could only delete comment created by his/her own. + */ +public class DeleteCommentCommand extends Command { + public static final String COMMAND_WORD = "deleteComment"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Delete a certain comment under corresponding module and thread\n" + + "Parameters: " + + PREFIX_COMMENT_ID + "COMMENT ID \n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_COMMENT_ID + "1"; + + public static final String MESSAGE_SUCCESS = "Comment deleted successfully! %1$s"; + private final int commentIdToDelete; + private String currentModuleCode; + private int currentModuleId; + private int threadId; + /** + * Creates an DeleteCommentCommand to delete the specified {@code Comment} + */ + public DeleteCommentCommand(int commentIdToDelete) { + requireNonNull(commentIdToDelete); + this.commentIdToDelete = commentIdToDelete; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(MESSAGE_NOT_LOGIN); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + threadId = unitOfWork.getCommentRepository().getComment(commentIdToDelete).getThreadId(); + currentModuleId = Context.getInstance().getCurrentModuleId(); + if (Context.getInstance().getCurrentThreadId() != threadId) { + throw new CommandException(MESSAGE_INVALID_COMMENT); + } + Comment commentToDelete = unitOfWork.getCommentRepository().getComment(commentIdToDelete); + if (Context.getInstance().getCurrentUser().getId() == commentToDelete.getCreatedByUserId() + || Context.getInstance().isCurrentUserAdmin()) { + //delete the comment according to the commentId from the memory repository + unitOfWork.getCommentRepository().deleteComment(commentIdToDelete); + //update to local database + unitOfWork.commit(); + currentModuleCode = unitOfWork.getModuleRepository().getModule(currentModuleId).getModuleCode(); + } else { + throw new CommandException(MESSAGE_NOT_COMMENT_OWNER); + } + } catch (EntityDoesNotExistException e) { + throw new CommandException(MESSAGE_INVALID_COMMENT_ID); + } catch (CommandException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + } + String deleteMessage = "\n\n" + + "Under Module Code: " + currentModuleCode + "\n" + + "Under Thread ID: " + Context.getInstance().getCurrentThreadId() + "\n" + + "Deleted Comment ID: " + commentIdToDelete + "\n"; + + return new CommandResult(String.format(MESSAGE_SUCCESS, deleteMessage)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/DeleteModuleCommand.java b/src/main/java/com/t13g2/forum/logic/commands/DeleteModuleCommand.java new file mode 100644 index 000000000000..4cb79d4bae90 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/DeleteModuleCommand.java @@ -0,0 +1,66 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author xllx1 + +/** + * Deletes a module to the forum book by admin + */ +public class DeleteModuleCommand extends Command { + public static final String COMMAND_WORD = "deleteModule"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes a module. " + + "\nParameters: " + + PREFIX_MODULE_CODE + "MODULE CODE " + + "\nExample: " + COMMAND_WORD + " " + + PREFIX_MODULE_CODE + "CS2113"; + + public static final String MESSAGE_SUCCESS = "%1$s is now deleted."; + public static final String MESSAGE_INVALID_MODULE = "There is no module matching %1$s."; + + private final String moduleCodeToDelete; + + /** + * Creates an DeleteModuleCommand to create the specified {@code module}. + */ + public DeleteModuleCommand(String moduleCode) { + requireNonNull(moduleCode); + moduleCodeToDelete = moduleCode; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + // if user has not login or is not admin, then throw exception + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } else if (!Context.getInstance().isCurrentUserAdmin()) { + throw new CommandException(User.MESSAGE_NOT_ADMIN); + } + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + Module moduleToDelete = unitOfWork.getModuleRepository().getModuleByCode(moduleCodeToDelete); + unitOfWork.getModuleRepository().removeModule(moduleToDelete); + unitOfWork.commit(); + } catch (EntityDoesNotExistException e) { + throw new CommandException(String.format(MESSAGE_INVALID_MODULE, + moduleCodeToDelete)); + } catch (Exception e) { + e.printStackTrace(); + } + Context.getInstance().setCurrentModuleId(-1); + return new CommandResult(String.format(MESSAGE_SUCCESS, moduleCodeToDelete)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/DeleteThreadCommand.java b/src/main/java/com/t13g2/forum/logic/commands/DeleteThreadCommand.java new file mode 100644 index 000000000000..3676aae1b03b --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/DeleteThreadCommand.java @@ -0,0 +1,81 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_THREAD; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_THREAD_ID; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_LOGIN; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_THREAD_OWNER; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_ID; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author HansKoh +/** + * Delete a certain thread. Only admin could delete threads from others, + * user could only delete threads created by his/her own. + */ +public class DeleteThreadCommand extends Command { + public static final String COMMAND_WORD = "deleteThread"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Delete a certain thread under corresponding module\n" + + "Parameters: " + + PREFIX_THREAD_ID + "THREAD ID \n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_THREAD_ID + "1"; + + public static final String MESSAGE_SUCCESS = "Thread deleted successfully! %1$s"; + private final int threadId; + private int moduleId; + private String moduleCode; + + /** + * Creates an DeleteThreadCommand to delete the specified {@code ForumThread} + */ + public DeleteThreadCommand(int threadId) { + requireNonNull(threadId); + this.threadId = threadId; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(MESSAGE_NOT_LOGIN); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + moduleId = unitOfWork.getForumThreadRepository().getThread(threadId).getModuleId(); + moduleCode = unitOfWork.getModuleRepository().getModule(moduleId).getModuleCode(); + if (Context.getInstance().getCurrentModuleId() != moduleId) { + throw new CommandException(MESSAGE_INVALID_THREAD); + } + if (Context.getInstance().getCurrentUser().getId() + == unitOfWork.getForumThreadRepository().getThread(threadId).getCreatedByUserId() + || Context.getInstance().isCurrentUserAdmin()) { + //delete the thread according to the threadId from the memory repository + unitOfWork.getForumThreadRepository().deleteThread(threadId); + //update to local database + unitOfWork.commit(); + } else { + throw new CommandException(MESSAGE_NOT_THREAD_OWNER); + } + } catch (EntityDoesNotExistException e) { + throw new CommandException(MESSAGE_INVALID_THREAD_ID); + } catch (CommandException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + } + Context.getInstance().setCurrentThreadId(-1); + String deletedMessage = "\n\n" + + "Under Module Code: " + moduleCode + "\n" + + "Deleted Thread ID: " + threadId + "\n"; + + return new CommandResult(String.format(MESSAGE_SUCCESS, deletedMessage)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/DeleteUserCommand.java b/src/main/java/com/t13g2/forum/logic/commands/DeleteUserCommand.java new file mode 100644 index 000000000000..77b75c48f11b --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/DeleteUserCommand.java @@ -0,0 +1,68 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.model.UserLoginEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author e0191729 +/** + * Self deletes a user from the ForumBook + */ +public class DeleteUserCommand extends Command { + public static final String COMMAND_WORD = "deleteUser"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes a certain user. " + + "\nParameters: " + + PREFIX_USER_NAME + "USER NAME " + + "\nExample: " + COMMAND_WORD + " " + + PREFIX_USER_NAME + "john "; + + public static final String MESSAGE_SUCCESS = "%1$s successfully deleted."; + public static final String MESSAGE_INVALID_USER = "No user named %1$s found. Please try again!"; + + private final String userNameToDelete; + + /** + * Creates an DeleteUserCommand to delete the specified {@code userName}. + */ + public DeleteUserCommand(String uName) { + requireNonNull(uName); + this.userNameToDelete = uName; + } + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + // if user has not login or is not admin, then throw exception + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } else if (!Context.getInstance().isCurrentUserAdmin()) { + throw new CommandException(User.MESSAGE_NOT_ADMIN); + } + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + User userToDelete = unitOfWork.getUserRepository().getUserByUsername(userNameToDelete); + unitOfWork.getUserRepository().deleteUser(userToDelete); + unitOfWork.commit(); + } catch (EntityDoesNotExistException e) { + throw new CommandException(String.format(MESSAGE_INVALID_USER, userNameToDelete)); + } catch (Exception e) { + e.printStackTrace(); + } + + String currentUserName = Context.getInstance().getCurrentUser().getUsername(); + if (userNameToDelete.equals(currentUserName)) { + EventsCenter.getInstance().post(new UserLoginEvent("", false, false)); + } + return new CommandResult(String.format(MESSAGE_SUCCESS, userNameToDelete)); + } +} diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/com/t13g2/forum/logic/commands/EditCommand.java similarity index 87% rename from src/main/java/seedu/address/logic/commands/EditCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/EditCommand.java index dc782d8e230f..074beee3f237 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/EditCommand.java @@ -1,12 +1,11 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_EMAIL; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_PHONE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_TAG; 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_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 java.util.Collections; import java.util.HashSet; @@ -14,18 +13,18 @@ import java.util.Optional; import java.util.Set; -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.commons.util.CollectionUtil; -import seedu.address.logic.CommandHistory; -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.tag.Tag; +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.commons.util.CollectionUtil; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.person.Address; +import com.t13g2.forum.model.person.Email; +import com.t13g2.forum.model.person.Name; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.model.person.Phone; +import com.t13g2.forum.model.tag.Tag; /** * Edits the details of an existing person in the address book. @@ -83,8 +82,8 @@ public CommandResult execute(Model model, CommandHistory history) throws Command } model.updatePerson(personToEdit, editedPerson); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - model.commitAddressBook(); + model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); + model.commitForumBook(); return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson)); } diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/com/t13g2/forum/logic/commands/ExitCommand.java similarity index 66% rename from src/main/java/seedu/address/logic/commands/ExitCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/ExitCommand.java index e848fa918964..42f6e4fe3a4c 100644 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/ExitCommand.java @@ -1,9 +1,9 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; -import seedu.address.commons.core.EventsCenter; -import seedu.address.commons.events.ui.ExitAppRequestEvent; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.ui.ExitAppRequestEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; /** * Terminates the program. diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/com/t13g2/forum/logic/commands/FindCommand.java similarity index 85% rename from src/main/java/seedu/address/logic/commands/FindCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/FindCommand.java index beb178e3a3f5..020ee6b6aec4 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/FindCommand.java @@ -1,11 +1,11 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; -import seedu.address.commons.core.Messages; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.person.NameContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/com/t13g2/forum/logic/commands/HelpCommand.java similarity index 72% rename from src/main/java/seedu/address/logic/commands/HelpCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/HelpCommand.java index 66305e95d8f2..e2123edaac34 100644 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/HelpCommand.java @@ -1,9 +1,9 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; -import seedu.address.commons.core.EventsCenter; -import seedu.address.commons.events.ui.ShowHelpRequestEvent; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.ui.ShowHelpRequestEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; /** * Format full help instructions for every command for display. diff --git a/src/main/java/seedu/address/logic/commands/HistoryCommand.java b/src/main/java/com/t13g2/forum/logic/commands/HistoryCommand.java similarity index 88% rename from src/main/java/seedu/address/logic/commands/HistoryCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/HistoryCommand.java index f1541fb57f20..fab698ab18f0 100644 --- a/src/main/java/seedu/address/logic/commands/HistoryCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/HistoryCommand.java @@ -1,12 +1,12 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; import java.util.Collections; import java.util.List; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; /** * Lists all the commands entered by user from the start of app launch. diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/com/t13g2/forum/logic/commands/ListCommand.java similarity index 64% rename from src/main/java/seedu/address/logic/commands/ListCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/ListCommand.java index 6d44824c7d1b..04e5721b75c5 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/ListCommand.java @@ -1,10 +1,9 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; /** * Lists all persons in the address book to the user. @@ -19,7 +18,7 @@ public class ListCommand extends Command { @Override public CommandResult execute(Model model, CommandHistory history) { requireNonNull(model); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/com/t13g2/forum/logic/commands/ListModuleCommand.java b/src/main/java/com/t13g2/forum/logic/commands/ListModuleCommand.java new file mode 100644 index 000000000000..dc6cdf01e4c6 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/ListModuleCommand.java @@ -0,0 +1,46 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_LOGIN; +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.util.DisplayFormatter; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Module; + +//@@author HansKoh +/** + * List out all the modules in the forum book. + */ +public class ListModuleCommand extends Command { + public static final String COMMAND_WORD = "listModule"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": List all the modules in the forum book.\n" + + "Example: " + COMMAND_WORD + " "; + + public static final String MESSAGE_SUCCESS = "Listed all modules: \n" + + "****************************************************************************\n" + + "****************************************************************************\n" + + "%s"; + private static String message; + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(MESSAGE_NOT_LOGIN); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + List moduleList = unitOfWork.getModuleRepository().getAllModule(); + message = DisplayFormatter.displayModuleList(moduleList); + } catch (Exception e) { + e.printStackTrace(); + } + return new CommandResult(String.format(MESSAGE_SUCCESS, message)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/LoginCommand.java b/src/main/java/com/t13g2/forum/logic/commands/LoginCommand.java new file mode 100644 index 000000000000..841ef7f94410 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/LoginCommand.java @@ -0,0 +1,71 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_PASSWORD; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.model.UserLoginEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author e0191729 +/** + * Login to the ForumBook + */ +public class LoginCommand extends Command { + public static final String COMMAND_WORD = "login"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": login to forum book. " + + "\nParameters: " + + PREFIX_USER_NAME + "USER NAME " + + PREFIX_USER_PASSWORD + "PASSWORD \n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_USER_NAME + "John Doe " + + PREFIX_USER_PASSWORD + "1234 "; + + + public static final String MESSAGE_SUCCESS = "WELCOME : %1$s"; + public static final String MESSAGE_FAIL = "No user named %s found or password is wrong"; + public static final String MESSAGE_USER_ACTIVE = "Hi %s, Please logout before trying to login. Thank you"; + private final String userName; + private final String userPassword; + private boolean empty; + + public LoginCommand(String userName, String userPassword) { + requireNonNull(userName); + requireNonNull(userPassword); + this.userName = userName; + this.userPassword = userPassword; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + User exist = null; + if (Context.getInstance().getCurrentUser() == null) { + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + exist = unitOfWork.getUserRepository().authenticate(userName, userPassword); + } catch (EntityDoesNotExistException e) { + exist = null; + } catch (Exception e) { + e.printStackTrace(); + } + if (exist != null) { + Context.getInstance().setCurrentUser(exist); + EventsCenter.getInstance().post(new UserLoginEvent(userName, exist.isAdmin(), exist.isBlock())); + return new CommandResult(String.format(MESSAGE_SUCCESS, userName)); + } else { + EventsCenter.getInstance().post(new UserLoginEvent("", false, false)); + throw new CommandException(String.format(MESSAGE_FAIL, userName)); + } + } else { + return new CommandResult(String.format(MESSAGE_USER_ACTIVE, userName)); + } + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/LogoutCommand.java b/src/main/java/com/t13g2/forum/logic/commands/LogoutCommand.java new file mode 100644 index 000000000000..29d15c019516 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/LogoutCommand.java @@ -0,0 +1,46 @@ +package com.t13g2.forum.logic.commands; + +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.model.UserLoginEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; + +//@@author e0191729 +/** + *LogOut of ForumBook + */ +public class LogoutCommand extends Command { + public static final String COMMAND_WORD = "logout"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": logout from the forum book. "; + + + public static final String MESSAGE_SUCCESS = "Good bye : %1$s"; + public static final String MESSAGE_FAIL = "No user logged in to Logout"; + private String userName; + private Boolean canLogout; + + public LogoutCommand() { + if (Context.getInstance().getCurrentUser() != null) { + this.userName = Context.getInstance().getCurrentUser().getUsername(); + Context.getInstance().setCurrentUser(null); + canLogout = true; + } else { + canLogout = false; + } + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + if (canLogout) { + EventsCenter.getInstance().post(new UserLoginEvent("", false, false)); + return new CommandResult(String.format(MESSAGE_SUCCESS, userName)); + } else { + return new CommandResult(String.format(MESSAGE_FAIL, userName)); + } + } +} diff --git a/src/main/java/seedu/address/logic/commands/RedoCommand.java b/src/main/java/com/t13g2/forum/logic/commands/RedoCommand.java similarity index 62% rename from src/main/java/seedu/address/logic/commands/RedoCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/RedoCommand.java index 227771a4eef6..baa7bbeaed92 100644 --- a/src/main/java/seedu/address/logic/commands/RedoCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/RedoCommand.java @@ -1,11 +1,10 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; -import seedu.address.logic.CommandHistory; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Model; /** * Reverts the {@code model}'s address book to its previously undone state. @@ -20,12 +19,12 @@ public class RedoCommand extends Command { public CommandResult execute(Model model, CommandHistory history) throws CommandException { requireNonNull(model); - if (!model.canRedoAddressBook()) { + if (!model.canRedoForumBook()) { throw new CommandException(MESSAGE_FAILURE); } - model.redoAddressBook(); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + model.redoForumBook(); + model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/seedu/address/logic/commands/SelectCommand.java b/src/main/java/com/t13g2/forum/logic/commands/SelectCommand.java similarity index 78% rename from src/main/java/seedu/address/logic/commands/SelectCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/SelectCommand.java index f5e8c1a8722e..3139bb1e6b70 100644 --- a/src/main/java/seedu/address/logic/commands/SelectCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/SelectCommand.java @@ -1,17 +1,17 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; import java.util.List; -import seedu.address.commons.core.EventsCenter; -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.commons.events.ui.JumpToListRequestEvent; -import seedu.address.logic.CommandHistory; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.commons.events.ui.JumpToListRequestEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.person.Person; /** * Selects a person identified using it's displayed index from the address book. diff --git a/src/main/java/com/t13g2/forum/logic/commands/SelectModuleCommand.java b/src/main/java/com/t13g2/forum/logic/commands/SelectModuleCommand.java new file mode 100644 index 000000000000..2d6c6a289aef --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/SelectModuleCommand.java @@ -0,0 +1,65 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_MODULE_CODE; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_LOGIN; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.util.DisplayFormatter; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author HansKoh +/** + * List out all the threads under certain module in the forum book. + */ +public class SelectModuleCommand extends Command { + public static final String COMMAND_WORD = "selectModule"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": List all the threads under certain module in the forum book.\n" + + "Parameters: " + + PREFIX_MODULE_CODE + "MODULE CODE" + + "\nExample: " + + COMMAND_WORD + " " + + PREFIX_MODULE_CODE + "CS2113"; + + private static String message; + private static String moduleCode; + + public SelectModuleCommand(String moduleCode) { + requireNonNull(moduleCode); + this.moduleCode = moduleCode; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + String messageSuccess = "Listed all threads under Module Code: " + moduleCode + "\n" + + "****************************************************************************\n" + + "****************************************************************************\n" + + "%s"; + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(MESSAGE_NOT_LOGIN); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + Module module = unitOfWork.getModuleRepository().getModuleByCode(moduleCode); + List threadList = unitOfWork.getForumThreadRepository().getThreadsByModule(module); + message = DisplayFormatter.diplayThreadList(threadList); + Context.getInstance().setCurrentModuleId(module.getId()); + } catch (EntityDoesNotExistException e) { + throw new CommandException(MESSAGE_INVALID_MODULE_CODE); + } catch (Exception e) { + e.printStackTrace(); + } + return new CommandResult(String.format(messageSuccess, message)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/SelectThreadCommand.java b/src/main/java/com/t13g2/forum/logic/commands/SelectThreadCommand.java new file mode 100644 index 000000000000..0f5429a81e7e --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/SelectThreadCommand.java @@ -0,0 +1,72 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_THREAD_ID; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_LOGIN; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_ID; +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.util.DisplayFormatter; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author HansKoh +/** + * List out all the comments under certain thread in the forum book. + */ +public class SelectThreadCommand extends Command { + public static final String COMMAND_WORD = "selectThread"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": List out all the comments under certain thread in the forum book.\n" + + "Parameters: " + + PREFIX_THREAD_ID + "THREAD ID" + + "\nExample: " + + COMMAND_WORD + " " + + PREFIX_THREAD_ID + "1"; + + private static String message; + private static int threadId; + private static int moduleId; + private static String threadTitle; + private static String moduleCode; + + public SelectThreadCommand(int threadId) { + requireNonNull(threadId); + this.threadId = threadId; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + String messageSuccess = "Listed all comments under \n" + + "Module Code: %s\n" + + "Thread ID : %s\n" + + "Thread Title : %s\n" + + "****************************************************************************\n" + + "****************************************************************************\n" + + "%s"; + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(MESSAGE_NOT_LOGIN); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + moduleId = unitOfWork.getForumThreadRepository().getThread(threadId).getModuleId(); + moduleCode = unitOfWork.getModuleRepository().getModule(moduleId).getModuleCode(); + List commentList = unitOfWork.getCommentRepository().getCommentsByThread(threadId); + message = DisplayFormatter.displayCommentList(commentList); + threadTitle = unitOfWork.getForumThreadRepository().getThread(threadId).getTitle(); + Context.getInstance().setCurrentThreadId(unitOfWork.getForumThreadRepository().getThread(threadId).getId()); + } catch (EntityDoesNotExistException e) { + throw new CommandException(MESSAGE_INVALID_THREAD_ID); + } catch (Exception e) { + e.printStackTrace(); + } + return new CommandResult(String.format(messageSuccess, moduleCode, threadId, threadTitle, message)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/SetAdminCommand.java b/src/main/java/com/t13g2/forum/logic/commands/SetAdminCommand.java new file mode 100644 index 000000000000..f0e85888830e --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/SetAdminCommand.java @@ -0,0 +1,94 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ADMIN_SET; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author xllx1 +/** + * Set a certain user as admin or set the admin as user + */ +public class SetAdminCommand extends Command { + public static final String COMMAND_WORD = "setAdmin"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Set/Revert (true/false) a user as admin. " + + "\nParameters: " + + PREFIX_USER_NAME + "USER NAME " + + PREFIX_ADMIN_SET + "SET/REVERT " + + "\nExample: " + COMMAND_WORD + " " + + PREFIX_USER_NAME + "john " + + PREFIX_ADMIN_SET + "true "; + + public static final String MESSAGE_SUCCESS = "%1$s now is %2$s."; + public static final String MESSAGE_FAILED = "You cannot set/revert yourself."; + public static final String MESSAGE_INVALID_USER = "The user \"%1$s\" does not exist."; + public static final String MESSAGE_USER_BLOCKED = + "The user \"%1$s\" is blocked, please unblock in order to set admin."; + public static final String MESSAGE_DUPLICATE_SET = "The user \"%1$s\" is already an admin."; + public static final String MESSAGE_DUPLICATE_REVERT = "%1$s is not an admin, unable to revert."; + public static final String MESSAGE_SET_CONSTRAINTS = "Invalid parameter: set can only take true or false."; + + private final String userNametoSetAdmin; + private final boolean setAdmin; + + /** + * Creates an SetAdminCommand to set the specified {@code userName}. + */ + public SetAdminCommand(String userName, boolean set) { + requireNonNull(userName); + userNametoSetAdmin = userName; + setAdmin = set; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + String isAdmin = "an admin"; + User userToSet = null; + + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } else if (!Context.getInstance().isCurrentUserAdmin()) { + throw new CommandException(User.MESSAGE_NOT_ADMIN); + } + + if (Context.getInstance().getCurrentUser().getUsername().equals(userNametoSetAdmin)) { + return new CommandResult(MESSAGE_FAILED); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + userToSet = unitOfWork.getUserRepository().getUserByUsername(userNametoSetAdmin); + if (setAdmin && userToSet.isBlock()) { + throw new CommandException(String.format(MESSAGE_USER_BLOCKED, userNametoSetAdmin)); + } + if (setAdmin && userToSet.isAdmin()) { + throw new CommandException(String.format(MESSAGE_DUPLICATE_SET, userNametoSetAdmin)); + } else if (!setAdmin && !userToSet.isAdmin()) { + throw new CommandException(String.format(MESSAGE_DUPLICATE_REVERT, userNametoSetAdmin)); + } else { + userToSet.setAdmin(!userToSet.isAdmin()); + unitOfWork.getUserRepository().updateUser(userToSet); + unitOfWork.commit(); + } + + if (!setAdmin) { + isAdmin = "a user"; + } + } catch (CommandException e) { + throw e; + } catch (EntityDoesNotExistException e) { + throw new CommandException(String.format(MESSAGE_INVALID_USER, userNametoSetAdmin)); + } catch (Exception e) { + e.printStackTrace(); + } + return new CommandResult(String.format(MESSAGE_SUCCESS, userNametoSetAdmin, isAdmin)); + } +} diff --git a/src/main/java/seedu/address/logic/commands/UndoCommand.java b/src/main/java/com/t13g2/forum/logic/commands/UndoCommand.java similarity index 61% rename from src/main/java/seedu/address/logic/commands/UndoCommand.java rename to src/main/java/com/t13g2/forum/logic/commands/UndoCommand.java index 40441264f346..4883feb64459 100644 --- a/src/main/java/seedu/address/logic/commands/UndoCommand.java +++ b/src/main/java/com/t13g2/forum/logic/commands/UndoCommand.java @@ -1,11 +1,10 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; -import seedu.address.logic.CommandHistory; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Model; /** * Reverts the {@code model}'s address book to its previous state. @@ -20,12 +19,12 @@ public class UndoCommand extends Command { public CommandResult execute(Model model, CommandHistory history) throws CommandException { requireNonNull(model); - if (!model.canUndoAddressBook()) { + if (!model.canUndoForumBook()) { throw new CommandException(MESSAGE_FAILURE); } - model.undoAddressBook(); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + model.undoForumBook(); + model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/com/t13g2/forum/logic/commands/UpdateCommentCommand.java b/src/main/java/com/t13g2/forum/logic/commands/UpdateCommentCommand.java new file mode 100644 index 000000000000..e4765a7b3e06 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/UpdateCommentCommand.java @@ -0,0 +1,93 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_BLOCKED_USER; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_COMMENT; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_COMMENT_ID; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_COMMENT_OWNER; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_LOGIN; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_CONTENT; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_ID; + +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author HansKoh +/** + * Update a existing comment content in the forum book + * Only unblocked user could only update comment content created by his/her own. + */ +public class UpdateCommentCommand extends Command { + public static final String COMMAND_WORD = "updateComment"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Update an existing comment title created by its user(Unblocked) in the forum book.\n" + + "Parameters: " + + PREFIX_COMMENT_ID + "COMMENT ID" + + PREFIX_COMMENT_CONTENT + "COMMENT CONTENT" + + "\nExample: " + + COMMAND_WORD + " " + + PREFIX_COMMENT_ID + "123 " + + PREFIX_COMMENT_CONTENT + "This is a new comment"; + + public static final String MESSAGE_SUCCESS = "Comment content updated successfully! %1$s"; + private static int commentIdToUpdate; + private static String contentToUpdate; + private int currentModuleId; + private int currentThreadId; + private String currentModuleCode; + + public UpdateCommentCommand(int commentIdToUpdate, String contentToUpdate) { + requireNonNull(commentIdToUpdate); + requireNonNull(contentToUpdate); + this.commentIdToUpdate = commentIdToUpdate; + this.contentToUpdate = contentToUpdate; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(MESSAGE_NOT_LOGIN); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + if (Context.getInstance().isCurrentUserBlocked()) { + throw new CommandException(MESSAGE_BLOCKED_USER); + } + currentThreadId = Context.getInstance().getCurrentThreadId(); + currentModuleId = Context.getInstance().getCurrentModuleId(); + currentModuleCode = unitOfWork.getModuleRepository().getModule(currentModuleId).getModuleCode(); + Comment comment = unitOfWork.getCommentRepository().getComment(commentIdToUpdate); + if (currentThreadId != comment.getThreadId()) { + throw new CommandException(MESSAGE_INVALID_COMMENT); + } + if (Context.getInstance().getCurrentUser().getId() == comment.getCreatedByUserId() + || Context.getInstance().isCurrentUserAdmin()) { + comment.setContent(contentToUpdate); + unitOfWork.getCommentRepository().updateComment(comment); + unitOfWork.commit(); + } else { + throw new CommandException(MESSAGE_NOT_COMMENT_OWNER); + } + + } catch (EntityDoesNotExistException e) { + throw new CommandException(MESSAGE_INVALID_COMMENT_ID); + } catch (CommandException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + } + String updateMessage = "\n\n" + + "Under Module Code: " + currentModuleCode + "\n" + + "Under Thread ID: " + currentThreadId + "\n" + + "Updated Comment ID: " + commentIdToUpdate + "\n" + + "Updated Comment Content: " + contentToUpdate + "\n"; + return new CommandResult(String.format(MESSAGE_SUCCESS, updateMessage)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/UpdateModuleCommand.java b/src/main/java/com/t13g2/forum/logic/commands/UpdateModuleCommand.java new file mode 100644 index 000000000000..f6a4142211ce --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/UpdateModuleCommand.java @@ -0,0 +1,85 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_ID; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_TITLE; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author xllx1 + +/** + * Creates a module to the forum book by admin + */ +public class UpdateModuleCommand extends Command { + public static final String COMMAND_WORD = "updateModule"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Updates a module. " + + "\nNote: either one of mCode and mTitle or both must be provided" + + "\nParameters: " + + PREFIX_MODULE_ID + "MODULE ID " + + "[" + PREFIX_MODULE_CODE + "MODULE CODE " + "]" + + "[" + PREFIX_MODULE_TITLE + "MODULE TITLE " + "]" + + "\nExample: " + COMMAND_WORD + " " + + PREFIX_MODULE_ID + "1 " + + "[" + PREFIX_MODULE_CODE + "CS2113 " + "]" + + "[" + PREFIX_MODULE_TITLE + "Software Engineering and OOP" + "]"; + + public static final String MESSAGE_SUCCESS = "The module is now updated to\n" + + "Module Code: %s\nModule Title: %s"; + public static final String MESSAGE_INVALID_MODULE_ID = "Invalid module id: %1$s."; + + private final int moduleIdToUpdate; + private final String moduleCodeToUpdate; + private final String moduleTitleToUpdate; + + /** + * Creates an UpdateModuleCommand to create the specified {@code module}. + */ + public UpdateModuleCommand(int moduleId, String moduleCode, String moduleTitle) { + requireNonNull(moduleId); + moduleIdToUpdate = moduleId; + moduleCodeToUpdate = moduleCode; + moduleTitleToUpdate = moduleTitle; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } else if (!Context.getInstance().isCurrentUserAdmin()) { + throw new CommandException(User.MESSAGE_NOT_ADMIN); + } + + Module moduleToUpdate = null; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + moduleToUpdate = unitOfWork.getModuleRepository().getModule(moduleIdToUpdate); + if (!moduleCodeToUpdate.equals("")) { + moduleToUpdate.setModuleCode(moduleCodeToUpdate); + } + if (!moduleTitleToUpdate.equals("")) { + moduleToUpdate.setTitle(moduleTitleToUpdate); + } + unitOfWork.getModuleRepository().updateModule(moduleToUpdate); + unitOfWork.commit(); + } catch (CommandException e) { + throw e; + } catch (EntityDoesNotExistException e) { + throw new CommandException(String.format(MESSAGE_INVALID_MODULE_ID, moduleIdToUpdate)); + } catch (Exception e) { + e.printStackTrace(); + } + return new CommandResult(String.format(MESSAGE_SUCCESS, moduleToUpdate.getModuleCode(), + moduleToUpdate.getTitle())); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/UpdateThreadCommand.java b/src/main/java/com/t13g2/forum/logic/commands/UpdateThreadCommand.java new file mode 100644 index 000000000000..09282f92e156 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/UpdateThreadCommand.java @@ -0,0 +1,89 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_BLOCKED_USER; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_THREAD; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_THREAD_ID; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_LOGIN; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_NOT_THREAD_OWNER; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_ID; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_TITLE; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +//@@author HansKoh +/** + * Update an existing thread title in the forum book + * Only unblocked user could update thread title created by his/her own. + */ +public class UpdateThreadCommand extends Command { + public static final String COMMAND_WORD = "updateThread"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Update an existing thread title created by its user(Unblocked) in the forum book.\n" + + "Parameters: " + + PREFIX_THREAD_ID + "THREAD ID" + + PREFIX_THREAD_TITLE + "THREAD TITLE" + + "\nExample: " + + COMMAND_WORD + " " + + PREFIX_THREAD_ID + "123 " + + PREFIX_THREAD_TITLE + "This is a new title"; + + public static final String MESSAGE_SUCCESS = "Thread title updated successfully! %1$s"; + private static int threadIdToUpdate; + private static String threadTitleToUpdate; + private String moduleCode; + private int moduleId; + + public UpdateThreadCommand(int threadIdToUpdate, String threadTitleToUpdate) { + requireNonNull(threadIdToUpdate); + requireNonNull(threadTitleToUpdate); + this.threadIdToUpdate = threadIdToUpdate; + this.threadTitleToUpdate = threadTitleToUpdate; + } + + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(MESSAGE_NOT_LOGIN); + } + try (UnitOfWork unitOfWork = new UnitOfWork()) { + if (Context.getInstance().isCurrentUserBlocked()) { + throw new CommandException(MESSAGE_BLOCKED_USER); + } + ForumThread forumThread = unitOfWork.getForumThreadRepository().getThread(threadIdToUpdate); + moduleId = unitOfWork.getForumThreadRepository().getThread(threadIdToUpdate).getModuleId(); + moduleCode = unitOfWork.getModuleRepository().getModule(moduleId).getModuleCode(); + if (Context.getInstance().getCurrentModuleId() != moduleId) { + throw new CommandException(MESSAGE_INVALID_THREAD); + } + if (Context.getInstance().getCurrentUser().getId() == forumThread.getCreatedByUserId() + || Context.getInstance().isCurrentUserAdmin()) { + forumThread.setTitle(threadTitleToUpdate); + unitOfWork.getForumThreadRepository().updateThread(forumThread); + unitOfWork.commit(); + } else { + throw new CommandException(MESSAGE_NOT_THREAD_OWNER); + } + } catch (EntityDoesNotExistException e) { + throw new CommandException(MESSAGE_INVALID_THREAD_ID); + } catch (CommandException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + } + String updateMessage = "\n\n" + + "Under Module Code: " + moduleCode + "\n" + + "Updated Thread ID: " + threadIdToUpdate + "\n" + + "Updated Thread Title: " + threadTitleToUpdate + "\n"; + + return new CommandResult(String.format(MESSAGE_SUCCESS, updateMessage)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/UpdateUserOldCommand.java b/src/main/java/com/t13g2/forum/logic/commands/UpdateUserOldCommand.java new file mode 100644 index 000000000000..6eccaa0eebdd --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/UpdateUserOldCommand.java @@ -0,0 +1,59 @@ +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +/** + * Deletes a specific user by admin + */ +public class UpdateUserOldCommand extends Command { + public static final String COMMAND_WORD = "updateUser"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Update a certain user's password, email and/or phone. " + + "Parameters: " + + PREFIX_USER_NAME + "USER NAME " + + "Example: " + COMMAND_WORD + " " + + PREFIX_USER_NAME + "john "; + + public static final String MESSAGE_SUCCESS = "%1$s successfully updated."; + public static final String MESSAGE_INVALID_USER = "No user named %1$s found. Please verify and try again!"; + + private final String userNameToUpdate = ""; + private final Person userToUpdate; + + /** + * Creates an DeleteUserCommand to delete the specified {@code userName}. + */ + public UpdateUserOldCommand(Person personToUpdate) { + requireNonNull(personToUpdate); + this.userToUpdate = personToUpdate; + } + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + // if user has not login or is not admin, then throw exception + // if user has not login or is not admin, then throw exception + if (!Context.getInstance().isLoggedIn()) { + throw new CommandException(User.MESSAGE_NOT_LOGIN); + } + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + User userToUpdate = unitOfWork.getUserRepository().getUserByUsername(userNameToUpdate); + } catch (EntityDoesNotExistException e) { + throw new CommandException(String.format(MESSAGE_INVALID_USER, userNameToUpdate)); + } catch (Exception e) { + e.printStackTrace(); + } + //model.updatePerson(userNameToUpdate); + return new CommandResult(String.format(MESSAGE_SUCCESS, userNameToUpdate)); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/commands/UserDeleteCommand.java b/src/main/java/com/t13g2/forum/logic/commands/UserDeleteCommand.java new file mode 100644 index 000000000000..5cde2ed2998c --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/commands/UserDeleteCommand.java @@ -0,0 +1,45 @@ +package com.t13g2.forum.logic.commands; + +import static java.util.Objects.requireNonNull; + +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.model.UserLoginEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.User; + +/** + * + */ +public class UserDeleteCommand extends Command { + public static final String COMMAND_WORD = "deleteMe"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Self delete user from the forum book. "; + + public static final String MESSAGE_SUCCESS = "It was nice knowing you! Good bye %1$s :("; + public static final String MESSAGE_FAIL = "No user logged in for Self Delete"; + + + private String userName; + @Override + public CommandResult execute(Model model, CommandHistory history) throws CommandException { + requireNonNull(model); + if (Context.getInstance().getCurrentUser() != null) { + try (UnitOfWork unitOfWork = new UnitOfWork()) { + User userToDelete = Context.getInstance().getCurrentUser(); + userName = userToDelete.getUsername(); + unitOfWork.getUserRepository().deleteUser(userToDelete); + unitOfWork.commit(); + Context.getInstance().setCurrentUser(null); + } catch (Exception e) { + e.printStackTrace(); + } + EventsCenter.getInstance().post(new UserLoginEvent("", false, false)); + return new CommandResult(String.format(MESSAGE_SUCCESS, userName)); + } else { + return new CommandResult(String.format(MESSAGE_FAIL, userName)); + } + } +} diff --git a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java b/src/main/java/com/t13g2/forum/logic/commands/exceptions/CommandException.java similarity index 81% rename from src/main/java/seedu/address/logic/commands/exceptions/CommandException.java rename to src/main/java/com/t13g2/forum/logic/commands/exceptions/CommandException.java index a16bd14f2cde..acdd356a6d6e 100644 --- a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java +++ b/src/main/java/com/t13g2/forum/logic/commands/exceptions/CommandException.java @@ -1,4 +1,6 @@ -package seedu.address.logic.commands.exceptions; +package com.t13g2.forum.logic.commands.exceptions; + +import com.t13g2.forum.logic.commands.Command; /** * Represents an error which occurs during execution of a {@link Command}. diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/AddCommandParser.java similarity index 65% rename from src/main/java/seedu/address/logic/parser/AddCommandParser.java rename to src/main/java/com/t13g2/forum/logic/parser/AddCommandParser.java index 3b8bfa035e83..26797710b267 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/com/t13g2/forum/logic/parser/AddCommandParser.java @@ -1,23 +1,23 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_EMAIL; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_PHONE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_TAG; import java.util.Set; import java.util.stream.Stream; -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.tag.Tag; +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.AddCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.person.Address; +import com.t13g2.forum.model.person.Email; +import com.t13g2.forum.model.person.Name; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.model.person.Phone; +import com.t13g2.forum.model.tag.Tag; /** * Parses input arguments and creates a new AddCommand object @@ -35,7 +35,7 @@ public AddCommand parse(String args) throws ParseException { if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) || !argMultimap.getPreamble().isEmpty()) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()); diff --git a/src/main/java/com/t13g2/forum/logic/parser/AddUserCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/AddUserCommandParser.java new file mode 100644 index 000000000000..be083af833a1 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/AddUserCommandParser.java @@ -0,0 +1,45 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_PASSWORD; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.AddUserCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.forum.User; + +/** + * + */ +public class AddUserCommandParser { + /** + * Parses the given {@code String} of arguments in the context of the LoginCommand + * and returns an LoginCommand object for execution. + * + * @throws ParseException if the user input does not conform the expected format + */ + public AddUserCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_USER_NAME, PREFIX_USER_PASSWORD); + + if (!arePrefixesPresent(argMultimap, PREFIX_USER_NAME, PREFIX_USER_PASSWORD) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + AddUserCommand.MESSAGE_USAGE)); + } + + String userName = ParserUtil.parseUserName(argMultimap.getValue(PREFIX_USER_NAME).get()); + String userPassword = ParserUtil.parseUserPassword(argMultimap.getValue(PREFIX_USER_PASSWORD).get()); + boolean admin = false; + if (userName.equals("admin")) { + admin = true; + } + User user = new User (userName, userPassword, admin, false, " ", " "); + return new AddUserCommand(user); + } + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/AddressBookParser.java b/src/main/java/com/t13g2/forum/logic/parser/AddressBookParser.java new file mode 100644 index 000000000000..fff87f2bfbfe --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/AddressBookParser.java @@ -0,0 +1,173 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.t13g2.forum.logic.commands.AddUserCommand; +import com.t13g2.forum.logic.commands.AdminUpdatePasswordCommand; +import com.t13g2.forum.logic.commands.AnnounceCommand; +import com.t13g2.forum.logic.commands.BlockUserFromCreatingCommand; +import com.t13g2.forum.logic.commands.CheckAnnouncmentCommand; +import com.t13g2.forum.logic.commands.Command; +import com.t13g2.forum.logic.commands.CreateCommentCommand; +import com.t13g2.forum.logic.commands.CreateModuleCommand; +import com.t13g2.forum.logic.commands.CreateThreadCommand; +import com.t13g2.forum.logic.commands.DeleteCommentCommand; +import com.t13g2.forum.logic.commands.DeleteModuleCommand; +import com.t13g2.forum.logic.commands.DeleteThreadCommand; +import com.t13g2.forum.logic.commands.DeleteUserCommand; +import com.t13g2.forum.logic.commands.EditCommand; +import com.t13g2.forum.logic.commands.ExitCommand; +import com.t13g2.forum.logic.commands.HelpCommand; +import com.t13g2.forum.logic.commands.HistoryCommand; +import com.t13g2.forum.logic.commands.ListModuleCommand; +import com.t13g2.forum.logic.commands.LoginCommand; +import com.t13g2.forum.logic.commands.LogoutCommand; +import com.t13g2.forum.logic.commands.SelectModuleCommand; +import com.t13g2.forum.logic.commands.SelectThreadCommand; +import com.t13g2.forum.logic.commands.SetAdminCommand; +import com.t13g2.forum.logic.commands.UpdateCommentCommand; +import com.t13g2.forum.logic.commands.UpdateModuleCommand; +import com.t13g2.forum.logic.commands.UpdateThreadCommand; +import com.t13g2.forum.logic.commands.UserDeleteCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +/** + * Parses user input. + */ +public class AddressBookParser { + + /** + * Used for initial separation of command word and args. + */ + private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)"); + + /** + * Parses user input into command for execution. + * + * @param userInput full user input string + * @return the command based on the user input + * @throws ParseException if the user input does not conform the expected format + */ + public Command parseCommand(String userInput) throws ParseException { + final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim()); + if (!matcher.matches()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); + } + + final String commandWord = matcher.group("commandWord"); + final String arguments = matcher.group("arguments"); + switch (commandWord) { + + // case AddCommand.COMMAND_WORD: + // return new AddCommandParser().parse(arguments); + // + case EditCommand.COMMAND_WORD: + return new UpdateUserCommandParser().parse(arguments); + // + // case SelectCommand.COMMAND_WORD: + // return new SelectCommandParser().parse(arguments); + // + // case DeleteCommand.COMMAND_WORD: + // return new DeleteCommandParser().parse(arguments); + // + // case ClearCommand.COMMAND_WORD: + // return new ClearCommand(); + // + // case FindCommand.COMMAND_WORD: + // return new FindCommandParser().parse(arguments); + // + // case ListCommand.COMMAND_WORD: + // return new ListCommand(); + + case HistoryCommand.COMMAND_WORD: + return new HistoryCommand(); + + case ExitCommand.COMMAND_WORD: + return new ExitCommand(); + + case HelpCommand.COMMAND_WORD: + return new HelpCommand(); + + // case UndoCommand.COMMAND_WORD: + // return new UndoCommand(); + // + // case RedoCommand.COMMAND_WORD: + // return new RedoCommand(); + + case AnnounceCommand.COMMAND_WORD: + return new AnnounceCommandParser().parse(arguments); + + case CheckAnnouncmentCommand.COMMAND_WORD: + return new CheckAnnouncmentCommand(); + + case BlockUserFromCreatingCommand.COMMAND_WORD: + return new BlockUserFromPostingCommandParser().parse(arguments); + + case SetAdminCommand.COMMAND_WORD: + return new SetAdminCommandParser().parse(arguments); + + case AdminUpdatePasswordCommand.COMMAND_WORD: + return new AdminUpdatePasswordCommandParser().parse(arguments); + + case CreateModuleCommand.COMMAND_WORD: + return new CreateModuleCommandParser().parse(arguments); + + case DeleteModuleCommand.COMMAND_WORD: + return new DeleteModuleCommandParser().parse(arguments); + + case DeleteUserCommand.COMMAND_WORD: + return new DeleteUserCommandParser().parse(arguments); + + case UpdateModuleCommand.COMMAND_WORD: + return new UpdateModuleCommandParser().parse(arguments); + + //@@author HansKoh + case CreateThreadCommand.COMMAND_WORD: + return new CreateThreadCommandParser().parse(arguments); + + case CreateCommentCommand.COMMAND_WORD: + return new CreateCommentCommandParser().parse(arguments); + + case UpdateThreadCommand.COMMAND_WORD: + return new UpdateThreadCommandParser().parse(arguments); + + case UpdateCommentCommand.COMMAND_WORD: + return new UpdateCommentCommandParser().parse(arguments); + + case DeleteThreadCommand.COMMAND_WORD: + return new DeleteThreadCommandParser().parse(arguments); + + case DeleteCommentCommand.COMMAND_WORD: + return new DeleteCommentCommandParser().parse(arguments); + + case ListModuleCommand.COMMAND_WORD: + return new ListModuleCommand(); + + case SelectModuleCommand.COMMAND_WORD: + return new SelectModuleCommandParser().parse(arguments); + + case SelectThreadCommand.COMMAND_WORD: + return new SelectThreadCommandParser().parse(arguments); + + case LoginCommand.COMMAND_WORD: + return new LoginCommandParser().parse(arguments); + + case AddUserCommand.COMMAND_WORD: + return new AddUserCommandParser().parse(arguments); + + case LogoutCommand.COMMAND_WORD: + return new LogoutCommand(); + + case UserDeleteCommand.COMMAND_WORD: + return new UserDeleteCommand(); + + default: + throw new ParseException(MESSAGE_UNKNOWN_COMMAND); + } + } + +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/AdminUpdatePasswordCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/AdminUpdatePasswordCommandParser.java new file mode 100644 index 000000000000..93b7f356df1f --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/AdminUpdatePasswordCommandParser.java @@ -0,0 +1,45 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_PASSWORD; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.AdminUpdatePasswordCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author xllx1 +/** + * Parses input arguments and creates a new AdminUpdatePasswordCommand object. + */ +public class AdminUpdatePasswordCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the AdminUpdatePasswordCommand. + * and returns an AdminUpdatePasswordCommand object for execution. + * + * @throws ParseException if the user input does not conform the expected format + */ + public AdminUpdatePasswordCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_USER_NAME, PREFIX_USER_PASSWORD); + if (!arePrefixesPresent(argMultimap, PREFIX_USER_NAME, PREFIX_USER_PASSWORD) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + AdminUpdatePasswordCommand.MESSAGE_USAGE)); + } + + String userName = ParserUtil.parseUserName(argMultimap.getValue(PREFIX_USER_NAME).get()); + String userPassword = ParserUtil.parseUserPassword(argMultimap.getValue(PREFIX_USER_PASSWORD).get()); + + return new AdminUpdatePasswordCommand(userName, userPassword); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/AnnounceCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/AnnounceCommandParser.java new file mode 100644 index 000000000000..cab6f5287e2d --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/AnnounceCommandParser.java @@ -0,0 +1,48 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ANNOUNCE_CONTENT; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ANNOUNCE_TITLE; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.AnnounceCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.forum.Announcement; + +//@@author xllx1 +/** + * Parses input arguments and creates a new AnnounceCommand object. + */ +public class AnnounceCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the AnnounceCommand. + * and returns an AnnounceCommand object for execution. + * + * @throws ParseException if the user input does not conform the expected format + */ + public AnnounceCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_ANNOUNCE_TITLE, PREFIX_ANNOUNCE_CONTENT); + if (!arePrefixesPresent(argMultimap, PREFIX_ANNOUNCE_TITLE, PREFIX_ANNOUNCE_CONTENT) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + AnnounceCommand.MESSAGE_USAGE)); + } + + Announcement announcement = ParserUtil.parseAnnouncement(argMultimap.getValue(PREFIX_ANNOUNCE_TITLE).get(), + argMultimap.getValue(PREFIX_ANNOUNCE_CONTENT).get()); + + return new AnnounceCommand(announcement); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } + +} diff --git a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java b/src/main/java/com/t13g2/forum/logic/parser/ArgumentMultimap.java similarity index 98% rename from src/main/java/seedu/address/logic/parser/ArgumentMultimap.java rename to src/main/java/com/t13g2/forum/logic/parser/ArgumentMultimap.java index 954c8e18f8ea..afbf7641b309 100644 --- a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java +++ b/src/main/java/com/t13g2/forum/logic/parser/ArgumentMultimap.java @@ -1,4 +1,4 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java b/src/main/java/com/t13g2/forum/logic/parser/ArgumentTokenizer.java similarity index 99% rename from src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java rename to src/main/java/com/t13g2/forum/logic/parser/ArgumentTokenizer.java index 5c9aebfa4888..87fac0cb1a4b 100644 --- a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java +++ b/src/main/java/com/t13g2/forum/logic/parser/ArgumentTokenizer.java @@ -1,4 +1,4 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; import java.util.ArrayList; import java.util.Arrays; diff --git a/src/main/java/com/t13g2/forum/logic/parser/BlockUserFromPostingCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/BlockUserFromPostingCommandParser.java new file mode 100644 index 000000000000..d5ef2e8711d6 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/BlockUserFromPostingCommandParser.java @@ -0,0 +1,52 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_BLOCK; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.BlockUserFromCreatingCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author xllx1 +/** + * Parses input arguments and block a certain user from posting. + */ +public class BlockUserFromPostingCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the BlockUserFromCreatingCommand. + * and returns an BlockUserFromCreatingCommand object for execution. + * + * @throws ParseException if the user input does not conform the expected format + */ + public BlockUserFromCreatingCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_USER_NAME, PREFIX_BLOCK); + if (!arePrefixesPresent(argMultimap, PREFIX_USER_NAME, PREFIX_BLOCK) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + BlockUserFromCreatingCommand.MESSAGE_USAGE)); + } + String userName = ParserUtil.parseUserName(argMultimap.getValue(PREFIX_USER_NAME).get()); + boolean block; + if (argMultimap.getValue(PREFIX_BLOCK).get().equals("true")) { + block = true; + } else if (argMultimap.getValue(PREFIX_BLOCK).get().equals("false")) { + block = false; + } else { + throw new ParseException(BlockUserFromCreatingCommand.MESSAGE_BLOCK_CONSTRAINTS); + } + + return new BlockUserFromCreatingCommand(userName, block); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } + +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/CliSyntax.java b/src/main/java/com/t13g2/forum/logic/parser/CliSyntax.java new file mode 100644 index 000000000000..bcd0e443400e --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/CliSyntax.java @@ -0,0 +1,43 @@ +package com.t13g2.forum.logic.parser; + +/** + * Contains Command Line Interface (CLI) syntax definitions common to multiple commands + */ +public class CliSyntax { + + /* Prefix definitions */ + public static final Prefix PREFIX_NAME = new Prefix("n/"); + public static final Prefix PREFIX_PHONE = new Prefix("p/"); + public static final Prefix PREFIX_EMAIL = new Prefix("e/"); + public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); + public static final Prefix PREFIX_TAG = new Prefix("t/"); + + public static final Prefix PREFIX_COMMENT = new Prefix("c/"); + public static final Prefix PREFIX_INDEX = new Prefix("i/"); + public static final Prefix PREFIX_MODULE = new Prefix("m/"); + public static final Prefix PREFIX_THREAD = new Prefix("th/"); + /* Prefix for Announcement */ + public static final Prefix PREFIX_ANNOUNCE_TITLE = new Prefix("aTitle/"); + public static final Prefix PREFIX_ANNOUNCE_CONTENT = new Prefix("aContent/"); + /* Prefix for Thread */ + public static final Prefix PREFIX_THREAD_ID = new Prefix("tId/"); + public static final Prefix PREFIX_THREAD_TITLE = new Prefix("tTitle/"); + /* Prefix for User */ + public static final Prefix PREFIX_USER_ID = new Prefix("uID/"); + public static final Prefix PREFIX_USER_NAME = new Prefix("uName/"); + public static final Prefix PREFIX_USER_PASSWORD = new Prefix("uPass/"); + public static final Prefix PREFIX_USER_EMAIL = new Prefix("uEmail/"); + public static final Prefix PREFIX_USER_PHONE = new Prefix("uPhone/"); + public static final Prefix PREFIX_USER_IS_ADMIN = new Prefix("uAdmin/"); + /* Prefix for Module */ + public static final Prefix PREFIX_MODULE_ID = new Prefix("mId/"); + public static final Prefix PREFIX_MODULE_TITLE = new Prefix("mTitle/"); + public static final Prefix PREFIX_MODULE_CODE = new Prefix("mCode/"); + /* Prefix for Comment */ + public static final Prefix PREFIX_COMMENT_CONTENT = new Prefix("cContent/"); + public static final Prefix PREFIX_COMMENT_ID = new Prefix("cId/"); + /* Prefix for setAdmin */ + public static final Prefix PREFIX_ADMIN_SET = new Prefix("set/"); + /* Prefix for blockUser */ + public static final Prefix PREFIX_BLOCK = new Prefix("block/"); +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/CreateCommentCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/CreateCommentCommandParser.java new file mode 100644 index 000000000000..d1d1a2e59c3d --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/CreateCommentCommandParser.java @@ -0,0 +1,47 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_CONTENT; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_ID; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.CreateCommentCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author HansKoh +/** + * Parses input arguments and creates a new CreateCommentCommand object + */ +public class CreateCommentCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the CreateCommentCommand + * and returns an CreateCommentCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public CreateCommentCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_THREAD_ID, PREFIX_COMMENT_CONTENT); + + if (!arePrefixesPresent(argMultimap, PREFIX_THREAD_ID, PREFIX_COMMENT_CONTENT) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + CreateCommentCommand.MESSAGE_USAGE)); + } + + int threadId = Integer.parseInt(ParserUtil.parseThreadId(argMultimap.getValue(PREFIX_THREAD_ID).get())); + String commentToAdd = ParserUtil.parseComment(argMultimap.getValue(PREFIX_COMMENT_CONTENT).get()); + + return new CreateCommentCommand(threadId, commentToAdd); + + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/CreateModuleCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/CreateModuleCommandParser.java new file mode 100644 index 000000000000..756fe39733de --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/CreateModuleCommandParser.java @@ -0,0 +1,46 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_TITLE; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.CreateModuleCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.forum.Module; + +//@@author xllx1 +/** + * Parses input arguments and create a module to forum book. + */ +public class CreateModuleCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the CreateModuleCommand + * and returns an CreateModuleCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public CreateModuleCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_MODULE_TITLE, PREFIX_MODULE_CODE); + + if (!arePrefixesPresent(argMultimap, PREFIX_MODULE_TITLE, PREFIX_MODULE_CODE) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + CreateModuleCommand.MESSAGE_USAGE)); + } + + String moduleCode = ParserUtil.parseModule(argMultimap.getValue(PREFIX_MODULE_CODE).get()); + String moduleTitle = ParserUtil.parseModuleTitle(argMultimap.getValue(PREFIX_MODULE_TITLE).get()); + + return new CreateModuleCommand(new Module(moduleTitle, moduleCode)); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/CreateThreadCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/CreateThreadCommandParser.java new file mode 100644 index 000000000000..d0c27f4cb95a --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/CreateThreadCommandParser.java @@ -0,0 +1,57 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_CONTENT; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_TITLE; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.CreateThreadCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; + +//@@author HansKoh +/** + * Parses input arguments and creates a new CreateThreadCommand object + */ +public class CreateThreadCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the CreateThreadCommand + * and returns an CreateThreadCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public CreateThreadCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_MODULE_CODE, PREFIX_THREAD_TITLE, PREFIX_COMMENT_CONTENT); + + if (!arePrefixesPresent(argMultimap, PREFIX_MODULE_CODE, PREFIX_COMMENT_CONTENT, PREFIX_THREAD_TITLE) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + CreateThreadCommand.MESSAGE_USAGE)); + } + + String moduleCode = ParserUtil.parseModule(argMultimap.getValue(PREFIX_MODULE_CODE).get()); + String threadTitle = ParserUtil.parseThread(argMultimap.getValue(PREFIX_THREAD_TITLE).get()); + String commentContent = ParserUtil.parseComment(argMultimap.getValue(PREFIX_COMMENT_CONTENT).get()); + + ForumThread forumThread = new ForumThread(); //instantiate a new forum thread + forumThread.setTitle(threadTitle); //pass the thread title to this new forum thread + + Comment comment = new Comment(); //instantiate a new comment + comment.setContent(commentContent); //pass the comment content to this new comment + + return new CreateThreadCommand(moduleCode, forumThread, comment); + + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/DeleteCommandParser.java similarity index 63% rename from src/main/java/seedu/address/logic/parser/DeleteCommandParser.java rename to src/main/java/com/t13g2/forum/logic/parser/DeleteCommandParser.java index 4d1f4bb0e4ec..c03d4d83ba80 100644 --- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java +++ b/src/main/java/com/t13g2/forum/logic/parser/DeleteCommandParser.java @@ -1,10 +1,10 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.logic.commands.DeleteCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.parser.exceptions.ParseException; /** * Parses input arguments and creates a new DeleteCommand object @@ -22,8 +22,7 @@ public DeleteCommand parse(String args) throws ParseException { return new DeleteCommand(index); } catch (ParseException pe) { throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe); + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe); } } - } diff --git a/src/main/java/com/t13g2/forum/logic/parser/DeleteCommentCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/DeleteCommentCommandParser.java new file mode 100644 index 000000000000..b5f691fe037f --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/DeleteCommentCommandParser.java @@ -0,0 +1,44 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_ID; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.DeleteCommentCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + + +//@@author HansKoh +/** + * Parses input arguments and creates a new DeleteCommentCommand object + */ +public class DeleteCommentCommandParser { + /** + * Parses the given {@code String} of arguments in the context of the DeleteCommand + * and returns an DeleteCommentCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public DeleteCommentCommand parse(String args) throws ParseException { + + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_COMMENT_ID); + + if (!arePrefixesPresent(argMultimap, PREFIX_COMMENT_ID) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + DeleteCommentCommand.MESSAGE_USAGE)); + } + int commentId = Integer.parseInt(ParserUtil.parseCommentId(argMultimap.getValue(PREFIX_COMMENT_ID).get())); + + return new DeleteCommentCommand(commentId); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/DeleteModuleCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/DeleteModuleCommandParser.java new file mode 100644 index 000000000000..44c906a8df90 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/DeleteModuleCommandParser.java @@ -0,0 +1,43 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.DeleteModuleCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author xllx1 +/** + * Parses input arguments and deletes a module from forum book. + */ +public class DeleteModuleCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the DeleteModuleCommand + * and returns an DeleteModuleCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public DeleteModuleCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_MODULE_CODE); + + if (!arePrefixesPresent(argMultimap, PREFIX_MODULE_CODE) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + DeleteModuleCommand.MESSAGE_USAGE)); + } + + String moduleCode = ParserUtil.parseModule(argMultimap.getValue(PREFIX_MODULE_CODE).get()); + + return new DeleteModuleCommand(moduleCode); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/DeleteThreadCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/DeleteThreadCommandParser.java new file mode 100644 index 000000000000..f5d59b7abbbb --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/DeleteThreadCommandParser.java @@ -0,0 +1,44 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_ID; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.DeleteThreadCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author HansKoh +/** + * Parses input arguments and creates a new DeleteThreadCommand object + */ +public class DeleteThreadCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the DeleteCommand + * and returns an DeleteCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public DeleteThreadCommand parse(String args) throws ParseException { + + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_THREAD_ID); + + if (!arePrefixesPresent(argMultimap, PREFIX_THREAD_ID) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + DeleteThreadCommand.MESSAGE_USAGE)); + } + int threadId = Integer.parseInt(ParserUtil.parseThreadId(argMultimap.getValue(PREFIX_THREAD_ID).get())); + + return new DeleteThreadCommand(threadId); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/DeleteUserCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/DeleteUserCommandParser.java new file mode 100644 index 000000000000..ee4ed86acaca --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/DeleteUserCommandParser.java @@ -0,0 +1,44 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.DeleteUserCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author xllx1 + +/** + * Parses input arguments and deletes a user from forum book. + */ +public class DeleteUserCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the DeleteUserCommand + * and returns an DeleteUserCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public DeleteUserCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_USER_NAME); + + if (!arePrefixesPresent(argMultimap, PREFIX_USER_NAME) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + DeleteUserCommand.MESSAGE_USAGE)); + } + + String userName = ParserUtil.parseUserName(argMultimap.getValue(PREFIX_USER_NAME).get()); + + return new DeleteUserCommand(userName); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/FindCommandParser.java similarity index 66% rename from src/main/java/seedu/address/logic/parser/FindCommandParser.java rename to src/main/java/com/t13g2/forum/logic/parser/FindCommandParser.java index b186a967cb94..d990ba1e9bf3 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/com/t13g2/forum/logic/parser/FindCommandParser.java @@ -1,12 +1,12 @@ -package seedu.address.logic.parser; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +package com.t13g2.forum.logic.parser; import java.util.Arrays; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.FindCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.person.NameContainsKeywordsPredicate; + /** * Parses input arguments and creates a new FindCommand object @@ -22,7 +22,7 @@ public FindCommand parse(String args) throws ParseException { String trimmedArgs = args.trim(); if (trimmedArgs.isEmpty()) { throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); } String[] nameKeywords = trimmedArgs.split("\\s+"); diff --git a/src/main/java/com/t13g2/forum/logic/parser/LoginCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/LoginCommandParser.java new file mode 100644 index 000000000000..3a92004ca81c --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/LoginCommandParser.java @@ -0,0 +1,41 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_PASSWORD; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.LoginCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +/** + * + */ +public class LoginCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the LoginCommand + * and returns an LoginCommand object for execution. + * + * @throws ParseException if the user input does not conform the expected format + */ + public LoginCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_USER_NAME, PREFIX_USER_PASSWORD); + + if (!arePrefixesPresent(argMultimap, PREFIX_USER_NAME, PREFIX_USER_PASSWORD) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + LoginCommand.MESSAGE_USAGE)); + } + + String userName = ParserUtil.parseUserName(argMultimap.getValue(PREFIX_USER_NAME).get()); + String userPassword = ParserUtil.parseUserPassword(argMultimap.getValue(PREFIX_USER_PASSWORD).get()); + + return new LoginCommand(userName, userPassword); + } + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } + +} diff --git a/src/main/java/seedu/address/logic/parser/Parser.java b/src/main/java/com/t13g2/forum/logic/parser/Parser.java similarity index 71% rename from src/main/java/seedu/address/logic/parser/Parser.java rename to src/main/java/com/t13g2/forum/logic/parser/Parser.java index d6551ad8e3ff..59142cce3fd9 100644 --- a/src/main/java/seedu/address/logic/parser/Parser.java +++ b/src/main/java/com/t13g2/forum/logic/parser/Parser.java @@ -1,7 +1,7 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; -import seedu.address.logic.commands.Command; -import seedu.address.logic.parser.exceptions.ParseException; +import com.t13g2.forum.logic.commands.Command; +import com.t13g2.forum.logic.parser.exceptions.ParseException; /** * Represents a Parser that is able to parse user input into a {@code Command} of type {@code T}. diff --git a/src/main/java/com/t13g2/forum/logic/parser/ParserUtil.java b/src/main/java/com/t13g2/forum/logic/parser/ParserUtil.java new file mode 100644 index 000000000000..7a3ef5259558 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/ParserUtil.java @@ -0,0 +1,279 @@ +package com.t13g2.forum.logic.parser; + +import static java.util.Objects.requireNonNull; + +import java.math.BigInteger; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.commons.util.StringUtil; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.model.person.Address; +import com.t13g2.forum.model.person.Email; +import com.t13g2.forum.model.person.Name; +import com.t13g2.forum.model.person.Phone; +import com.t13g2.forum.model.tag.Tag; + +/** + * Contains utility methods used for parsing strings in the various *Parser classes. + */ +public class ParserUtil { + + public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer."; + + /** + * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be + * trimmed. + * @throws ParseException if the specified index is invalid (not non-zero unsigned integer). + */ + public static Index parseIndex(String oneBasedIndex) throws ParseException { + String trimmedIndex = oneBasedIndex.trim(); + if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) { + throw new ParseException(MESSAGE_INVALID_INDEX); + } + return Index.fromOneBased(Integer.parseInt(trimmedIndex)); + } + + /** + * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be + * trimmed. + * + * @throws ParseException if the specified index is invalid (not non-zero unsigned integer). + */ + public static String parseUserName(String userName) throws ParseException { + String trimmedUserName = userName.trim(); + if (!User.isValidUserName(trimmedUserName)) { + throw new ParseException(User.MESSAGE_USER_NAME_CONSTRAINTS); + } + return trimmedUserName; + } + + /** + * @param userPassword + * @return + * @throws ParseException + */ + public static String parseUserPassword(String userPassword) throws ParseException { + String trimmedUserPassword = userPassword.trim(); + if (!User.isValidUserName(trimmedUserPassword)) { + throw new ParseException(User.MESSAGE_USER_PASSWORD_CONSTRAINTS); + } + return trimmedUserPassword; + } + /** + * Parses a {@code String name} into a {@code Name}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code name} is invalid. + */ + public static Name parseName(String name) throws ParseException { + requireNonNull(name); + String trimmedName = name.trim(); + if (!Name.isValidName(trimmedName)) { + throw new ParseException(Name.MESSAGE_NAME_CONSTRAINTS); + } + return new Name(trimmedName); + } + + /** + * Parses a {@code String phone} into a {@code Phone}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code phone} is invalid. + */ + public static Phone parsePhone(String phone) throws ParseException { + requireNonNull(phone); + String trimmedPhone = phone.trim(); + if (!Phone.isValidPhone(trimmedPhone)) { + throw new ParseException(Phone.MESSAGE_PHONE_CONSTRAINTS); + } + return new Phone(trimmedPhone); + } + + /** + * Parses a {@code String address} into an {@code Address}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code address} is invalid. + */ + public static Address parseAddress(String address) throws ParseException { + requireNonNull(address); + String trimmedAddress = address.trim(); + if (!Address.isValidAddress(trimmedAddress)) { + throw new ParseException(Address.MESSAGE_ADDRESS_CONSTRAINTS); + } + return new Address(trimmedAddress); + } + + /** + * Parses a {@code String email} into an {@code Email}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code email} is invalid. + */ + public static Email parseEmail(String email) throws ParseException { + requireNonNull(email); + String trimmedEmail = email.trim(); + if (!Email.isValidEmail(trimmedEmail)) { + throw new ParseException(Email.MESSAGE_EMAIL_CONSTRAINTS); + } + return new Email(trimmedEmail); + } + + /** + * Parses a {@code String tag} into a {@code Tag}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code tag} is invalid. + */ + public static Tag parseTag(String tag) throws ParseException { + requireNonNull(tag); + String trimmedTag = tag.trim(); + if (!Tag.isValidTagName(trimmedTag)) { + throw new ParseException(Tag.MESSAGE_TAG_CONSTRAINTS); + } + return new Tag(trimmedTag); + } + + /** + * Parses {@code Collection tags} into a {@code Set}. + */ + public static Set parseTags(Collection tags) throws ParseException { + requireNonNull(tags); + final Set tagSet = new HashSet<>(); + for (String tagName : tags) { + tagSet.add(parseTag(tagName)); + } + return tagSet; + } + + //@@author xllx1 + /** + * Parses {@code title, content} into a {@code Announcement} + */ + public static Announcement parseAnnouncement(String title, String content) throws ParseException { + requireNonNull(title); + requireNonNull(content); + String trimmedTitle = title.trim(); + String trimmedContent = content.trim(); + if (!Announcement.isValidAnnouncement(trimmedTitle)) { + throw new ParseException(Announcement.MESSAGE_ANNOUNCEMENT_TITLE_CONSTRAINTS); + } else if (!Announcement.isValidAnnouncement(trimmedContent)) { + throw new ParseException(Announcement.MESSAGE_ANNOUNCEMENT_CONTENT_CONSTRAINTS); + } + return new Announcement(trimmedTitle, trimmedContent); + } + + /** + * Parse {@code moduleTitle} into {@code trimmedModuleTitle} + */ + public static String parseModuleTitle(String moduleTitle) throws ParseException { + requireNonNull(moduleTitle); + String trimmedModuleTitle = moduleTitle.trim(); + if (!isValidModuleTitle(trimmedModuleTitle)) { + throw new ParseException(Module.MESSAGE_MODULE_TITLE_CONSTRAINTS); + } + return trimmedModuleTitle; + } + + //Returns true if a given strings is a valid module title. + public static boolean isValidModuleTitle(String trimmedModuleTitle) { + return trimmedModuleTitle.matches(Module.MODULE_TITLE_VALIDATION_REGEX); + } + + /** + * Parse a {@code s} into a {@code int} + */ + public static int parseIntWithOverflow(String s) throws ParseException { + int result = 0; + try { + result = Integer.parseInt(s); + } catch (Exception e) { + try { + new BigInteger(s); + } catch (Exception e1) { + throw e; + } + throw new ParseException(Module.MESSAGE_MODULE_ID_OUT_OF_BOUND); + } + + if (result < 0) { + throw new ParseException(Module.MESSAGE_MODULE_ID_NEGATIVE); + } + return result; + } + + //@@author HansKoh + /** + * moduleCode + */ + public static String parseModule(String module) throws ParseException { + requireNonNull(module); + String trimmedModule = module.trim(); + if (!isValidModule(trimmedModule)) { + throw new ParseException(Module.MESSAGE_MODULE_CODE_CONSTRAINTS); + } + return trimmedModule; + } + //Returns true if a given string is a valid module. + public static boolean isValidModule(String trimmedModule) { + return trimmedModule.matches(Module.MODULE_CODE_VALIDATION_REGEX); + } + + /** + * threadTitle + */ + public static String parseThread(String threadTitle) throws ParseException { + requireNonNull(threadTitle); + String trimmedThreadTitle = threadTitle.trim(); + return trimmedThreadTitle; + } + + /** + * threadId + */ + public static String parseThreadId(String threadId) throws ParseException { + requireNonNull(threadId); + String trimmedThreadId = threadId.trim(); + if (!isValidThreadId(trimmedThreadId)) { + throw new ParseException(ForumThread.MESSAGE_THREAD_ID_CONSTRAINTS); + } + return trimmedThreadId; + } + //Returns true if a given string is a valid thread id. + public static boolean isValidThreadId(String trimmedThreadId) { + return trimmedThreadId.matches(ForumThread.THREAD_ID_VALIDATION_REGEX); + } + + /** + * commentId + */ + public static String parseCommentId(String commentId) throws ParseException { + requireNonNull(commentId); + String trimmedCommentId = commentId.trim(); + if (!isValidCommentId(trimmedCommentId)) { + throw new ParseException(Comment.MESSAGE_COMMENT_ID_CONSTRAINTS); + } + return trimmedCommentId; + } + //Returns true if a given string is a valid comment id. + public static boolean isValidCommentId(String trimmedCommentId) { + return trimmedCommentId.matches(Comment.COMMENT_ID_VALIDATION_REGEX); + } + + /** + * comment content + */ + public static String parseComment(String comment) throws ParseException { + requireNonNull(comment); + String trimmedComment = comment.trim(); + return trimmedComment; + } +} diff --git a/src/main/java/seedu/address/logic/parser/Prefix.java b/src/main/java/com/t13g2/forum/logic/parser/Prefix.java similarity index 95% rename from src/main/java/seedu/address/logic/parser/Prefix.java rename to src/main/java/com/t13g2/forum/logic/parser/Prefix.java index c859d5fa5db1..2e24852bb6f5 100644 --- a/src/main/java/seedu/address/logic/parser/Prefix.java +++ b/src/main/java/com/t13g2/forum/logic/parser/Prefix.java @@ -1,4 +1,4 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; /** * A prefix that marks the beginning of an argument in an arguments string. diff --git a/src/main/java/seedu/address/logic/parser/SelectCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/SelectCommandParser.java similarity index 63% rename from src/main/java/seedu/address/logic/parser/SelectCommandParser.java rename to src/main/java/com/t13g2/forum/logic/parser/SelectCommandParser.java index 565b7f04bfe1..ba5c6ab57efd 100644 --- a/src/main/java/seedu/address/logic/parser/SelectCommandParser.java +++ b/src/main/java/com/t13g2/forum/logic/parser/SelectCommandParser.java @@ -1,10 +1,9 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; - -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.SelectCommand; -import seedu.address.logic.parser.exceptions.ParseException; +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.logic.commands.SelectCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; /** * Parses input arguments and creates a new SelectCommand object @@ -22,7 +21,7 @@ public SelectCommand parse(String args) throws ParseException { return new SelectCommand(index); } catch (ParseException pe) { throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, SelectCommand.MESSAGE_USAGE), pe); + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, SelectCommand.MESSAGE_USAGE), pe); } } } diff --git a/src/main/java/com/t13g2/forum/logic/parser/SelectModuleCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/SelectModuleCommandParser.java new file mode 100644 index 000000000000..531ad89622d6 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/SelectModuleCommandParser.java @@ -0,0 +1,41 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.SelectModuleCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author HansKoh +/** + * Parses input arguments and creates a new SelectModuleCommand object + */ +public class SelectModuleCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the SelectModuleCommand + * and returns an SelectModuleCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public SelectModuleCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_MODULE_CODE); + + if (!arePrefixesPresent(argMultimap, PREFIX_MODULE_CODE) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + SelectModuleCommand.MESSAGE_USAGE)); + } + String moduleCode = ParserUtil.parseModule(argMultimap.getValue(PREFIX_MODULE_CODE).get()); + return new SelectModuleCommand(moduleCode); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/SelectThreadCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/SelectThreadCommandParser.java new file mode 100644 index 000000000000..61141ab0beef --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/SelectThreadCommandParser.java @@ -0,0 +1,41 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_ID; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.SelectThreadCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author HansKoh +/** + * Parses input arguments and creates a new SelectThreadCommand object + */ +public class SelectThreadCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the SelectThreadCommand + * and returns an SelectThreadCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public SelectThreadCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_THREAD_ID); + + if (!arePrefixesPresent(argMultimap, PREFIX_THREAD_ID) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + SelectThreadCommand.MESSAGE_USAGE)); + } + int threadId = Integer.parseInt(ParserUtil.parseThreadId(argMultimap.getValue(PREFIX_THREAD_ID).get())); + return new SelectThreadCommand(threadId); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/SetAdminCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/SetAdminCommandParser.java new file mode 100644 index 000000000000..a6d4c2db4c73 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/SetAdminCommandParser.java @@ -0,0 +1,53 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ADMIN_SET; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_USER_NAME; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.SetAdminCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author xllx1 +/** + * Parses input arguments and setor revert a certain user as admin. + */ +public class SetAdminCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the SetAdminCommand. + * and returns an SetAdminCommand object for execution. + * @param userInput + * @return + * @throws ParseException + */ + public SetAdminCommand parse(String userInput) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(userInput, PREFIX_USER_NAME, PREFIX_ADMIN_SET); + if (!arePrefixesPresent(argMultimap, PREFIX_USER_NAME, PREFIX_ADMIN_SET) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + SetAdminCommand.MESSAGE_USAGE)); + } + + String userName = ParserUtil.parseUserName(argMultimap.getValue(PREFIX_USER_NAME).get()); + boolean setAdmin; + if (argMultimap.getValue(PREFIX_ADMIN_SET).get().equals("true")) { + setAdmin = true; + } else if (argMultimap.getValue(PREFIX_ADMIN_SET).get().equals("false")) { + setAdmin = false; + } else { + throw new ParseException(SetAdminCommand.MESSAGE_SET_CONSTRAINTS); + } + + return new SetAdminCommand(userName, setAdmin); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/UpdateCommentCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/UpdateCommentCommandParser.java new file mode 100644 index 000000000000..e48726c440bb --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/UpdateCommentCommandParser.java @@ -0,0 +1,43 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_CONTENT; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_COMMENT_ID; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.UpdateCommentCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author HansKoh +/** + * Parses input arguments and creates a new UpdateCommentCommand object + */ +public class UpdateCommentCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the UpdateCommentCommand + * and returns an UpdateCommentCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public UpdateCommentCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_COMMENT_ID, PREFIX_COMMENT_CONTENT); + + if (!arePrefixesPresent(argMultimap, PREFIX_COMMENT_ID, PREFIX_COMMENT_CONTENT) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + UpdateCommentCommand.MESSAGE_USAGE)); + } + int commentId = Integer.parseInt(ParserUtil.parseCommentId(argMultimap.getValue(PREFIX_COMMENT_ID).get())); + String commentContentToUpdate = ParserUtil.parseComment(argMultimap.getValue(PREFIX_COMMENT_CONTENT).get()); + return new UpdateCommentCommand(commentId, commentContentToUpdate); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/UpdateModuleCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/UpdateModuleCommandParser.java new file mode 100644 index 000000000000..428364941c6d --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/UpdateModuleCommandParser.java @@ -0,0 +1,54 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_ID; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_TITLE; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.UpdateModuleCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new UpdateModuleCommand object + */ +public class UpdateModuleCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the UpdateModuleCommand + * and returns an UpdateModuleCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public UpdateModuleCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_MODULE_ID, PREFIX_MODULE_CODE, PREFIX_MODULE_TITLE); + + if (!(arePrefixesPresent(argMultimap, PREFIX_MODULE_ID, PREFIX_MODULE_TITLE) + || arePrefixesPresent(argMultimap, PREFIX_MODULE_ID, PREFIX_MODULE_CODE)) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + UpdateModuleCommand.MESSAGE_USAGE)); + } + + int moduleId = ParserUtil.parseIntWithOverflow(argMultimap.getValue(PREFIX_MODULE_ID).get()); + String moduleCode = ""; + String moduleTitle = ""; + if (argMultimap.getValue(PREFIX_MODULE_CODE).isPresent()) { + moduleCode = ParserUtil.parseModule(argMultimap.getValue(PREFIX_MODULE_CODE).get()); + } + if (argMultimap.getValue(PREFIX_MODULE_TITLE).isPresent()) { + moduleTitle = ParserUtil.parseModuleTitle(argMultimap.getValue(PREFIX_MODULE_TITLE).get()); + } + + return new UpdateModuleCommand(moduleId, moduleCode, moduleTitle); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/com/t13g2/forum/logic/parser/UpdateThreadCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/UpdateThreadCommandParser.java new file mode 100644 index 000000000000..3ea88505e877 --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/parser/UpdateThreadCommandParser.java @@ -0,0 +1,43 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_ID; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_THREAD_TITLE; + +import java.util.stream.Stream; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.commands.UpdateThreadCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + +//@@author HansKoh +/** + * Parses input arguments and creates a new UpdateThreadCommand object + */ +public class UpdateThreadCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the UpdateThreadCommand + * and returns an UpdateThreadCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public UpdateThreadCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_THREAD_ID, PREFIX_THREAD_TITLE); + + if (!arePrefixesPresent(argMultimap, PREFIX_THREAD_ID, PREFIX_THREAD_TITLE) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + UpdateThreadCommand.MESSAGE_USAGE)); + } + int threadId = Integer.parseInt(ParserUtil.parseThreadId(argMultimap.getValue(PREFIX_THREAD_ID).get())); + String threadTitle = ParserUtil.parseThread(argMultimap.getValue(PREFIX_THREAD_TITLE).get()); + return new UpdateThreadCommand(threadId, threadTitle); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/com/t13g2/forum/logic/parser/UpdateUserCommandParser.java similarity index 52% rename from src/main/java/seedu/address/logic/parser/EditCommandParser.java rename to src/main/java/com/t13g2/forum/logic/parser/UpdateUserCommandParser.java index 845644b7dea1..bae2b90c1e7f 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/com/t13g2/forum/logic/parser/UpdateUserCommandParser.java @@ -1,61 +1,61 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; 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_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import java.util.Collection; import java.util.Collections; import java.util.Optional; import java.util.Set; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.tag.Tag; +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.logic.commands.EditCommand; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.tag.Tag; /** * Parses input arguments and creates a new EditCommand object */ -public class EditCommandParser implements Parser { +public class UpdateUserCommandParser implements Parser { /** * Parses the given {@code String} of arguments in the context of the EditCommand * and returns an EditCommand object for execution. + * * @throws ParseException if the user input does not conform the expected format */ public EditCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, CliSyntax.PREFIX_NAME, CliSyntax.PREFIX_PHONE, + CliSyntax.PREFIX_EMAIL, CliSyntax.PREFIX_ADDRESS, CliSyntax.PREFIX_TAG); Index index; try { index = ParserUtil.parseIndex(argMultimap.getPreamble()); } catch (ParseException pe) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe); + throw new ParseException(String.format( + Messages.MESSAGE_INVALID_COMMAND_FORMAT, + EditCommand.MESSAGE_USAGE), + pe); } - EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); - if (argMultimap.getValue(PREFIX_NAME).isPresent()) { - editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get())); + EditCommand.EditPersonDescriptor editPersonDescriptor = new EditCommand.EditPersonDescriptor(); + if (argMultimap.getValue(CliSyntax.PREFIX_NAME).isPresent()) { + editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(CliSyntax.PREFIX_NAME).get())); } - if (argMultimap.getValue(PREFIX_PHONE).isPresent()) { - editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get())); + if (argMultimap.getValue(CliSyntax.PREFIX_PHONE).isPresent()) { + editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(CliSyntax.PREFIX_PHONE).get())); } - if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) { - editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get())); + if (argMultimap.getValue(CliSyntax.PREFIX_EMAIL).isPresent()) { + editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(CliSyntax.PREFIX_EMAIL).get())); } - if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) { - editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get())); + if (argMultimap.getValue(CliSyntax.PREFIX_ADDRESS).isPresent()) { + editPersonDescriptor.setAddress( + ParserUtil.parseAddress(argMultimap.getValue(CliSyntax.PREFIX_ADDRESS).get())); } - parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); + parseTagsForEdit(argMultimap.getAllValues(CliSyntax.PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); if (!editPersonDescriptor.isAnyFieldEdited()) { throw new ParseException(EditCommand.MESSAGE_NOT_EDITED); diff --git a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java b/src/main/java/com/t13g2/forum/logic/parser/exceptions/ParseException.java similarity index 72% rename from src/main/java/seedu/address/logic/parser/exceptions/ParseException.java rename to src/main/java/com/t13g2/forum/logic/parser/exceptions/ParseException.java index 158a1a54c1c5..62328a15d7f8 100644 --- a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java +++ b/src/main/java/com/t13g2/forum/logic/parser/exceptions/ParseException.java @@ -1,6 +1,6 @@ -package seedu.address.logic.parser.exceptions; +package com.t13g2.forum.logic.parser.exceptions; -import seedu.address.commons.exceptions.IllegalValueException; +import com.t13g2.forum.commons.exceptions.IllegalValueException; /** * Represents a parse error encountered by a parser. diff --git a/src/main/java/com/t13g2/forum/logic/util/DisplayFormatter.java b/src/main/java/com/t13g2/forum/logic/util/DisplayFormatter.java new file mode 100644 index 000000000000..d29abd6f78df --- /dev/null +++ b/src/main/java/com/t13g2/forum/logic/util/DisplayFormatter.java @@ -0,0 +1,80 @@ +package com.t13g2.forum.logic.util; + +import java.util.List; + +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; + +//@@author HansKoh +/** + * To format the message of a threadList and commentList + */ +public class DisplayFormatter { + + private static String message; + private static int index; + + /** + * + * @param moduleList + * @return + */ + public static String displayModuleList (List moduleList) { + try (UnitOfWork unitOfWork = new UnitOfWork()) { + message = ""; + for (Module module : moduleList) { + message += "Module ID : " + module.getId() + "\n" + + "Module Code : " + module.getModuleCode() + "\n" + + "Module Title : " + module.getTitle() + "\n"; + message += "----------------------------------------------------------------------------------\n"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return message; + } + + /** + * return a string message of threadList to display + * @param threadList + * @return + */ + public static String diplayThreadList (List threadList) { + try (UnitOfWork unitOfWork = new UnitOfWork()) { + message = ""; + for (index = threadList.size() - 1; index >= 0; index--) { + message += "Thread ID : " + threadList.get(index).getId() + "\n" + + "Thread Title: " + threadList.get(index).getTitle() + "\n" + + "Created by : " + unitOfWork.getUserRepository().getUser((threadList.get(index) + .getCreatedByUserId())).getUsername() + "\n" + + "----------------------------------------------------------------------------------\n"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return message; + } + + /** + * return a string message of commentList to display + * @param commentList + * @return + */ + public static String displayCommentList (List commentList) { + try (UnitOfWork unitOfWork = new UnitOfWork()) { + message = ""; + for (index = 0; index < commentList.size(); index++) { + message += "Comment ID: " + commentList.get(index).getId() + "\n" + + "Content : " + commentList.get(index).getContent() + "\n" + + "Created by : " + unitOfWork.getUserRepository().getUser((commentList.get(index) + .getCreatedByUserId())).getUsername() + "\n" + + "----------------------------------------------------------------------------------\n"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return message; + } +} diff --git a/src/main/java/com/t13g2/forum/model/AnnouncementRepository.java b/src/main/java/com/t13g2/forum/model/AnnouncementRepository.java new file mode 100644 index 000000000000..a5bbc188ed6d --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/AnnouncementRepository.java @@ -0,0 +1,85 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import java.util.Objects; +import java.util.Optional; + +import com.sun.istack.NotNull; +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; +import com.t13g2.forum.storage.forum.IForumBookStorage; + +/** + * Provides APIs to manipulate {@link Announcement} + */ +public class AnnouncementRepository extends BaseRepository implements IAnnouncementRepository { + /** + * Instantiates a new Announcement repository. + * + * @param forumBookStorage the forum book storage + */ + public AnnouncementRepository(IForumBookStorage forumBookStorage) { + super(forumBookStorage); + } + + + /** + * Adds an {@link Announcement} into database + * + * @param announcement + * @return Id of the object added + */ + @Override + public int addAnnouncement(@NotNull Announcement announcement) { + Objects.requireNonNull(announcement, "announcement can't be null"); + forumBookStorage.getAnnouncements().getList().add(announcement); + forumBookStorage.getAnnouncements().setDirty(); + return announcement.getId(); + } + + /** + * Deletes an {@link Announcement} + * @param announcement + */ + @Override + public void deleteAnnouncement(@NotNull Announcement announcement) { + Objects.requireNonNull(announcement, "announcement can't be null"); + this.deleteAnnouncement(announcement.getId()); + } + + /** + * Deletes an {@link Announcement} + * @param announcementId + */ + @Override + public void deleteAnnouncement(int announcementId) { + forumBookStorage.getAnnouncements().getList().removeIf(announcement -> announcement.getId() == announcementId); + forumBookStorage.getAnnouncements().setDirty(); + } + + /** + * Gets an {@link Announcement} by its object Id + * @param announcementId + * @return the {@link Announcement} queried + * @throws EntityDoesNotExistException + */ + @Override + public Announcement getAnnouncement(int announcementId) throws EntityDoesNotExistException { + return this.getById(forumBookStorage.getAnnouncements().getList(), announcementId); + } + + /** + * Gets the latest {@link Announcement} + * @return latest {@link Announcement} + * @throws EntityDoesNotExistException + */ + @Override + public Announcement getLatestAnnouncement() throws EntityDoesNotExistException { + Optional announcement = forumBookStorage.getAnnouncements().getList().stream() + .min((o1, o2) -> o2.getCreated().compareTo(o1.getCreated())); + if (!announcement.isPresent()) { + throw new EntityDoesNotExistException("No Announcement found"); + } + return announcement.get(); + } +} diff --git a/src/main/java/com/t13g2/forum/model/BaseRepository.java b/src/main/java/com/t13g2/forum/model/BaseRepository.java new file mode 100644 index 000000000000..e35524fed177 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/BaseRepository.java @@ -0,0 +1,52 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import java.util.List; +import java.util.Optional; + +import com.t13g2.forum.model.forum.BaseModel; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; +import com.t13g2.forum.storage.forum.IForumBookStorage; + +/** + * Defines a base class for all entity repositories + */ +public abstract class BaseRepository { + protected IForumBookStorage forumBookStorage; + + /** + * Creates a new BaseRepository instance. + * + * @param forumBookStorage of type IForumBookStorage + */ + public BaseRepository(IForumBookStorage forumBookStorage) { + this.forumBookStorage = forumBookStorage; + } + + + /** + * Helper method to get an entity by its id + * + * @param list + * @param id of type int + * @return T + * @throws EntityDoesNotExistException when + */ + protected T getById(List list, int id) throws EntityDoesNotExistException { + Optional result = list.stream().filter(item -> item.getId() == id).findFirst(); + if (!result.isPresent()) { + throw new EntityDoesNotExistException("Entity does not exist"); + } + return result.get(); + } + + /** + * Helper method to remove an entity from a list by id + * + * @param list + * @param id of type int + */ + protected void removeById(List list, int id) { + list.removeIf(item -> item.getId() == id); + } +} diff --git a/src/main/java/com/t13g2/forum/model/CommentRepository.java b/src/main/java/com/t13g2/forum/model/CommentRepository.java new file mode 100644 index 000000000000..3855c74d5b21 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/CommentRepository.java @@ -0,0 +1,105 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import com.sun.istack.NotNull; +import com.t13g2.forum.commons.util.Extensions; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; +import com.t13g2.forum.storage.forum.IForumBookStorage; + +/** + *Provides APIs to manipulate {@link Comment} + */ +public class CommentRepository extends BaseRepository implements ICommentRepository { + /** + * Creates a new BaseRepository instance. + * + * @param forumBookStorage of type IForumBookStorage + */ + public CommentRepository(IForumBookStorage forumBookStorage) { + super(forumBookStorage); + } + + /** + * Adds an {@link Comment} into database + * + * @param comment + * @return Id of the object added + */ + @Override + public int addComment(@NotNull Comment comment) { + Objects.requireNonNull(comment, "comment can't be null"); + forumBookStorage.getComments().getList().add(comment); + forumBookStorage.getComments().setDirty(); + return comment.getId(); + } + + /** + * Deletes an {@link Comment} + * @param comment + */ + @Override + public void deleteComment(@NotNull Comment comment) { + Objects.requireNonNull(comment, "comment can't be null"); + this.deleteComment(comment.getId()); + } + + /** + * Deletes an {@link Comment} + * @param commentId + */ + @Override + public void deleteComment(int commentId) { + forumBookStorage.getComments().getList().removeIf(comment -> comment.getId() == commentId); + forumBookStorage.getComments().setDirty(); + } + + /** + * Updates an {@link Comment} + * + * @param comment + */ + @Override + public void updateComment(Comment comment) { + Extensions.updateObjectInList(forumBookStorage.getComments().getList(), comment); + forumBookStorage.getComments().setDirty(); + } + + /** + * Gets an {@link Comment} by its object Id + * @param commentId + * @return the {@link Comment} queried + * @throws EntityDoesNotExistException + */ + @Override + public Comment getComment(int commentId) throws EntityDoesNotExistException { + return this.getById(forumBookStorage.getComments().getList(), commentId); + } + + /** + * Gets all comments under a certain thread + * @param threadId + * @return a list of {@link Comment} + */ + @Override + public List getCommentsByThread(int threadId) { + return forumBookStorage.getComments().getList().stream() + .filter(aComment -> aComment.getThreadId() == threadId).collect(Collectors.toList()); + } + + /** + * Gets all comments under a certain thread + * @param forumThread + * @return a list of {@link Comment} + */ + @Override + public List getCommentsByThread(@NotNull ForumThread forumThread) { + Objects.requireNonNull(forumThread, "forumThread can't be null"); + return this.getCommentsByThread(forumThread.getId()); + } +} diff --git a/src/main/java/com/t13g2/forum/model/Context.java b/src/main/java/com/t13g2/forum/model/Context.java new file mode 100644 index 000000000000..23c4ba6ac8d6 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/Context.java @@ -0,0 +1,129 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import com.t13g2.forum.model.forum.User; + +/** + * A singleton class to manage login status + */ +public class Context { + private static Context instance; + private User currentUser; + private int currentModuleId = -1; + private int currentThreadId = -1; + private int currentCommentId = -1; + + + /** + * Creates a new Context instance. + */ + private Context() { + + } + + public static Context getInstance() { + if (instance == null) { + instance = new Context(); + } + return instance; + } + + /** + * Returns current logged in user + * + * @return current logged in user + */ + public User getCurrentUser() { + return currentUser; + } + + /** + * Sets current logged in user + * + * @param currentUser + */ + public void setCurrentUser(User currentUser) { + this.currentUser = currentUser; + } + + /** + * Returns current logged in user id + * + * @return user id, if not logged in -1 + */ + public int getCurrentUserId() { + return currentUser == null ? -1 : currentUser.getId(); + } + + /** + * Checks login status + * @return true if logged in otherwise false + */ + public boolean isLoggedIn() { + return currentUser != null; + } + + /** + * Checks if current user a admin. + * @return true if current user is admin otherwise false(including not logged in) + */ + public boolean isCurrentUserAdmin() { + return currentUser != null && currentUser.isAdmin(); + } + + /** + * Checks if current user is blocked. + * @return true if current user is blocked or not logged in otherwise false + */ + public boolean isCurrentUserBlocked() { + return currentUser == null || currentUser.isBlock(); + } + + /** + * Gets the module id that current user is browsing + * @return module id + */ + public int getCurrentModuleId() { + return currentModuleId; + } + + /** + * Sets the module id that current user is browsing + * @param currentModuleId + */ + public void setCurrentModuleId(int currentModuleId) { + this.currentModuleId = currentModuleId; + } + + /** + * Gets the thread id that current user is browsing + * @return thread id + */ + public int getCurrentThreadId() { + return currentThreadId; + } + + /** + * Sets the thread id that current user is browsing + * @param currentThreadId + */ + public void setCurrentThreadId(int currentThreadId) { + this.currentThreadId = currentThreadId; + } + + /** + * Gets the comment id that current user is browsing + * @return comment id + */ + public int getCurrentCommentId() { + return currentCommentId; + } + + /** + * Sets the comment id that current user is browsing + * @param currentCommentId + */ + public void setCurrentCommentId(int currentCommentId) { + this.currentCommentId = currentCommentId; + } +} diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/com/t13g2/forum/model/ForumBook.java similarity index 80% rename from src/main/java/seedu/address/model/AddressBook.java rename to src/main/java/com/t13g2/forum/model/ForumBook.java index 7f85c8b9258b..93eec9ab4e52 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/com/t13g2/forum/model/ForumBook.java @@ -1,18 +1,19 @@ -package seedu.address.model; +package com.t13g2.forum.model; import static java.util.Objects.requireNonNull; import java.util.List; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.model.person.UniquePersonList; + import javafx.collections.ObservableList; -import seedu.address.model.person.Person; -import seedu.address.model.person.UniquePersonList; /** * Wraps all data at the address-book level * Duplicates are not allowed (by .isSamePerson comparison) */ -public class AddressBook implements ReadOnlyAddressBook { +public class ForumBook implements ReadOnlyForumBook { private final UniquePersonList persons; @@ -27,12 +28,12 @@ public class AddressBook implements ReadOnlyAddressBook { persons = new UniquePersonList(); } - public AddressBook() {} + public ForumBook() {} /** - * Creates an AddressBook using the Persons in the {@code toBeCopied} + * Creates an ForumBook using the Persons in the {@code toBeCopied} */ - public AddressBook(ReadOnlyAddressBook toBeCopied) { + public ForumBook(ReadOnlyForumBook toBeCopied) { this(); resetData(toBeCopied); } @@ -48,9 +49,9 @@ public void setPersons(List persons) { } /** - * Resets the existing data of this {@code AddressBook} with {@code newData}. + * Resets the existing data of this {@code ForumBook} with {@code newData}. */ - public void resetData(ReadOnlyAddressBook newData) { + public void resetData(ReadOnlyForumBook newData) { requireNonNull(newData); setPersons(newData.getPersonList()); @@ -86,7 +87,7 @@ public void updatePerson(Person target, Person editedPerson) { } /** - * Removes {@code key} from this {@code AddressBook}. + * Removes {@code key} from this {@code ForumBook}. * {@code key} must exist in the address book. */ public void removePerson(Person key) { @@ -109,8 +110,8 @@ public ObservableList getPersonList() { @Override public boolean equals(Object other) { return other == this // short circuit if same object - || (other instanceof AddressBook // instanceof handles nulls - && persons.equals(((AddressBook) other).persons)); + || (other instanceof ForumBook // instanceof handles nulls + && persons.equals(((ForumBook) other).persons)); } @Override diff --git a/src/main/java/com/t13g2/forum/model/ForumThreadRepository.java b/src/main/java/com/t13g2/forum/model/ForumThreadRepository.java new file mode 100644 index 000000000000..11605c7ed609 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/ForumThreadRepository.java @@ -0,0 +1,110 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import com.sun.istack.NotNull; +import com.t13g2.forum.commons.util.Extensions; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; +import com.t13g2.forum.storage.forum.IForumBookStorage; + +/** + *Provides APIs to manipulate {@link ForumThread} + */ +public class ForumThreadRepository extends BaseRepository implements IForumThreadRepository { + /** + * Creates a new BaseRepository instance. + * + * @param forumBookStorage of type IForumBookStorage + */ + public ForumThreadRepository(IForumBookStorage forumBookStorage) { + super(forumBookStorage); + } + + + /** + * Adds an {@link ForumThread} into database + * + * @param forumThread + * @return object Id added + */ + @Override + public int addThread(@NotNull ForumThread forumThread) { + Objects.requireNonNull(forumThread, "forumThread can't be null"); + forumBookStorage.getForumThreads().getList().add(forumThread); + forumBookStorage.getForumThreads().setDirty(); + return forumThread.getId(); + } + + /** + * Update an {@link ForumThread} + * @param forumThread + */ + @Override + public void updateThread(@NotNull ForumThread forumThread) { + Objects.requireNonNull(forumThread, "forumThread can't be null"); + List forumThreads = forumBookStorage.getForumThreads().getList(); + Extensions.updateObjectInList(forumThreads, forumThread); + forumBookStorage.getForumThreads().setDirty(); + } + + /** + * Gets a thread by its Id + * @param forumThreadId + * @return the {@link ForumThread} queried + * @throws EntityDoesNotExistException + */ + @Override + public ForumThread getThread(int forumThreadId) throws EntityDoesNotExistException { + return this.getById(forumBookStorage.getForumThreads().getList(), forumThreadId); + } + + /** + * Gets all threads under a certain module + * @param moduleId + * @return a list of {@link ForumThread} + */ + @Override + public List getThreadsByModule(int moduleId) { + return forumBookStorage.getForumThreads().getList().stream() + .filter(aForumThread -> aForumThread.getModuleId() == moduleId).collect(Collectors.toList()); + } + + /** + * Gets all threads under a certain module + * @param module + * @return a list of {@link ForumThread} + */ + @Override + public List getThreadsByModule(@NotNull Module module) { + Objects.requireNonNull(module, "module can't be null"); + return this.getThreadsByModule(module.getId()); + } + + /** + * Deletes an {@link ForumThread} + * @param forumThreadId + */ + @Override + public void deleteThread(int forumThreadId) { + List pointer = forumBookStorage.getForumThreads().getList(); + Optional toBeDeleted = pointer.stream().filter(forumThread -> forumThread.getId() + == forumThreadId).findFirst(); + toBeDeleted.ifPresent(pointer::remove); + forumBookStorage.getForumThreads().setDirty(); + } + + /** + * Deletes an {@link ForumThread} + * @param forumThread + */ + @Override + public void deleteThread(ForumThread forumThread) { + this.deleteThread(forumThread.getId()); + } +} diff --git a/src/main/java/com/t13g2/forum/model/IAnnouncementRepository.java b/src/main/java/com/t13g2/forum/model/IAnnouncementRepository.java new file mode 100644 index 000000000000..76a30b42eed3 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/IAnnouncementRepository.java @@ -0,0 +1,45 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +/** + * Provides APIs to manipulate {@link Announcement} + */ +public interface IAnnouncementRepository { + /** + * Adds an {@link Announcement} into database + * + * @param announcement + * @return Id of the object added + */ + int addAnnouncement(Announcement announcement); + + /** + * Deletes an {@link Announcement} + * @param announcement + */ + void deleteAnnouncement(Announcement announcement); + + /** + * Deletes an {@link Announcement} + * @param announcementId + */ + void deleteAnnouncement(int announcementId); + + /** + * Gets an {@link Announcement} by its object Id + * @param announcementId + * @return the {@link Announcement} queried + * @throws EntityDoesNotExistException + */ + Announcement getAnnouncement(int announcementId) throws EntityDoesNotExistException; + + /** + * Gets the latest {@link Announcement} + * @return latest {@link Announcement} + * @throws EntityDoesNotExistException + */ + Announcement getLatestAnnouncement() throws EntityDoesNotExistException; +} diff --git a/src/main/java/com/t13g2/forum/model/ICommentRepository.java b/src/main/java/com/t13g2/forum/model/ICommentRepository.java new file mode 100644 index 000000000000..9d529650df22 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/ICommentRepository.java @@ -0,0 +1,62 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import java.util.List; + +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +/** + *Provides APIs to manipulate {@link Comment} + */ +public interface ICommentRepository { + /** + * Adds an {@link Comment} into database + * + * @param comment + * @return Id of the object added + */ + int addComment(Comment comment); + + /** + * Deletes an {@link Comment} + * @param comment + */ + void deleteComment(Comment comment); + + /** + * Deletes an {@link Comment} + * @param commentId + */ + void deleteComment(int commentId); + + /** + * Updates an {@link Comment} + * + * @param comment + */ + void updateComment(Comment comment); + + /** + * Gets an {@link Comment} by its object Id + * @param commentId + * @return the {@link Comment} queried + * @throws EntityDoesNotExistException + */ + Comment getComment(int commentId) throws EntityDoesNotExistException; + + /** + * Gets all comments under a certain thread + * @param threadId + * @return a list of {@link Comment} + */ + List getCommentsByThread(int threadId); + + /** + * Gets all comments under a certain thread + * @param forumThread + * @return a list of {@link Comment} + */ + List getCommentsByThread(ForumThread forumThread); +} diff --git a/src/main/java/com/t13g2/forum/model/IForumThreadRepository.java b/src/main/java/com/t13g2/forum/model/IForumThreadRepository.java new file mode 100644 index 000000000000..8c66853d737d --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/IForumThreadRepository.java @@ -0,0 +1,64 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import java.util.List; + +import com.sun.istack.NotNull; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +/** + * Provides APIs to manipulate {@link ForumThread} + */ +public interface IForumThreadRepository { + /** + * Adds an {@link ForumThread} into database + * + * @param forumThread + * @return object Id added + */ + int addThread(ForumThread forumThread); + + /** + * Update an {@link ForumThread} + * @param forumThread + */ + void updateThread(@NotNull ForumThread forumThread); + + /** + * Gets a thread by its Id + * @param forumThreadId + * @return the {@link ForumThread} queried + * @throws EntityDoesNotExistException + */ + ForumThread getThread(int forumThreadId) throws EntityDoesNotExistException; + + /** + * Gets all threads under a certain module + * @param moduleId + * @return a list of {@link ForumThread} + */ + List getThreadsByModule(int moduleId); + + /** + * Gets all threads under a certain module + * @param module + * @return a list of {@link ForumThread} + */ + List getThreadsByModule(Module module); + + /** + * Deletes an {@link ForumThread} + * @param forumThreadId + */ + void deleteThread(int forumThreadId); + + /** + * Deletes an {@link ForumThread} + * @param forumThread + */ + void deleteThread(ForumThread forumThread); + + +} diff --git a/src/main/java/com/t13g2/forum/model/IModuleRepository.java b/src/main/java/com/t13g2/forum/model/IModuleRepository.java new file mode 100644 index 000000000000..4cb0c65bec5f --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/IModuleRepository.java @@ -0,0 +1,60 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import java.util.List; + +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +/** + * Provides APIs to manipulate {@link Module} + */ +public interface IModuleRepository { + /** + * Adds an {@link Module} into database + * + * @param module + * @return object Id added + */ + int addModule(Module module); + + /** + * Removes an {@link Module} + * @param module + */ + void removeModule(Module module); + + /** + * Removes an {@link Module} + * @param moduleId + */ + void removeModule(int moduleId); + + /** + * Updates an {@link Module} + * @param module + */ + void updateModule(Module module); + + /** + * Gets a module by its Id + * @param moduleId + * @return module queried + * @throws EntityDoesNotExistException + */ + Module getModule(int moduleId) throws EntityDoesNotExistException; + + /** + * Gets a module by its module code + * @param moduleCode + * @return module queried + * @throws EntityDoesNotExistException + */ + Module getModuleByCode(String moduleCode) throws EntityDoesNotExistException; + + /** + * Gets all modules in the database + * @return a list of modules + */ + List getAllModule(); +} diff --git a/src/main/java/com/t13g2/forum/model/IUnitOfWork.java b/src/main/java/com/t13g2/forum/model/IUnitOfWork.java new file mode 100644 index 000000000000..1269d313fb00 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/IUnitOfWork.java @@ -0,0 +1,48 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +/** + * Provides a transaction API to manipulate application database + */ +public interface IUnitOfWork { + /** + * Saves all changes + */ + void commit(); + + /** + * Revert all changes + */ + void rollBack(); + + /** + * Gets {@link IAnnouncementRepository} + * + * @return {@link IAnnouncementRepository} + */ + IAnnouncementRepository getAnnouncementRepository(); + + /** + * Gets {@link ICommentRepository} + * @return {@link ICommentRepository} + */ + ICommentRepository getCommentRepository(); + + /** + * Gets {@link IForumThreadRepository} + * @return {@link IForumThreadRepository} + */ + IForumThreadRepository getForumThreadRepository(); + + /** + * Gets {@link IModuleRepository} + * @return {@link IModuleRepository} + */ + IModuleRepository getModuleRepository(); + + /** + * Gets {@link IUserRepository} + * @return {@link IUserRepository} + */ + IUserRepository getUserRepository(); +} diff --git a/src/main/java/com/t13g2/forum/model/IUserRepository.java b/src/main/java/com/t13g2/forum/model/IUserRepository.java new file mode 100644 index 000000000000..b0f0254e2444 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/IUserRepository.java @@ -0,0 +1,62 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +/** + * Provides APIs to manipulate {@link User} + */ +public interface IUserRepository { + /** + * Adds an {@link User} into database + * + * @param user + * @return Id of the object added + */ + int addUser(User user); + + /** + * Updates an {@link User} + * @param user + */ + void updateUser(User user); + + /** + * Deletes an {@link User} + * @param user + */ + void deleteUser(User user); + + /** + * Deletes an {@link User} + * @param userId + */ + void deleteUser(int userId); + + /** + * Gets an {@link User} by its object Id + * @param userId + * @return the {@link User} queried + * @throws EntityDoesNotExistException + */ + User getUser(int userId) throws EntityDoesNotExistException; + + /** + * Gets a user by its username + * @param username + * @return user queried + * @throws EntityDoesNotExistException + */ + User getUserByUsername(String username) throws EntityDoesNotExistException; + + /** + * Checks if the given username and password match with the record in the database + * @param username + * @param password + * @return user matched + * @throws EntityDoesNotExistException + */ + User authenticate(String username, String password) throws EntityDoesNotExistException; + +} diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/com/t13g2/forum/model/Model.java similarity index 84% rename from src/main/java/seedu/address/model/Model.java rename to src/main/java/com/t13g2/forum/model/Model.java index ac4521f33199..b072c16052e8 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/com/t13g2/forum/model/Model.java @@ -1,9 +1,10 @@ -package seedu.address.model; +package com.t13g2.forum.model; import java.util.function.Predicate; +import com.t13g2.forum.model.person.Person; + import javafx.collections.ObservableList; -import seedu.address.model.person.Person; /** * The API of the Model component. @@ -13,10 +14,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(ReadOnlyForumBook newData); - /** Returns the AddressBook */ - ReadOnlyAddressBook getAddressBook(); + /** Returns the ForumBook */ + ReadOnlyForumBook getForumBook(); /** * Returns true if a person with the same identity as {@code person} exists in the address book. @@ -54,25 +55,25 @@ public interface Model { /** * Returns true if the model has previous address book states to restore. */ - boolean canUndoAddressBook(); + boolean canUndoForumBook(); /** * Returns true if the model has undone address book states to restore. */ - boolean canRedoAddressBook(); + boolean canRedoForumBook(); /** * Restores the model's address book to its previous state. */ - void undoAddressBook(); + void undoForumBook(); /** * Restores the model's address book to its previously undone state. */ - void redoAddressBook(); + void redoForumBook(); /** * Saves the current address book state for undo/redo. */ - void commitAddressBook(); + void commitForumBook(); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/com/t13g2/forum/model/ModelManager.java similarity index 78% rename from src/main/java/seedu/address/model/ModelManager.java rename to src/main/java/com/t13g2/forum/model/ModelManager.java index a664602ef5b1..bffa480c16e5 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/com/t13g2/forum/model/ModelManager.java @@ -1,18 +1,20 @@ -package seedu.address.model; +package com.t13g2.forum.model; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.util.function.Predicate; import java.util.logging.Logger; +import com.t13g2.forum.commons.core.ComponentManager; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.events.model.AddressBookChangedEvent; +import com.t13g2.forum.commons.util.CollectionUtil; +import com.t13g2.forum.model.person.Person; + import javafx.collections.FXCollections; import javafx.collections.ObservableList; 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.model.person.Person; + /** * Represents the in-memory model of the address book data. @@ -20,34 +22,34 @@ public class ModelManager extends ComponentManager implements Model { private static final Logger logger = LogsCenter.getLogger(ModelManager.class); - private final VersionedAddressBook versionedAddressBook; + private final VersionedForumBook versionedAddressBook; private final FilteredList filteredPersons; /** * Initializes a ModelManager with the given addressBook and userPrefs. */ - public ModelManager(ReadOnlyAddressBook addressBook, UserPrefs userPrefs) { + public ModelManager(ReadOnlyForumBook addressBook, UserPrefs userPrefs) { super(); - requireAllNonNull(addressBook, userPrefs); + CollectionUtil.requireAllNonNull(addressBook, userPrefs); logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs); - versionedAddressBook = new VersionedAddressBook(addressBook); + versionedAddressBook = new VersionedForumBook(addressBook); filteredPersons = new FilteredList<>(versionedAddressBook.getPersonList()); } public ModelManager() { - this(new AddressBook(), new UserPrefs()); + this(new ForumBook(), new UserPrefs()); } @Override - public void resetData(ReadOnlyAddressBook newData) { + public void resetData(ReadOnlyForumBook newData) { versionedAddressBook.resetData(newData); indicateAddressBookChanged(); } @Override - public ReadOnlyAddressBook getAddressBook() { + public ReadOnlyForumBook getForumBook() { return versionedAddressBook; } @@ -77,7 +79,7 @@ public void addPerson(Person person) { @Override public void updatePerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); + CollectionUtil.requireAllNonNull(target, editedPerson); versionedAddressBook.updatePerson(target, editedPerson); indicateAddressBookChanged(); @@ -103,29 +105,29 @@ public void updateFilteredPersonList(Predicate predicate) { //=========== Undo/Redo ================================================================================= @Override - public boolean canUndoAddressBook() { + public boolean canUndoForumBook() { return versionedAddressBook.canUndo(); } @Override - public boolean canRedoAddressBook() { + public boolean canRedoForumBook() { return versionedAddressBook.canRedo(); } @Override - public void undoAddressBook() { + public void undoForumBook() { versionedAddressBook.undo(); indicateAddressBookChanged(); } @Override - public void redoAddressBook() { + public void redoForumBook() { versionedAddressBook.redo(); indicateAddressBookChanged(); } @Override - public void commitAddressBook() { + public void commitForumBook() { versionedAddressBook.commit(); } diff --git a/src/main/java/com/t13g2/forum/model/ModuleRepository.java b/src/main/java/com/t13g2/forum/model/ModuleRepository.java new file mode 100644 index 000000000000..129e830030f3 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/ModuleRepository.java @@ -0,0 +1,120 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; + +import com.sun.istack.NotNull; +import com.t13g2.forum.commons.util.Extensions; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; +import com.t13g2.forum.storage.forum.IForumBookStorage; + +/** + * Provides APIs to manipulate {@link Module} + */ +public class ModuleRepository extends BaseRepository implements IModuleRepository { + /** + * Creates a new BaseRepository instance. + * + * @param forumBookStorage of type IForumBookStorage + */ + public ModuleRepository(IForumBookStorage forumBookStorage) { + super(forumBookStorage); + } + + + /** + * Adds an {@link Module} into database + * + * @param module + * @return object Id added + */ + @Override + public int addModule(@NotNull Module module) { + Objects.requireNonNull(module, "module can't be null"); + + forumBookStorage.getModules().getList().add(module); + forumBookStorage.getModules().setDirty(); + return module.getId(); + } + + /** + * Removes an {@link Module} + * @param module + */ + @Override + public void removeModule(@NotNull Module module) { + Objects.requireNonNull(module, "module can't be null"); + + this.removeModule(module.getId()); + } + + /** + * Removes an {@link Module} + * @param moduleId + */ + @Override + public void removeModule(int moduleId) { + forumBookStorage.getModules().getList().removeIf(module -> module.getId() == moduleId); + forumBookStorage.getModules().setDirty(); + } + + /** + * Updates an {@link Module} + * @param module + */ + @Override + public void updateModule(@NotNull Module module) { + Objects.requireNonNull(module, "module can't be null"); + Extensions.updateObjectInList(forumBookStorage.getModules().getList(), module); + forumBookStorage.getModules().setDirty(); + } + + /** + * Gets a module by its Id + * @param moduleId + * @return module queried + * @throws EntityDoesNotExistException + */ + @Override + public Module getModule(int moduleId) throws EntityDoesNotExistException { + return getModuleBy(module -> module.getId() == moduleId); + } + + /** + * Gets a module by its module code + * @param moduleCode + * @return module queried + * @throws EntityDoesNotExistException + */ + @Override + public Module getModuleByCode(String moduleCode) throws EntityDoesNotExistException { + return getModuleBy(module -> module.getModuleCode().equals(moduleCode)); + } + + /** + * Gets all modules in the database + * @return a list of modules + */ + @Override + public List getAllModule() { + return forumBookStorage.getModules().getList(); + } + + /** + * Helper method to get a module by a predicate + * @param predicate + * @return module queried + * @throws EntityDoesNotExistException + */ + private Module getModuleBy(Predicate predicate) throws EntityDoesNotExistException { + Optional module = forumBookStorage.getModules().getList().stream().filter(predicate).findFirst(); + if (module.isPresent()) { + return module.get(); + } + throw new EntityDoesNotExistException("Module does not exist"); + } +} diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/com/t13g2/forum/model/ReadOnlyForumBook.java similarity index 70% rename from src/main/java/seedu/address/model/ReadOnlyAddressBook.java rename to src/main/java/com/t13g2/forum/model/ReadOnlyForumBook.java index 6ddc2cd9a290..3193306c28e0 100644 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ b/src/main/java/com/t13g2/forum/model/ReadOnlyForumBook.java @@ -1,12 +1,13 @@ -package seedu.address.model; +package com.t13g2.forum.model; + +import com.t13g2.forum.model.person.Person; import javafx.collections.ObservableList; -import seedu.address.model.person.Person; /** * Unmodifiable view of an address book */ -public interface ReadOnlyAddressBook { +public interface ReadOnlyForumBook { /** * Returns an unmodifiable view of the persons list. diff --git a/src/main/java/com/t13g2/forum/model/SampleDataGenerator.java b/src/main/java/com/t13g2/forum/model/SampleDataGenerator.java new file mode 100644 index 000000000000..92b3edb4a38c --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/SampleDataGenerator.java @@ -0,0 +1,96 @@ +package com.t13g2.forum.model; + +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +//@@author Meowzz95 + +/** + * Helps to generate some sample data + */ +public class SampleDataGenerator { + private UnitOfWork uow; + private int userId; + private int moduleId; + private int forumThreadId; + + public SampleDataGenerator(UnitOfWork uow) { + this.uow = uow; + } + + /** + * Generates sample data + */ + public void generate() { + this.generateUser(); + this.generateModule(); + this.generateThread(); + this.generateComment(); + this.generateAnnouncement(); + } + + /** + * Generates sample user data + */ + private void generateUser() { + User admin = new User(); + admin.setUsername("admin"); + admin.setPassword("admin"); + admin.setAdmin(true); + admin.setEmail("email@gmail.com"); + admin.setPhone("12345678"); + + User user1 = new User(); + user1.setUsername("user1"); + user1.setPassword("user1"); + user1.setEmail("user1@email.com"); + user1.setPhone("88888888"); + this.userId = user1.getId(); + + uow.getUserRepository().addUser(admin); + uow.getUserRepository().addUser(user1); + } + + /** + * Generates sample module data + */ + private void generateModule() { + Module module = new Module("Software Eng", "CS2113"); + uow.getModuleRepository().addModule(module); + this.moduleId = module.getId(); + } + + /** + * Generates sample thread data + */ + private void generateThread() { + ForumThread forumThread = new ForumThread(); + forumThread.setModuleId(this.moduleId); + forumThread.setTitle("Hey How is CS2113"); + forumThread.setCreatedByUserId(this.userId); + uow.getForumThreadRepository().addThread(forumThread); + this.forumThreadId = forumThread.getId(); + } + + /** + * Generates sample comment data + */ + private void generateComment() { + Comment comment = new Comment(); + comment.setThreadId(this.forumThreadId); + comment.setContent("I am taking this module next sem, how is it?"); + comment.setCreatedByUserId(this.userId); + + uow.getCommentRepository().addComment(comment); + } + + /** + * Generates sample announcement data + */ + private void generateAnnouncement() { + Announcement announcement = new Announcement("Welcome!", "Welcome to ForumBook"); + uow.getAnnouncementRepository().addAnnouncement(announcement); + } +} diff --git a/src/main/java/com/t13g2/forum/model/UnitOfWork.java b/src/main/java/com/t13g2/forum/model/UnitOfWork.java new file mode 100644 index 000000000000..a849e5ed09ce --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/UnitOfWork.java @@ -0,0 +1,114 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import com.t13g2.forum.storage.forum.ForumBookStorage; +import com.t13g2.forum.storage.forum.IForumBookStorage; +import com.t13g2.forum.storage.forum.IStorage; +import com.t13g2.forum.storage.forum.JsonFileStorage; + +/** + * Provides a transaction API to manipulate application database + */ +public class UnitOfWork implements IUnitOfWork, AutoCloseable { + private IForumBookStorage forumBookStorage; + + private IAnnouncementRepository announcementRepository; + private ICommentRepository commentRepository; + private IForumThreadRepository forumThreadRepository; + private IModuleRepository moduleRepository; + private IUserRepository userRepository; + + public UnitOfWork(IStorage storage) { + forumBookStorage = new ForumBookStorage(storage); + + announcementRepository = new AnnouncementRepository(forumBookStorage); + commentRepository = new CommentRepository(forumBookStorage); + forumThreadRepository = new ForumThreadRepository(forumBookStorage); + moduleRepository = new ModuleRepository(forumBookStorage); + userRepository = new UserRepository(forumBookStorage); + } + + public UnitOfWork() { + this(new JsonFileStorage()); + } + + /** + * Gets {@link IAnnouncementRepository} + * + * @return {@link IAnnouncementRepository} + */ + @Override + public IAnnouncementRepository getAnnouncementRepository() { + return announcementRepository; + } + + /** + * Gets {@link ICommentRepository} + * @return {@link ICommentRepository} + */ + @Override + public ICommentRepository getCommentRepository() { + return commentRepository; + } + + /** + * Gets {@link IForumThreadRepository} + * @return {@link IForumThreadRepository} + */ + @Override + public IForumThreadRepository getForumThreadRepository() { + return forumThreadRepository; + } + + /** + * Gets {@link IModuleRepository} + * @return {@link IModuleRepository} + */ + @Override + public IModuleRepository getModuleRepository() { + return moduleRepository; + } + + /** + * Gets {@link IUserRepository} + * @return {@link IUserRepository} + */ + @Override + public IUserRepository getUserRepository() { + return userRepository; + } + + /** + * Saves all changes + */ + @Override + public void commit() { + + forumBookStorage.commit(); + + } + + /** + * Reverts all changes + */ + @Override + public void rollBack() { + + } + + @Override + public void close() throws Exception { + + } + + /** + * Generates sample data is this is a fresh copy of the application + */ + public void init() { + if (this.forumBookStorage.isFresh()) { + new SampleDataGenerator(this).generate(); + this.commit(); + } + } +} + diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/com/t13g2/forum/model/UserPrefs.java similarity index 68% rename from src/main/java/seedu/address/model/UserPrefs.java rename to src/main/java/com/t13g2/forum/model/UserPrefs.java index 980b2b388852..fe4c9e7138aa 100644 --- a/src/main/java/seedu/address/model/UserPrefs.java +++ b/src/main/java/com/t13g2/forum/model/UserPrefs.java @@ -1,10 +1,10 @@ -package seedu.address.model; +package com.t13g2.forum.model; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Objects; -import seedu.address.commons.core.GuiSettings; +import com.t13g2.forum.commons.core.GuiSettings; /** * Represents User's preferences. @@ -12,7 +12,7 @@ public class UserPrefs { private GuiSettings guiSettings; - private Path addressBookFilePath = Paths.get("data" , "addressbook.xml"); + private Path forumBookFilePath = Paths.get("data" , "addressbook.xml"); public UserPrefs() { setGuiSettings(500, 500, 0, 0); @@ -30,12 +30,12 @@ public void setGuiSettings(double width, double height, int x, int y) { guiSettings = new GuiSettings(width, height, x, y); } - public Path getAddressBookFilePath() { - return addressBookFilePath; + public Path getForumBookFilePath() { + return forumBookFilePath; } - public void setAddressBookFilePath(Path addressBookFilePath) { - this.addressBookFilePath = addressBookFilePath; + public void setForumBookFilePath(Path forumBookFilePath) { + this.forumBookFilePath = forumBookFilePath; } @Override @@ -50,19 +50,19 @@ public boolean equals(Object other) { UserPrefs o = (UserPrefs) other; return Objects.equals(guiSettings, o.guiSettings) - && Objects.equals(addressBookFilePath, o.addressBookFilePath); + && Objects.equals(forumBookFilePath, o.forumBookFilePath); } @Override public int hashCode() { - return Objects.hash(guiSettings, addressBookFilePath); + return Objects.hash(guiSettings, forumBookFilePath); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Gui Settings : " + guiSettings.toString()); - sb.append("\nLocal data file location : " + addressBookFilePath); + sb.append("\nLocal data file location : " + forumBookFilePath); return sb.toString(); } diff --git a/src/main/java/com/t13g2/forum/model/UserRepository.java b/src/main/java/com/t13g2/forum/model/UserRepository.java new file mode 100644 index 000000000000..28b7b326cae6 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/UserRepository.java @@ -0,0 +1,113 @@ +//@@author Meowzz95 +package com.t13g2.forum.model; + +import java.util.Objects; +import java.util.Optional; + +import com.sun.istack.NotNull; +import com.t13g2.forum.commons.util.Extensions; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; +import com.t13g2.forum.storage.forum.IForumBookStorage; + +/** + * Provides APIs to manipulate {@link User} + */ +public class UserRepository extends BaseRepository implements IUserRepository { + /** + * Creates a new BaseRepository instance. + * + * @param forumBookStorage of type IForumBookStorage + */ + public UserRepository(IForumBookStorage forumBookStorage) { + super(forumBookStorage); + } + + /** + * Adds an {@link User} into database + * + * @param user + * @return Id of the object added + */ + @Override + public int addUser(@NotNull User user) { + Objects.requireNonNull(user, "user can't be null"); + forumBookStorage.getUsers().getList().add(user); + forumBookStorage.getUsers().setDirty(); + return user.getId(); + } + + /** + * Updates an {@link User} + * @param user + */ + @Override + public void updateUser(@NotNull User user) { + Objects.requireNonNull(user, "user can't be null"); + Extensions.updateObjectInList(forumBookStorage.getUsers().getList(), user); + forumBookStorage.getUsers().setDirty(); + } + + /** + * Deletes an {@link User} + * @param user + */ + @Override + public void deleteUser(@NotNull User user) { + Objects.requireNonNull(user, "user can't be null"); + this.deleteUser(user.getId()); + } + + /** + * Deletes an {@link User} + * @param userId + */ + @Override + public void deleteUser(int userId) { + this.removeById(forumBookStorage.getUsers().getList(), userId); + forumBookStorage.getUsers().setDirty(); + } + + /** + * Gets an {@link User} by its object Id + * @param userId + * @return the {@link User} queried + * @throws EntityDoesNotExistException + */ + @Override + public User getUser(int userId) throws EntityDoesNotExistException { + return this.getById(forumBookStorage.getUsers().getList(), userId); + } + + /** + * Gets a user by its username + * @param username + * @return user queried + * @throws EntityDoesNotExistException + */ + @Override + public User getUserByUsername(String username) throws EntityDoesNotExistException { + Optional userInDb = forumBookStorage.getUsers().getList().stream() + .filter(user -> user.getUsername().equals(username)).findFirst(); + if (!userInDb.isPresent()) { + throw new EntityDoesNotExistException("Username does not exist"); + } + return userInDb.get(); + } + + /** + * Checks if the given username and password match with the record in the database + * @param username + * @param password + * @return user matched + * @throws EntityDoesNotExistException + */ + @Override + public User authenticate(String username, String password) throws EntityDoesNotExistException { + User user = getUserByUsername(username); + if (user.getPassword().equals(password)) { + return user; + } + return null; + } +} diff --git a/src/main/java/seedu/address/model/VersionedAddressBook.java b/src/main/java/com/t13g2/forum/model/VersionedForumBook.java similarity index 80% rename from src/main/java/seedu/address/model/VersionedAddressBook.java rename to src/main/java/com/t13g2/forum/model/VersionedForumBook.java index 227a335045d7..885bb3d00e37 100644 --- a/src/main/java/seedu/address/model/VersionedAddressBook.java +++ b/src/main/java/com/t13g2/forum/model/VersionedForumBook.java @@ -1,31 +1,31 @@ -package seedu.address.model; +package com.t13g2.forum.model; import java.util.ArrayList; import java.util.List; /** - * {@code AddressBook} that keeps track of its own history. + * {@code ForumBook} that keeps track of its own history. */ -public class VersionedAddressBook extends AddressBook { +public class VersionedForumBook extends ForumBook { - private final List addressBookStateList; + private final List addressBookStateList; private int currentStatePointer; - public VersionedAddressBook(ReadOnlyAddressBook initialState) { + public VersionedForumBook(ReadOnlyForumBook initialState) { super(initialState); addressBookStateList = new ArrayList<>(); - addressBookStateList.add(new AddressBook(initialState)); + addressBookStateList.add(new ForumBook(initialState)); currentStatePointer = 0; } /** - * Saves a copy of the current {@code AddressBook} state at the end of the state list. + * Saves a copy of the current {@code ForumBook} state at the end of the state list. * Undone states are removed from the state list. */ public void commit() { removeStatesAfterCurrentPointer(); - addressBookStateList.add(new AddressBook(this)); + addressBookStateList.add(new ForumBook(this)); currentStatePointer++; } @@ -77,11 +77,11 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof VersionedAddressBook)) { + if (!(other instanceof VersionedForumBook)) { return false; } - VersionedAddressBook otherVersionedAddressBook = (VersionedAddressBook) other; + VersionedForumBook otherVersionedAddressBook = (VersionedForumBook) other; // state check return super.equals(otherVersionedAddressBook) diff --git a/src/main/java/com/t13g2/forum/model/forum/Announcement.java b/src/main/java/com/t13g2/forum/model/forum/Announcement.java new file mode 100644 index 000000000000..0b1303a27b9c --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/forum/Announcement.java @@ -0,0 +1,65 @@ +package com.t13g2.forum.model.forum; + +import com.t13g2.forum.commons.util.AppUtil; +import com.t13g2.forum.commons.util.CollectionUtil; + +/** + * Represents the announcement in ForumBook. + * Guarantees: is valid as declared in {@link #isValidAnnouncement(String)} + */ +public class Announcement extends BaseModel { + /** + * Show message if announcement is not valid + */ + public static final String MESSAGE_ANNOUNCEMENT_TITLE_CONSTRAINTS = + "Invalid parameter: aTitle can take any values, and they should not be blank"; + public static final String MESSAGE_ANNOUNCEMENT_CONTENT_CONSTRAINTS = + "Invalid parameter: aContent can take any values, and they should not be blank"; + + /** + * The first character of the announcement must not be a whitespace, + * otherwise " " (a blank string) becomes a valid input. + */ + public static final String ANNOUNCEMENT_VALIDATION_REGEX = "[^\\s].*"; + private static final long serialVersionUID = 1L; + + private String title; + private String content; + public Announcement() { + } + /** + * Every field must be present and not null. + */ + public Announcement(String title, String content) { + CollectionUtil.requireAllNonNull(title, content); + AppUtil.checkArgument(isValidAnnouncement(title), MESSAGE_ANNOUNCEMENT_TITLE_CONSTRAINTS); + AppUtil.checkArgument(isValidAnnouncement(content), MESSAGE_ANNOUNCEMENT_CONTENT_CONSTRAINTS); + this.title = title; + this.content = content; + } + + /** + * Returns true if a given string is a valid email. + */ + public static boolean isValidAnnouncement(String testString) { + return (testString.matches(ANNOUNCEMENT_VALIDATION_REGEX)); + } + + public String getTitle() { + return title; + } + + public String getContent() { + return content; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("\nTitle: ") + .append(title) + .append("\nContent: ") + .append(content); + return builder.toString(); + } +} diff --git a/src/main/java/com/t13g2/forum/model/forum/BaseModel.java b/src/main/java/com/t13g2/forum/model/forum/BaseModel.java new file mode 100644 index 000000000000..41b2681dc0af --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/forum/BaseModel.java @@ -0,0 +1,50 @@ +package com.t13g2.forum.model.forum; + +import java.io.Serializable; +import java.util.Date; + +import com.t13g2.forum.storage.forum.RunningId; +//@@author Meowzz95 +/** + * Metadata for the other classes + */ +public class BaseModel implements Serializable { + + protected int id = RunningId.getInstance().nextId(); + protected Date created = new Date(); + protected Date modified; + protected int createdByUserId; + protected int modifiedByUserId; + + public int getId() { + return id; + } + + public Date getCreated() { + return created; + } + + public Date getModified() { + return modified; + } + + public int getCreatedByUserId() { + return createdByUserId; + } + + public int getModifiedByUserId() { + return modifiedByUserId; + } + + public void setModified(Date modified) { + this.modified = modified; + } + + public void setCreatedByUserId(int createdByUserId) { + this.createdByUserId = createdByUserId; + } + + public void setModifiedByUserId(int modifiedByUserId) { + this.modifiedByUserId = modifiedByUserId; + } +} diff --git a/src/main/java/com/t13g2/forum/model/forum/Comment.java b/src/main/java/com/t13g2/forum/model/forum/Comment.java new file mode 100644 index 000000000000..81d76c4828a6 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/forum/Comment.java @@ -0,0 +1,34 @@ +package com.t13g2.forum.model.forum; + +/** + * Represents comment under thread in ForumBook + */ +public class Comment extends BaseModel { + public static final String MESSAGE_COMMENT_ID_CONSTRAINTS = + "Comment ID should only contain an integer, and it should not be blank"; + public static final String COMMENT_ID_VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; + + private int threadId; + private String content; + public Comment(){} + public Comment(int threadId, String content) { + this.threadId = threadId; + this.content = content; + } + + public int getThreadId() { + return threadId; + } + + public void setThreadId(int threadId) { + this.threadId = threadId; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/src/main/java/com/t13g2/forum/model/forum/ForumThread.java b/src/main/java/com/t13g2/forum/model/forum/ForumThread.java new file mode 100644 index 000000000000..28ef69587f01 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/forum/ForumThread.java @@ -0,0 +1,42 @@ +package com.t13g2.forum.model.forum; + +import java.util.List; + +/** + * Represents thread under module in ForumBook + */ +public class ForumThread extends BaseModel { + public static final String MESSAGE_THREAD_ID_CONSTRAINTS = + "Thread ID should only contain an integer, and it should not be blank"; + public static final String THREAD_ID_VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; + + private int moduleId; + private String title; + // Identity FieldAddress + private List comments; + public ForumThread() {} + public ForumThread(int moduleId, String title) { + this.moduleId = moduleId; + this.title = title; + } + + public int getModuleId() { + return moduleId; + } + + public String getTitle() { + return title; + } + + public List getComments() { + return comments; + } + + public void setModuleId(int moduleId) { + this.moduleId = moduleId; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/src/main/java/com/t13g2/forum/model/forum/Module.java b/src/main/java/com/t13g2/forum/model/forum/Module.java new file mode 100644 index 000000000000..26f97fbe5507 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/forum/Module.java @@ -0,0 +1,49 @@ +package com.t13g2.forum.model.forum; + +import java.util.List; + +/** + * Represents module in ForumBook + */ +public class Module extends BaseModel { + public static final String MESSAGE_MODULE_CODE_CONSTRAINTS = + "Invalid parameter: mCode should follow (2 or 3 capital letters)+(4 numbers)+(0 or 1 capital letter)" + + "\nand it should not be blank. E.g. MA1580E, CS2113 or USP1000A, USP1000"; + public static final String MESSAGE_MODULE_TITLE_CONSTRAINTS = + "Invalid parameter: mTitle should not be blank"; + public static final String MESSAGE_MODULE_ID_OUT_OF_BOUND = "mId is outside of Integer range!"; + public static final String MESSAGE_MODULE_ID_NEGATIVE = "mId should be in the range of 0 ~ INT_MAX"; + public static final String MODULE_CODE_VALIDATION_REGEX = "[A-Z]{2,3}[0-9]{4}[A-Z]{0,1}"; + public static final String MODULE_TITLE_VALIDATION_REGEX = "[^\\s].*"; + + private String title; + private String moduleCode; + + private List forumThreads; + + public Module(String title, String moduleCode) { + this.title = title; + this.moduleCode = moduleCode; + } + + public String getTitle() { + return title; + } + + public String getModuleCode() { + return moduleCode; + } + + public List getForumThreads() { + return forumThreads; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setModuleCode(String moduleCode) { + this.moduleCode = moduleCode; + } + +} diff --git a/src/main/java/com/t13g2/forum/model/forum/User.java b/src/main/java/com/t13g2/forum/model/forum/User.java new file mode 100644 index 000000000000..239446344a49 --- /dev/null +++ b/src/main/java/com/t13g2/forum/model/forum/User.java @@ -0,0 +1,107 @@ +package com.t13g2.forum.model.forum; + +/** + * Represents user in ForumBook + */ +public class User extends BaseModel { + public static final String MESSAGE_USER_NAME_CONSTRAINTS = + "Invalid parameter: uName can take any values, and it should not be blank"; + public static final String MESSAGE_USER_PASSWORD_CONSTRAINTS = + "Invalid parameter: uPass can take any values, and it should not be blank"; + public static final String MESSAGE_NOT_ADMIN = "You are not an admin!"; + public static final String MESSAGE_NOT_LOGIN = "Please login in order to proceed!"; + /** + * The first character of the user name must not be a whitespace, + * otherwise " " (a blank string) becomes a valid input. + */ + public static final String USER_NAME_VALIDATION_REGEX = "[^\\s].*"; + public static final String USER_PASSWORD_VALIDATION_REGEX = "[^\\s].*"; + private String username; + private String password; + private boolean isAdmin; + private boolean isBlock; + private String email; + private String phone; + + + public User() { + } + + public User(String username, String password, boolean isAdmin, boolean isBlock, String email, String phone) { + this.username = username; + this.password = password; + this.isAdmin = isAdmin; + this.isBlock = isBlock; + this.email = email; + this.phone = phone; + } + + /** + * Returns true if a given string is a valid email. + */ + public static boolean isValidUserName(String testUserName) { + return (testUserName.matches(USER_NAME_VALIDATION_REGEX)); + } + + public static boolean isValidUserPassword(String testUserName) { + return (testUserName.matches(USER_PASSWORD_VALIDATION_REGEX)); + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public boolean isAdmin() { + return isAdmin; + } + + public boolean isBlock() { + return isBlock; + } + + public String getEmail() { + return email; + } + + public String getPhone() { + return phone; + } + + public void setUsername(String username) { + this.username = username; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setAdmin(boolean admin) { + isAdmin = admin; + } + + public void setBlock(boolean block) { + isBlock = block; + } + + public void setEmail(String email) { + this.email = email; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(" User ID: ") + .append(id) + .append(" User Name: ") + .append(username); + return builder.toString(); + } +} diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/com/t13g2/forum/model/person/Address.java similarity index 88% rename from src/main/java/seedu/address/model/person/Address.java rename to src/main/java/com/t13g2/forum/model/person/Address.java index a1409233ceb9..5330c8b4d2bf 100644 --- a/src/main/java/seedu/address/model/person/Address.java +++ b/src/main/java/com/t13g2/forum/model/person/Address.java @@ -1,7 +1,8 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; + +import com.t13g2.forum.commons.util.AppUtil; /** * Represents a Person's address in the address book. @@ -27,7 +28,7 @@ public class Address { */ public Address(String address) { requireNonNull(address); - checkArgument(isValidAddress(address), MESSAGE_ADDRESS_CONSTRAINTS); + AppUtil.checkArgument(isValidAddress(address), MESSAGE_ADDRESS_CONSTRAINTS); value = address; } diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/com/t13g2/forum/model/person/Email.java similarity index 93% rename from src/main/java/seedu/address/model/person/Email.java rename to src/main/java/com/t13g2/forum/model/person/Email.java index 4a8283a20002..2dd8ba7ff323 100644 --- a/src/main/java/seedu/address/model/person/Email.java +++ b/src/main/java/com/t13g2/forum/model/person/Email.java @@ -1,7 +1,8 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; + +import com.t13g2.forum.commons.util.AppUtil; /** * Represents a Person's email in the address book. @@ -28,7 +29,6 @@ public class Email { + DOMAIN_FIRST_CHARACTER_REGEX + DOMAIN_MIDDLE_REGEX + DOMAIN_LAST_CHARACTER_REGEX; public final String value; - /** * Constructs an {@code Email}. * @@ -36,7 +36,7 @@ public class Email { */ public Email(String email) { requireNonNull(email); - checkArgument(isValidEmail(email), MESSAGE_EMAIL_CONSTRAINTS); + AppUtil.checkArgument(isValidEmail(email), MESSAGE_EMAIL_CONSTRAINTS); value = email; } diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/com/t13g2/forum/model/person/Name.java similarity index 89% rename from src/main/java/seedu/address/model/person/Name.java rename to src/main/java/com/t13g2/forum/model/person/Name.java index 9982393dabb5..a4d4dfaac2ee 100644 --- a/src/main/java/seedu/address/model/person/Name.java +++ b/src/main/java/com/t13g2/forum/model/person/Name.java @@ -1,7 +1,8 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; + +import com.t13g2.forum.commons.util.AppUtil; /** * Represents a Person's name in the address book. @@ -27,7 +28,7 @@ public class Name { */ public Name(String name) { requireNonNull(name); - checkArgument(isValidName(name), MESSAGE_NAME_CONSTRAINTS); + AppUtil.checkArgument(isValidName(name), MESSAGE_NAME_CONSTRAINTS); fullName = name; } diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/com/t13g2/forum/model/person/NameContainsKeywordsPredicate.java similarity index 91% rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java rename to src/main/java/com/t13g2/forum/model/person/NameContainsKeywordsPredicate.java index c9b5868427ca..448916f89efb 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ b/src/main/java/com/t13g2/forum/model/person/NameContainsKeywordsPredicate.java @@ -1,9 +1,9 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import java.util.List; import java.util.function.Predicate; -import seedu.address.commons.util.StringUtil; +import com.t13g2.forum.commons.util.StringUtil; /** * Tests that a {@code Person}'s {@code Name} matches any of the keywords given. diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/com/t13g2/forum/model/person/Person.java similarity index 74% rename from src/main/java/seedu/address/model/person/Person.java rename to src/main/java/com/t13g2/forum/model/person/Person.java index 557a7a60cd51..0167a70e44e2 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/com/t13g2/forum/model/person/Person.java @@ -1,13 +1,12 @@ -package seedu.address.model.person; - -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +package com.t13g2.forum.model.person; import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; -import seedu.address.model.tag.Tag; +import com.t13g2.forum.commons.util.CollectionUtil; +import com.t13g2.forum.model.tag.Tag; /** * Represents a Person in the address book. @@ -28,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) { - requireAllNonNull(name, phone, email, address, tags); + CollectionUtil.requireAllNonNull(name, phone, email, address, tags); this.name = name; this.phone = phone; this.email = email; @@ -70,8 +69,8 @@ public boolean isSamePerson(Person otherPerson) { } return otherPerson != null - && otherPerson.getName().equals(getName()) - && (otherPerson.getPhone().equals(getPhone()) || otherPerson.getEmail().equals(getEmail())); + && otherPerson.getName().equals(getName()) + && (otherPerson.getPhone().equals(getPhone()) || otherPerson.getEmail().equals(getEmail())); } /** @@ -90,10 +89,10 @@ public boolean equals(Object other) { Person otherPerson = (Person) other; return otherPerson.getName().equals(getName()) - && otherPerson.getPhone().equals(getPhone()) - && otherPerson.getEmail().equals(getEmail()) - && otherPerson.getAddress().equals(getAddress()) - && otherPerson.getTags().equals(getTags()); + && otherPerson.getPhone().equals(getPhone()) + && otherPerson.getEmail().equals(getEmail()) + && otherPerson.getAddress().equals(getAddress()) + && otherPerson.getTags().equals(getTags()); } @Override @@ -106,13 +105,13 @@ public int hashCode() { public String toString() { final StringBuilder builder = new StringBuilder(); builder.append(getName()) - .append(" Phone: ") - .append(getPhone()) - .append(" Email: ") - .append(getEmail()) - .append(" Address: ") - .append(getAddress()) - .append(" Tags: "); + .append(" Phone: ") + .append(getPhone()) + .append(" Email: ") + .append(getEmail()) + .append(" Address: ") + .append(getAddress()) + .append(" Tags: "); getTags().forEach(builder::append); return builder.toString(); } diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/com/t13g2/forum/model/person/Phone.java similarity index 88% rename from src/main/java/seedu/address/model/person/Phone.java rename to src/main/java/com/t13g2/forum/model/person/Phone.java index a22e51653835..352785cc4fbd 100644 --- a/src/main/java/seedu/address/model/person/Phone.java +++ b/src/main/java/com/t13g2/forum/model/person/Phone.java @@ -1,7 +1,8 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; + +import com.t13g2.forum.commons.util.AppUtil; /** * Represents a Person's phone number in the address book. @@ -22,7 +23,7 @@ public class Phone { */ public Phone(String phone) { requireNonNull(phone); - checkArgument(isValidPhone(phone), MESSAGE_PHONE_CONSTRAINTS); + AppUtil.checkArgument(isValidPhone(phone), MESSAGE_PHONE_CONSTRAINTS); value = phone; } diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/com/t13g2/forum/model/person/UniquePersonList.java similarity index 92% rename from src/main/java/seedu/address/model/person/UniquePersonList.java rename to src/main/java/com/t13g2/forum/model/person/UniquePersonList.java index 5856aa42e6b5..951b2198a661 100644 --- a/src/main/java/seedu/address/model/person/UniquePersonList.java +++ b/src/main/java/com/t13g2/forum/model/person/UniquePersonList.java @@ -1,15 +1,16 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.util.Iterator; import java.util.List; +import com.t13g2.forum.commons.util.CollectionUtil; +import com.t13g2.forum.model.person.exceptions.DuplicatePersonException; +import com.t13g2.forum.model.person.exceptions.PersonNotFoundException; + import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; /** * A list of persons that enforces uniqueness between its elements and does not allow nulls. @@ -52,7 +53,7 @@ public void add(Person toAdd) { * The person identity of {@code editedPerson} must not be the same as another existing person in the list. */ public void setPerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); + CollectionUtil.requireAllNonNull(target, editedPerson); int index = internalList.indexOf(target); if (index == -1) { @@ -87,7 +88,7 @@ public void setPersons(UniquePersonList replacement) { * {@code persons} must not contain duplicate persons. */ public void setPersons(List persons) { - requireAllNonNull(persons); + CollectionUtil.requireAllNonNull(persons); if (!personsAreUnique(persons)) { throw new DuplicatePersonException(); } diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/com/t13g2/forum/model/person/exceptions/DuplicatePersonException.java similarity index 86% rename from src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java rename to src/main/java/com/t13g2/forum/model/person/exceptions/DuplicatePersonException.java index d7290f594423..b1d315602b1c 100644 --- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java +++ b/src/main/java/com/t13g2/forum/model/person/exceptions/DuplicatePersonException.java @@ -1,4 +1,4 @@ -package seedu.address.model.person.exceptions; +package com.t13g2.forum.model.person.exceptions; /** * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/com/t13g2/forum/model/person/exceptions/PersonNotFoundException.java similarity index 74% rename from src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java rename to src/main/java/com/t13g2/forum/model/person/exceptions/PersonNotFoundException.java index fa764426ca73..a4e930a54d36 100644 --- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java +++ b/src/main/java/com/t13g2/forum/model/person/exceptions/PersonNotFoundException.java @@ -1,4 +1,4 @@ -package seedu.address.model.person.exceptions; +package com.t13g2.forum.model.person.exceptions; /** * Signals that the operation is unable to find the specified person. diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/com/t13g2/forum/model/tag/Tag.java similarity index 88% rename from src/main/java/seedu/address/model/tag/Tag.java rename to src/main/java/com/t13g2/forum/model/tag/Tag.java index 8cdff2773ac9..f387b36b159e 100644 --- a/src/main/java/seedu/address/model/tag/Tag.java +++ b/src/main/java/com/t13g2/forum/model/tag/Tag.java @@ -1,7 +1,8 @@ -package seedu.address.model.tag; +package com.t13g2.forum.model.tag; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; + +import com.t13g2.forum.commons.util.AppUtil; /** * Represents a Tag in the address book. @@ -21,7 +22,7 @@ public class Tag { */ public Tag(String tagName) { requireNonNull(tagName); - checkArgument(isValidTagName(tagName), MESSAGE_TAG_CONSTRAINTS); + AppUtil.checkArgument(isValidTagName(tagName), MESSAGE_TAG_CONSTRAINTS); this.tagName = tagName; } diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/com/t13g2/forum/model/util/SampleDataUtil.java similarity index 77% rename from src/main/java/seedu/address/model/util/SampleDataUtil.java rename to src/main/java/com/t13g2/forum/model/util/SampleDataUtil.java index 1806da4facfa..9e74eb59ad61 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/com/t13g2/forum/model/util/SampleDataUtil.java @@ -1,20 +1,20 @@ -package seedu.address.model.util; +package com.t13g2.forum.model.util; import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.ReadOnlyForumBook; +import com.t13g2.forum.model.person.Address; +import com.t13g2.forum.model.person.Email; +import com.t13g2.forum.model.person.Name; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.model.person.Phone; +import com.t13g2.forum.model.tag.Tag; /** - * Contains utility methods for populating {@code AddressBook} with sample data. + * Contains utility methods for populating {@code ForumBook} with sample data. */ public class SampleDataUtil { public static Person[] getSamplePersons() { @@ -40,8 +40,8 @@ public static Person[] getSamplePersons() { }; } - public static ReadOnlyAddressBook getSampleAddressBook() { - AddressBook sampleAb = new AddressBook(); + public static ReadOnlyForumBook getSampleForumBook() { + ForumBook sampleAb = new ForumBook(); for (Person samplePerson : getSamplePersons()) { sampleAb.addPerson(samplePerson); } diff --git a/src/main/java/com/t13g2/forum/storage/ForumBookStorage.java b/src/main/java/com/t13g2/forum/storage/ForumBookStorage.java new file mode 100644 index 000000000000..b58c81691031 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/ForumBookStorage.java @@ -0,0 +1,46 @@ +package com.t13g2.forum.storage; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; + +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.ReadOnlyForumBook; + +/** + * Represents a storage for {@link ForumBook}. + */ +public interface ForumBookStorage { + + /** + * Returns the file path of the data file. + */ + Path getForumBookFilePath(); + + /** + * Returns ForumBook data as a {@link ReadOnlyForumBook}. + * 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 readForumBook() throws DataConversionException, IOException; + + /** + * @see #getForumBookFilePath() + */ + Optional readForumBook(Path filePath) throws DataConversionException, IOException; + + /** + * Saves the given {@link ReadOnlyForumBook} to the storage. + * @param addressBook cannot be null. + * @throws IOException if there was any problem writing to the file. + */ + void saveForumBook(ReadOnlyForumBook addressBook) throws IOException; + + /** + * @see #saveForumBook(ReadOnlyForumBook) + */ + void saveForumBook(ReadOnlyForumBook addressBook, Path filePath) throws IOException; + +} diff --git a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java b/src/main/java/com/t13g2/forum/storage/JsonUserPrefsStorage.java similarity index 85% rename from src/main/java/seedu/address/storage/JsonUserPrefsStorage.java rename to src/main/java/com/t13g2/forum/storage/JsonUserPrefsStorage.java index 2ab927023cc4..6e32bebdf055 100644 --- a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java +++ b/src/main/java/com/t13g2/forum/storage/JsonUserPrefsStorage.java @@ -1,12 +1,12 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.commons.util.JsonUtil; -import seedu.address.model.UserPrefs; +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.commons.util.JsonUtil; +import com.t13g2.forum.model.UserPrefs; /** * A class to access UserPrefs stored in the hard disk as a json file diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/com/t13g2/forum/storage/Storage.java similarity index 51% rename from src/main/java/seedu/address/storage/Storage.java rename to src/main/java/com/t13g2/forum/storage/Storage.java index 28791127999b..c64b53fd5633 100644 --- a/src/main/java/seedu/address/storage/Storage.java +++ b/src/main/java/com/t13g2/forum/storage/Storage.java @@ -1,19 +1,19 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -import seedu.address.commons.events.model.AddressBookChangedEvent; -import seedu.address.commons.events.storage.DataSavingExceptionEvent; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.UserPrefs; +import com.t13g2.forum.commons.events.model.AddressBookChangedEvent; +import com.t13g2.forum.commons.events.storage.DataSavingExceptionEvent; +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.model.ReadOnlyForumBook; +import com.t13g2.forum.model.UserPrefs; /** * API of the Storage component */ -public interface Storage extends AddressBookStorage, UserPrefsStorage { +public interface Storage extends ForumBookStorage, UserPrefsStorage { @Override Optional readUserPrefs() throws DataConversionException, IOException; @@ -22,13 +22,13 @@ public interface Storage extends AddressBookStorage, UserPrefsStorage { void saveUserPrefs(UserPrefs userPrefs) throws IOException; @Override - Path getAddressBookFilePath(); + Path getForumBookFilePath(); @Override - Optional readAddressBook() throws DataConversionException, IOException; + Optional readForumBook() throws DataConversionException, IOException; @Override - void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; + void saveForumBook(ReadOnlyForumBook addressBook) throws IOException; /** * Saves the current version of the Address Book to the hard disk. diff --git a/src/main/java/com/t13g2/forum/storage/StorageManager.java b/src/main/java/com/t13g2/forum/storage/StorageManager.java new file mode 100644 index 000000000000..19d9ae332fc6 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/StorageManager.java @@ -0,0 +1,92 @@ +package com.t13g2.forum.storage; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; +import java.util.logging.Logger; + +import com.google.common.eventbus.Subscribe; +import com.t13g2.forum.commons.core.ComponentManager; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.events.model.AddressBookChangedEvent; +import com.t13g2.forum.commons.events.storage.DataSavingExceptionEvent; +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.model.ReadOnlyForumBook; +import com.t13g2.forum.model.UserPrefs; + +/** + * Manages storage of ForumBook data in local storage. + */ +public class StorageManager extends ComponentManager implements Storage { + + private static final Logger logger = LogsCenter.getLogger(StorageManager.class); + private ForumBookStorage forumBookStorage; + private UserPrefsStorage userPrefsStorage; + + + public StorageManager(ForumBookStorage forumBookStorage, UserPrefsStorage userPrefsStorage) { + super(); + this.forumBookStorage = forumBookStorage; + this.userPrefsStorage = userPrefsStorage; + } + + // ================ UserPrefs methods ============================== + + @Override + public Path getUserPrefsFilePath() { + return userPrefsStorage.getUserPrefsFilePath(); + } + + @Override + public Optional readUserPrefs() throws DataConversionException, IOException { + return userPrefsStorage.readUserPrefs(); + } + + @Override + public void saveUserPrefs(UserPrefs userPrefs) throws IOException { + userPrefsStorage.saveUserPrefs(userPrefs); + } + + + // ================ ForumBook methods ============================== + + @Override + public Path getForumBookFilePath() { + return forumBookStorage.getForumBookFilePath(); + } + + @Override + public Optional readForumBook() throws DataConversionException, IOException { + return readForumBook(forumBookStorage.getForumBookFilePath()); + } + + @Override + public Optional readForumBook(Path filePath) throws DataConversionException, IOException { + logger.fine("Attempting to read data from file: " + filePath); + return forumBookStorage.readForumBook(filePath); + } + + @Override + public void saveForumBook(ReadOnlyForumBook addressBook) throws IOException { + saveForumBook(addressBook, forumBookStorage.getForumBookFilePath()); + } + + @Override + public void saveForumBook(ReadOnlyForumBook addressBook, Path filePath) throws IOException { + logger.fine("Attempting to write to data file: " + filePath); + forumBookStorage.saveForumBook(addressBook, filePath); + } + + + @Override + @Subscribe + public void handleAddressBookChangedEvent(AddressBookChangedEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event, "Local data changed, saving to file")); + try { + saveForumBook(event.data); + } catch (IOException e) { + raise(new DataSavingExceptionEvent(e)); + } + } + +} diff --git a/src/main/java/seedu/address/storage/UserPrefsStorage.java b/src/main/java/com/t13g2/forum/storage/UserPrefsStorage.java similarity index 74% rename from src/main/java/seedu/address/storage/UserPrefsStorage.java rename to src/main/java/com/t13g2/forum/storage/UserPrefsStorage.java index 877b0ee5c4f0..6da9bbe0a4f8 100644 --- a/src/main/java/seedu/address/storage/UserPrefsStorage.java +++ b/src/main/java/com/t13g2/forum/storage/UserPrefsStorage.java @@ -1,14 +1,14 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.UserPrefs; +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.model.UserPrefs; /** - * Represents a storage for {@link seedu.address.model.UserPrefs}. + * Represents a storage for {@link UserPrefs}. */ public interface UserPrefsStorage { @@ -26,7 +26,7 @@ public interface UserPrefsStorage { Optional readUserPrefs() throws DataConversionException, IOException; /** - * Saves the given {@link seedu.address.model.UserPrefs} to the storage. + * Saves the given {@link UserPrefs} to the storage. * @param userPrefs cannot be null. * @throws IOException if there was any problem writing to the file. */ diff --git a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java b/src/main/java/com/t13g2/forum/storage/XmlAdaptedPerson.java similarity index 92% rename from src/main/java/seedu/address/storage/XmlAdaptedPerson.java rename to src/main/java/com/t13g2/forum/storage/XmlAdaptedPerson.java index c03785e5700f..0b903c5d3374 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java +++ b/src/main/java/com/t13g2/forum/storage/XmlAdaptedPerson.java @@ -1,4 +1,4 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import java.util.ArrayList; import java.util.HashSet; @@ -6,16 +6,15 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; - 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.tag.Tag; +import com.t13g2.forum.commons.exceptions.IllegalValueException; +import com.t13g2.forum.model.person.Address; +import com.t13g2.forum.model.person.Email; +import com.t13g2.forum.model.person.Name; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.model.person.Phone; +import com.t13g2.forum.model.tag.Tag; /** * JAXB-friendly version of the Person. diff --git a/src/main/java/seedu/address/storage/XmlAdaptedTag.java b/src/main/java/com/t13g2/forum/storage/XmlAdaptedTag.java similarity index 91% rename from src/main/java/seedu/address/storage/XmlAdaptedTag.java rename to src/main/java/com/t13g2/forum/storage/XmlAdaptedTag.java index d3e2d8be9c4f..f4b5d274efb8 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedTag.java +++ b/src/main/java/com/t13g2/forum/storage/XmlAdaptedTag.java @@ -1,9 +1,9 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import javax.xml.bind.annotation.XmlValue; -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.tag.Tag; +import com.t13g2.forum.commons.exceptions.IllegalValueException; +import com.t13g2.forum.model.tag.Tag; /** * JAXB-friendly adapted version of the Tag. diff --git a/src/main/java/seedu/address/storage/XmlFileStorage.java b/src/main/java/com/t13g2/forum/storage/XmlFileStorage.java similarity index 77% rename from src/main/java/seedu/address/storage/XmlFileStorage.java rename to src/main/java/com/t13g2/forum/storage/XmlFileStorage.java index d8f65dc036ab..84ebcc246f25 100644 --- a/src/main/java/seedu/address/storage/XmlFileStorage.java +++ b/src/main/java/com/t13g2/forum/storage/XmlFileStorage.java @@ -1,12 +1,11 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import java.io.FileNotFoundException; import java.nio.file.Path; - import javax.xml.bind.JAXBException; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.commons.util.XmlUtil; +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.commons.util.XmlUtil; /** * Stores addressbook data in an XML file @@ -16,7 +15,7 @@ public class XmlFileStorage { * Saves the given addressbook data to the specified file. */ public static void saveDataToFile(Path file, XmlSerializableAddressBook addressBook) - throws FileNotFoundException { + throws FileNotFoundException { try { XmlUtil.saveDataToFile(file, addressBook); } catch (JAXBException e) { @@ -28,7 +27,7 @@ public static void saveDataToFile(Path file, XmlSerializableAddressBook addressB * Returns address book in the file or an empty address book */ public static XmlSerializableAddressBook loadDataFromSaveFile(Path file) throws DataConversionException, - FileNotFoundException { + FileNotFoundException { try { return XmlUtil.getDataFromFile(file, XmlSerializableAddressBook.class); } catch (JAXBException e) { diff --git a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java b/src/main/java/com/t13g2/forum/storage/XmlForumBookStorage.java similarity index 55% rename from src/main/java/seedu/address/storage/XmlAddressBookStorage.java rename to src/main/java/com/t13g2/forum/storage/XmlForumBookStorage.java index 8af60be0dc5d..ddcbd1084bb4 100644 --- a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java +++ b/src/main/java/com/t13g2/forum/storage/XmlForumBookStorage.java @@ -1,4 +1,4 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import static java.util.Objects.requireNonNull; @@ -9,45 +9,45 @@ import java.util.Optional; import java.util.logging.Logger; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.commons.util.FileUtil; -import seedu.address.model.ReadOnlyAddressBook; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.commons.exceptions.IllegalValueException; +import com.t13g2.forum.commons.util.FileUtil; +import com.t13g2.forum.model.ReadOnlyForumBook; /** - * A class to access AddressBook data stored as an xml file on the hard disk. + * A class to access ForumBook data stored as an xml file on the hard disk. */ -public class XmlAddressBookStorage implements AddressBookStorage { +public class XmlForumBookStorage implements ForumBookStorage { - private static final Logger logger = LogsCenter.getLogger(XmlAddressBookStorage.class); + private static final Logger logger = LogsCenter.getLogger(XmlForumBookStorage.class); private Path filePath; - public XmlAddressBookStorage(Path filePath) { + public XmlForumBookStorage(Path filePath) { this.filePath = filePath; } - public Path getAddressBookFilePath() { + public Path getForumBookFilePath() { return filePath; } @Override - public Optional readAddressBook() throws DataConversionException, IOException { - return readAddressBook(filePath); + public Optional readForumBook() throws DataConversionException, IOException { + return readForumBook(filePath); } /** - * Similar to {@link #readAddressBook()} + * Similar to {@link #readForumBook()} * @param filePath location of the data. Cannot be null * @throws DataConversionException if the file is not in the correct format. */ - public Optional readAddressBook(Path filePath) throws DataConversionException, + public Optional readForumBook(Path filePath) throws DataConversionException, FileNotFoundException { requireNonNull(filePath); if (!Files.exists(filePath)) { - logger.info("AddressBook file " + filePath + " not found"); + logger.info("ForumBook file " + filePath + " not found"); return Optional.empty(); } @@ -61,15 +61,15 @@ public Optional readAddressBook(Path filePath) throws DataC } @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException { - saveAddressBook(addressBook, filePath); + public void saveForumBook(ReadOnlyForumBook addressBook) throws IOException { + saveForumBook(addressBook, filePath); } /** - * Similar to {@link #saveAddressBook(ReadOnlyAddressBook)} + * Similar to {@link #saveForumBook(ReadOnlyForumBook)} * @param filePath location of the data. Cannot be null */ - public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException { + public void saveForumBook(ReadOnlyForumBook addressBook, Path filePath) throws IOException { requireNonNull(addressBook); requireNonNull(filePath); diff --git a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java b/src/main/java/com/t13g2/forum/storage/XmlSerializableAddressBook.java similarity index 74% rename from src/main/java/seedu/address/storage/XmlSerializableAddressBook.java rename to src/main/java/com/t13g2/forum/storage/XmlSerializableAddressBook.java index b85fa4a8f07e..c06c3e4c7b49 100644 --- a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java +++ b/src/main/java/com/t13g2/forum/storage/XmlSerializableAddressBook.java @@ -1,19 +1,18 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; - import javax.xml.bind.annotation.XmlElement; 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.person.Person; +import com.t13g2.forum.commons.exceptions.IllegalValueException; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.ReadOnlyForumBook; +import com.t13g2.forum.model.person.Person; /** - * An Immutable AddressBook that is serializable to XML format + * An Immutable ForumBook that is serializable to XML format */ @XmlRootElement(name = "addressbook") public class XmlSerializableAddressBook { @@ -34,19 +33,19 @@ public XmlSerializableAddressBook() { /** * Conversion */ - public XmlSerializableAddressBook(ReadOnlyAddressBook src) { + public XmlSerializableAddressBook(ReadOnlyForumBook src) { this(); persons.addAll(src.getPersonList().stream().map(XmlAdaptedPerson::new).collect(Collectors.toList())); } /** - * Converts this addressbook into the model's {@code AddressBook} object. + * Converts this addressbook into the model's {@code ForumBook} object. * * @throws IllegalValueException if there were any data constraints violated or duplicates in the * {@code XmlAdaptedPerson}. */ - public AddressBook toModelType() throws IllegalValueException { - AddressBook addressBook = new AddressBook(); + public ForumBook toModelType() throws IllegalValueException { + ForumBook addressBook = new ForumBook(); for (XmlAdaptedPerson p : persons) { Person person = p.toModelType(); if (addressBook.hasPerson(person)) { diff --git a/src/main/java/com/t13g2/forum/storage/forum/AnnouncementStorage.java b/src/main/java/com/t13g2/forum/storage/forum/AnnouncementStorage.java new file mode 100644 index 000000000000..cd14d1bfaf11 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/AnnouncementStorage.java @@ -0,0 +1,11 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import com.t13g2.forum.model.forum.Announcement; + +/** + * Wraps list of entities and keep track of if it is modified + */ +public class AnnouncementStorage extends BaseEntityStorage { + +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/BaseEntityStorage.java b/src/main/java/com/t13g2/forum/storage/forum/BaseEntityStorage.java new file mode 100644 index 000000000000..d46cad5e2094 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/BaseEntityStorage.java @@ -0,0 +1,49 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import java.io.Serializable; +import java.util.ArrayList; + +/** + * Wraps list of entities and keep track of if it is modified + * @param + */ +public abstract class BaseEntityStorage implements Serializable { + protected ArrayList list = new ArrayList<>(); + private boolean dirty; + + /** + * Gets the underlying list + * + * @return list of type T + */ + public ArrayList getList() { + return list; + } + + /** + * Checks if this storage is modified since last load + * @return + */ + public boolean isDirty() { + return dirty; + } + + /** + * Sets this storage's status to be 'modified' + * @return + */ + public void setDirty() { + dirty = true; + } + + /** + * Sets this storage's status to be 'unmodified' + * @return + */ + public void setFresh() { + dirty = false; + } + + +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/CommentStorage.java b/src/main/java/com/t13g2/forum/storage/forum/CommentStorage.java new file mode 100644 index 000000000000..284c50d5c778 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/CommentStorage.java @@ -0,0 +1,12 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import java.io.Serializable; + +import com.t13g2.forum.model.forum.Comment; + +/** + * Wraps list of entities and keep track of if it is modified + */ +public class CommentStorage extends BaseEntityStorage implements Serializable { +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/EntityDoesNotExistException.java b/src/main/java/com/t13g2/forum/storage/forum/EntityDoesNotExistException.java new file mode 100644 index 000000000000..7c07db405c14 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/EntityDoesNotExistException.java @@ -0,0 +1,12 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +/** + * Defines an exception that should be thrown when the queried entity + * does not exist + */ +public class EntityDoesNotExistException extends Exception { + public EntityDoesNotExistException(String message) { + super(message); + } +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/ForumBookStorage.java b/src/main/java/com/t13g2/forum/storage/forum/ForumBookStorage.java new file mode 100644 index 000000000000..18dd57b3131a --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/ForumBookStorage.java @@ -0,0 +1,257 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import com.t13g2.forum.model.forum.Announcement; + +/** + * Provides APIs to access entity repositories and handle load/save operation + */ +public class ForumBookStorage implements IForumBookStorage { + protected IStorage underlyingStorage; + + private AnnouncementStorage announcements; + private CommentStorage comments; + private ForumThreadStorage forumThreads; + private ModuleStorage modules; + private UserStorage users; + + private boolean isFresh; + + + public ForumBookStorage(IStorage underlyingStorage) { + this.underlyingStorage = underlyingStorage; + init(); + } + + /** + * Initializes forum book storage + */ + private void init() { + loadAnnouncement(); + loadComment(); + loadForumThread(); + loadUser(); + loadModule(); + } + + /** + * Saves all changes + */ + @Override + public void commit() { + saveAnnouncement(); + saveComment(); + saveForumThread(); + saveUser(); + saveModule(); + } + + /** + * Saves changes for the class + * + * @param clazz + */ + @Override + public void save(Class clazz) { + + } + + /** + * Loads data for the class + * @param clazz + */ + @Override + public void load(Class clazz) { + + } + + /** + * Executes save on entity {@link Announcement} + * Dirty check is done before saving + */ + @Override + public void saveAnnouncement() { + if (announcements.isDirty()) { + announcements.setFresh(); + underlyingStorage.write(announcements); + } + + } + + /** + * Executes load on entity {@link Announcement} + * Dirty check is done before saving + */ + @Override + public void loadAnnouncement() { + announcements = underlyingStorage.read(AnnouncementStorage.class); + if (announcements == null) { + announcements = new AnnouncementStorage(); + announcements.setDirty(); + saveAnnouncement(); + } + } + + /** + * Executes save on entity {@link com.t13g2.forum.model.forum.Comment} + * Dirty check is done before saving + */ + @Override + public void saveComment() { + if (comments.isDirty()) { + comments.setFresh(); + underlyingStorage.write(comments); + } + } + + /** + * Executes load on entity {@link com.t13g2.forum.model.forum.Comment} + * Dirty check is done before saving + */ + @Override + public void loadComment() { + comments = underlyingStorage.read(CommentStorage.class); + if (comments == null) { + comments = new CommentStorage(); + comments.setDirty(); + saveComment(); + } + } + + /** + * Executes save on entity {@link com.t13g2.forum.model.forum.ForumThread} + * Dirty check is done before saving + */ + @Override + public void saveForumThread() { + if (forumThreads.isDirty()) { + forumThreads.setFresh(); + underlyingStorage.write(forumThreads); + } + + } + + /** + * Executes load on entity {@link com.t13g2.forum.model.forum.ForumThread} + * Dirty check is done before saving + */ + @Override + public void loadForumThread() { + forumThreads = underlyingStorage.read(ForumThreadStorage.class); + if (forumThreads == null) { + forumThreads = new ForumThreadStorage(); + forumThreads.setDirty(); + saveForumThread(); + } + } + + + /** + * Executes save on entity {@link com.t13g2.forum.model.forum.User} + * Dirty check is done before saving + */ + @Override + public void saveUser() { + if (users.isDirty()) { + users.setFresh(); + underlyingStorage.write(users); + + } + } + + /** + * Executes load on entity {@link com.t13g2.forum.model.forum.User} + * Dirty check is done before saving + */ + @Override + public void loadUser() { + users = underlyingStorage.read(UserStorage.class); + if (users == null) { + users = new UserStorage(); + users.setDirty(); + saveUser(); + this.isFresh = true; + } + } + + /** + * Executes save on entity {@link com.t13g2.forum.model.forum.Module} + * Dirty check is done before saving + */ + @Override + public void saveModule() { + if (modules.isDirty()) { + modules.setFresh(); + underlyingStorage.write(modules); + } + } + + /** + * Executes load on entity {@link com.t13g2.forum.model.forum.Module} + * Dirty check is done before saving + */ + @Override + public void loadModule() { + modules = underlyingStorage.read(ModuleStorage.class); + if (modules == null) { + modules = new ModuleStorage(); + modules.setDirty(); + saveModule(); + } + } + + /** + * Gets announcement storage + * @return {@link AnnouncementStorage} + */ + @Override + public AnnouncementStorage getAnnouncements() { + return announcements; + } + + /** + * Gets threads storage + * @return {@link ForumThreadStorage} + */ + @Override + public ForumThreadStorage getForumThreads() { + return forumThreads; + } + + /** + * Gets user storage + * @return {@link UserStorage} + */ + @Override + public UserStorage getUsers() { + return users; + } + + /** + * Gets module storage + * @return {@link ModuleStorage} + */ + @Override + public ModuleStorage getModules() { + return modules; + } + + /** + * Gets comment storage + * @return {@link CommentStorage} + */ + @Override + public CommentStorage getComments() { + return comments; + } + + /** + * Checks if this is a fresh copy of the application + * @return + */ + public boolean isFresh() { + return this.isFresh; + } + + +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/ForumThreadStorage.java b/src/main/java/com/t13g2/forum/storage/forum/ForumThreadStorage.java new file mode 100644 index 000000000000..5c6f0f0893cf --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/ForumThreadStorage.java @@ -0,0 +1,10 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import com.t13g2.forum.model.forum.ForumThread; + +/** + * Wraps list of entities and keep track of if it is modified + */ +public class ForumThreadStorage extends BaseEntityStorage { +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/IEncryptor.java b/src/main/java/com/t13g2/forum/storage/forum/IEncryptor.java new file mode 100644 index 000000000000..10678f62f109 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/IEncryptor.java @@ -0,0 +1,38 @@ +package com.t13g2.forum.storage.forum; +//@@author Meowzz95 + +/** + * Provides encryption algorithm + */ +public interface IEncryptor { + /** + * Encrypts given string to an encrypted string + * + * @param text + * @return encrypted string + */ + String encryptToString(String text); + + /** + * Decrypts given string to original string + * @param text + * @return original string + */ + String decryptToString(String text); + + /** + * Encrypts given string to an encrypted byte array + * @param text + * @return byte array + */ + byte[] encryptToBytes(String text); + + /** + * Decrypts given string to original byte array + * @param text + * @return original byte array + */ + byte[] decryptToBytes(String text); + + +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/IForumBookStorage.java b/src/main/java/com/t13g2/forum/storage/forum/IForumBookStorage.java new file mode 100644 index 000000000000..7dade292294e --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/IForumBookStorage.java @@ -0,0 +1,126 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import com.t13g2.forum.model.forum.Announcement; + +/** + * Provides APIs to access entity repositories and handle load/save operation + */ +public interface IForumBookStorage { + + /** + * Saves all changes + */ + void commit(); + + /** + * Saves changes for the class + * + * @param clazz + */ + void save(Class clazz); + + /** + * Loads data for the class + * @param clazz + */ + void load(Class clazz); + + /** + * Executes save on entity {@link Announcement} + * Dirty check is done before saving + */ + void saveAnnouncement(); + + /** + * Executes load on entity {@link Announcement} + * Dirty check is done before saving + */ + void loadAnnouncement(); + + /** + * Executes save on entity {@link com.t13g2.forum.model.forum.Comment} + * Dirty check is done before saving + */ + void saveComment(); + + /** + * Executes load on entity {@link com.t13g2.forum.model.forum.Comment} + * Dirty check is done before saving + */ + void loadComment(); + + /** + * Executes save on entity {@link com.t13g2.forum.model.forum.ForumThread} + * Dirty check is done before saving + */ + void saveForumThread(); + + /** + * Executes load on entity {@link com.t13g2.forum.model.forum.ForumThread} + * Dirty check is done before saving + */ + void loadForumThread(); + + /** + * Executes save on entity {@link com.t13g2.forum.model.forum.User} + * Dirty check is done before saving + */ + void saveUser(); + + /** + * Executes load on entity {@link com.t13g2.forum.model.forum.User} + * Dirty check is done before saving + */ + void loadUser(); + + /** + * Executes save on entity {@link com.t13g2.forum.model.forum.Module} + * Dirty check is done before saving + */ + void saveModule(); + + /** + * Executes load on entity {@link com.t13g2.forum.model.forum.Module} + * Dirty check is done before saving + */ + void loadModule(); + + /** + * Checks if this is a fresh copy of the application + * @return + */ + boolean isFresh(); + + /** + * Gets announcement storage + * @return {@link AnnouncementStorage} + */ + AnnouncementStorage getAnnouncements(); + + /** + * Gets threads storage + * @return {@link ForumThreadStorage} + */ + ForumThreadStorage getForumThreads(); + + /** + * Gets user storage + * @return {@link UserStorage} + */ + UserStorage getUsers(); + + /** + * Gets module storage + * @return {@link ModuleStorage} + */ + ModuleStorage getModules(); + + /** + * Gets comment storage + * @return {@link CommentStorage} + */ + CommentStorage getComments(); + + +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/IStorage.java b/src/main/java/com/t13g2/forum/storage/forum/IStorage.java new file mode 100644 index 000000000000..9483c7e9b4bd --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/IStorage.java @@ -0,0 +1,22 @@ +package com.t13g2.forum.storage.forum; +//@@author Meowzz95 + +/** + * Provides a way to access storage system + */ +public interface IStorage { + /** + * Reads given class from storage system + * + * @param clazz + * @param + * @return data read from storage system + */ + T read(Class clazz); + + /** + * Writes given class to storage system + * @param object + */ + void write(Object object); +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/JsonFileStorage.java b/src/main/java/com/t13g2/forum/storage/forum/JsonFileStorage.java new file mode 100644 index 000000000000..64ed54d91aba --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/JsonFileStorage.java @@ -0,0 +1,64 @@ +package com.t13g2.forum.storage.forum; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import com.google.gson.Gson; +//@@author Meowzz95 + +/** + * Provides a way to save/load application data in json format + */ +public class JsonFileStorage implements IStorage { + private IEncryptor encryptor; + + public JsonFileStorage(IEncryptor encryptor) { + this.encryptor = encryptor; + } + + public JsonFileStorage() { + //default encryptor + this(new SimpleEncryptor()); + } + + /** + * Reads given class from storage system + * + * @param clazz + * @param + * @return data read from storage system + */ + @Override + public T read(Class clazz) { + try { + String json = new String(Files.readAllBytes(Paths.get(StorageMapping.getInstance().getFileName(clazz)))); + if (encryptor != null) { + json = this.encryptor.decryptToString(json); + } + return (T) new Gson().fromJson(json, clazz); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Writes given class to storage system + * @param object + */ + @Override + public void write(Object object) { + String json = new Gson().toJson(object); + if (encryptor != null) { + json = encryptor.encryptToString(json); + } + try { + Files.write(Paths.get(StorageMapping.getInstance().getFileName(object.getClass())), json.getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/ModuleStorage.java b/src/main/java/com/t13g2/forum/storage/forum/ModuleStorage.java new file mode 100644 index 000000000000..be3a2caef821 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/ModuleStorage.java @@ -0,0 +1,11 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import com.t13g2.forum.model.forum.Module; + +/** + * Wraps list of entities and keep track of if it is modified + */ +public class ModuleStorage extends BaseEntityStorage { + +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/RunningId.java b/src/main/java/com/t13g2/forum/storage/forum/RunningId.java new file mode 100644 index 000000000000..df5dd4588e02 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/RunningId.java @@ -0,0 +1,69 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +/** + * Provides auto increment integer Ids for entity classes + */ +public class RunningId { + private static RunningId ourInstance = new RunningId(); + + private RunningId() { + init(); + } + + public static RunningId getInstance() { + return ourInstance; + } + + /** + * Saves next Id + * @param currentId + */ + private void writeToFile(int currentId) { + try { + Files.write(Paths.get(StorageMapping.getInstance().getFileName(RunningId.class)), + String.valueOf(currentId + 1).getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Reads current Id + * @return + */ + private int readFromFile() { + try { + String text = new String(Files.readAllBytes(Paths.get(StorageMapping.getInstance() + .getFileName(RunningId.class)))); + return Integer.valueOf(text); + } catch (IOException e) { + //TODO: handle error + e.printStackTrace(); + } + return -1; + } + + /** + * Checks the existence of id record, if not, creates one with next Id 0 + */ + private void init() { + if (!Files.exists(Paths.get(StorageMapping.getInstance().getFileName(RunningId.class)))) { + writeToFile(0); + } + } + + /** + * Gets Id for an entity + * @return next auto incremented id + */ + public int nextId() { + int id = readFromFile(); + writeToFile(id); + return id; + } +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/SimpleEncryptor.java b/src/main/java/com/t13g2/forum/storage/forum/SimpleEncryptor.java new file mode 100644 index 000000000000..f0a9a02c0931 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/SimpleEncryptor.java @@ -0,0 +1,84 @@ +package com.t13g2.forum.storage.forum; +//@@author Meowzz95 + +/** + * Provides a simple OR encryption + */ +public class SimpleEncryptor implements IEncryptor { + private static final String DEFAULT_KEY = "Iamastupidencryptor"; + private String key; + private byte[] keyBytes; + + public SimpleEncryptor(String key) { + this.key = key; + this.keyBytes = key.getBytes(); + } + + public SimpleEncryptor() { + this(DEFAULT_KEY); + } + + /** + * Encrypts given string to an encrypted string + * + * @param text + * @return encrypted string + */ + @Override + public String encryptToString(String text) { + return new String(this.encryptToBytes(text)); + } + + /** + * Decrypts given string to original string + * @param text + * @return original string + */ + @Override + public String decryptToString(String text) { + return new String(this.decryptToBytes(text)); + } + + /** + * Encrypts given string to an encrypted byte array + * @param text + * @return byte array + */ + @Override + public byte[] encryptToBytes(String text) { + return this.orAlgorithm(text); + } + + /** + * Decrypts given string to original byte array + * @param text + * @return original byte array + */ + @Override + public byte[] decryptToBytes(String text) { + return this.orAlgorithm(text); + } + + /** + * Uses a simple OR encryption to encrypt the given text + * @param text + * @return encrypted byte array + */ + private byte[] orAlgorithm(String text) { + byte[] bytes = text.getBytes(); + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) (bytes[i] ^ this.keyBytes[this.getKeyBytesIndex(i)]); + } + return bytes; + } + + /** + * Calculates which bit to do OR operation with when the text to be + * encrypted is longer than the key + * @param index + * @return index in key byte array + */ + private int getKeyBytesIndex(int index) { + return index % this.keyBytes.length; + } +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/StorageMapping.java b/src/main/java/com/t13g2/forum/storage/forum/StorageMapping.java new file mode 100644 index 000000000000..8f856583bde8 --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/StorageMapping.java @@ -0,0 +1,71 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; + +/** + * Provides mapping of Java entity class and data file path + */ +public class StorageMapping { + private static StorageMapping ourInstance; + private static String dataFolder; + private HashMap classMapFileName; + + private StorageMapping() { + initDataFolder(); + classMapFileName = new HashMap<>(); + classMapFileName.put(AnnouncementStorage.class, Paths.get(dataFolder, "ann.json").toString()); + classMapFileName.put(CommentStorage.class, Paths.get(dataFolder, "comment.json").toString()); + classMapFileName.put(ForumThreadStorage.class, Paths.get(dataFolder, "threads.json").toString()); + classMapFileName.put(ModuleStorage.class, Paths.get(dataFolder, "modules.json").toString()); + classMapFileName.put(UserStorage.class, Paths.get(dataFolder, "user.json").toString()); + classMapFileName.put(RunningId.class, Paths.get(dataFolder, "i").toString()); + } + + public static StorageMapping getInstance() { + if (ourInstance == null) { + ourInstance = new StorageMapping(); + } + return ourInstance; + } + + /** + * Gets data file path based given Java class + * + * @param clazz of type Class + * @return String + */ + public String getFileName(Class clazz) { + return classMapFileName.get(clazz); + } + + /** + * Adds mapping infomation + * + * @param clazz of type Class + * @param path of type String + */ + public void addMapping(Class clazz, String path) { + classMapFileName.put(clazz, path); + } + + + /** + * Checks the existence of data folder and creates it if not exist + */ + private void initDataFolder() { + dataFolder = Paths.get(Paths.get("").toString(), "forumData").toString(); + if (!Files.exists(Paths.get(dataFolder))) { + try { + Files.createDirectory(Paths.get(dataFolder)); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + +} diff --git a/src/main/java/com/t13g2/forum/storage/forum/UserStorage.java b/src/main/java/com/t13g2/forum/storage/forum/UserStorage.java new file mode 100644 index 000000000000..9df7a156771f --- /dev/null +++ b/src/main/java/com/t13g2/forum/storage/forum/UserStorage.java @@ -0,0 +1,10 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage.forum; + +import com.t13g2.forum.model.forum.User; + +/** + * Wraps list of entities and keep track of if it is modified + */ +public class UserStorage extends BaseEntityStorage { +} diff --git a/src/main/java/com/t13g2/forum/ui/AnnouncementPopUp.java b/src/main/java/com/t13g2/forum/ui/AnnouncementPopUp.java new file mode 100644 index 000000000000..5730e24184ac --- /dev/null +++ b/src/main/java/com/t13g2/forum/ui/AnnouncementPopUp.java @@ -0,0 +1,89 @@ +package com.t13g2.forum.ui; + +import java.util.logging.Logger; + +import com.t13g2.forum.commons.core.LogsCenter; + +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.text.Font; +import javafx.stage.Stage; + +/** + * Controller for a help page + */ +public class AnnouncementPopUp extends UiPart { + + private static final Logger logger = LogsCenter.getLogger(AnnouncementPopUp.class); + private static final String FXML = "AnnouncementPopUp.fxml"; + + /** + * Creates a new AnnouncementPopUp. + * + * @param root Stage to use as the root of the AnnouncementPopUp. + */ + public AnnouncementPopUp(Stage root) { + super(FXML, root); + } + + /** + * Creates a new AnnouncementPopUp. + */ + public AnnouncementPopUp() { + this(new Stage()); + } + + /** + * Shows the AnnouncementPopUp. + * @throws IllegalStateException + */ + public void show(String aTitle, String aContent) { + GridPane grid = new GridPane(); + grid.setAlignment(Pos.CENTER); + grid.setHgap(10); + grid.setVgap(10); + grid.setPadding(new Insets(25, 25, 25, 25)); + + Scene scene = new Scene(grid, 300, 200); + + Label lblContent = new Label(aContent); + lblContent.setWrapText(true); + lblContent.setFont(new Font("Arial", 20)); + grid.add(lblContent, 0, 0, 2, 1); + + Button btnClose = new Button(); + btnClose.setText("Close"); + + btnClose.setOnAction(event -> { + getRoot().close(); // return to main window + }); + HBox hbBtn = new HBox(10); + hbBtn.setAlignment(Pos.CENTER); + hbBtn.getChildren().add(btnClose); + grid.add(hbBtn, 1, 1, 2, 1); + + getRoot().setTitle(aTitle); + getRoot().setScene(scene); + logger.fine("Showing announcement pop up."); + getRoot().show(); + } + + /** + * Returns true if the announcement pop up is currently being shown. + */ + public boolean isShowing() { + return getRoot().isShowing(); + } + + /** + * Focuses on the announcement pop up. + */ + public void focus() { + getRoot().requestFocus(); + } +} diff --git a/src/main/java/seedu/address/ui/BrowserPanel.java b/src/main/java/com/t13g2/forum/ui/BrowserPanel.java similarity index 89% rename from src/main/java/seedu/address/ui/BrowserPanel.java rename to src/main/java/com/t13g2/forum/ui/BrowserPanel.java index b43de90a2b9f..fd9143d263be 100644 --- a/src/main/java/seedu/address/ui/BrowserPanel.java +++ b/src/main/java/com/t13g2/forum/ui/BrowserPanel.java @@ -1,19 +1,19 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import java.net.URL; import java.util.logging.Logger; import com.google.common.eventbus.Subscribe; +import com.t13g2.forum.MainApp; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.events.ui.PersonPanelSelectionChangedEvent; +import com.t13g2.forum.model.person.Person; import javafx.application.Platform; import javafx.event.Event; import javafx.fxml.FXML; import javafx.scene.layout.Region; 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.model.person.Person; /** * The Browser Panel of the App. diff --git a/src/main/java/seedu/address/ui/CommandBox.java b/src/main/java/com/t13g2/forum/ui/CommandBox.java similarity index 91% rename from src/main/java/seedu/address/ui/CommandBox.java rename to src/main/java/com/t13g2/forum/ui/CommandBox.java index 3d7aaded5640..2ea0c9a568d0 100644 --- a/src/main/java/seedu/address/ui/CommandBox.java +++ b/src/main/java/com/t13g2/forum/ui/CommandBox.java @@ -1,19 +1,20 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import java.util.logging.Logger; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.events.ui.NewResultAvailableEvent; +import com.t13g2.forum.logic.ListElementPointer; +import com.t13g2.forum.logic.Logic; +import com.t13g2.forum.logic.commands.CommandResult; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.parser.exceptions.ParseException; + import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.control.TextField; import javafx.scene.input.KeyEvent; import javafx.scene.layout.Region; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.ui.NewResultAvailableEvent; -import seedu.address.logic.ListElementPointer; -import seedu.address.logic.Logic; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.exceptions.ParseException; /** * The UI component that is responsible for receiving user command inputs. @@ -48,7 +49,6 @@ private void handleKeyPress(KeyEvent keyEvent) { // As up and down buttons will alter the position of the caret, // consuming it causes the caret's position to remain unchanged keyEvent.consume(); - navigateToPreviousInput(); break; case DOWN: diff --git a/src/main/java/com/t13g2/forum/ui/DisplayFormatter.java b/src/main/java/com/t13g2/forum/ui/DisplayFormatter.java new file mode 100644 index 000000000000..4ec4c12eccba --- /dev/null +++ b/src/main/java/com/t13g2/forum/ui/DisplayFormatter.java @@ -0,0 +1,58 @@ +package com.t13g2.forum.ui; + +import java.util.List; + +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; + +//@@author HansKoh +/** + * To format the message of a threadList and commentList + */ +public class DisplayFormatter { + + private static String message; + + /** + * return a string message of threadList to display + * @param threadList + * @return + */ + public static String diplayThreadList (List threadList) { + try (UnitOfWork unitOfWork = new UnitOfWork()) { + message = ""; + for (ForumThread thread : threadList) { + message += "(By " + + unitOfWork.getUserRepository().getUser(thread.getCreatedByUserId()).getUsername() + + ")\n" + + thread.getId() + ": " + thread.getTitle() + "\n" + + "----------------------------------------------------------------------------\n"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return message; + } + + /** + * return a string message of commentList to display + * @param commentList + * @return + */ + public static String displayCommentList (List commentList) { + try (UnitOfWork unitOfWork = new UnitOfWork()) { + message = ""; + for (Comment comment : commentList) { + message += "(By " + + unitOfWork.getUserRepository().getUser(comment.getCreatedByUserId()).getUsername() + + ")\n" + + comment.getId() + ": " + comment.getContent() + "\n" + + "----------------------------------------------------------------------------\n"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return message; + } +} diff --git a/src/main/java/seedu/address/ui/HelpWindow.java b/src/main/java/com/t13g2/forum/ui/HelpWindow.java similarity index 94% rename from src/main/java/seedu/address/ui/HelpWindow.java rename to src/main/java/com/t13g2/forum/ui/HelpWindow.java index 19de515ec8f0..4beb7f1c09c3 100644 --- a/src/main/java/seedu/address/ui/HelpWindow.java +++ b/src/main/java/com/t13g2/forum/ui/HelpWindow.java @@ -1,11 +1,12 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import java.util.logging.Logger; +import com.t13g2.forum.commons.core.LogsCenter; + import javafx.fxml.FXML; import javafx.scene.web.WebView; import javafx.stage.Stage; -import seedu.address.commons.core.LogsCenter; /** * Controller for a help page @@ -44,7 +45,7 @@ public HelpWindow() { * @throws IllegalStateException *
    *
  • - * if this method is called on a thread other than the JavaFX Application Thread. + * if this method is called on a thread other than the JavaFX Application ForumThread. *
  • *
  • * if this method is called during animation or layout processing. diff --git a/src/main/java/com/t13g2/forum/ui/LoginPopUp.java b/src/main/java/com/t13g2/forum/ui/LoginPopUp.java new file mode 100644 index 000000000000..23da8660510a --- /dev/null +++ b/src/main/java/com/t13g2/forum/ui/LoginPopUp.java @@ -0,0 +1,89 @@ +package com.t13g2.forum.ui; +import java.util.logging.Logger; + +import com.t13g2.forum.commons.core.LogsCenter; + +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.text.Font; +import javafx.stage.Stage; + + +/** + * Controller for a help page + */ +public class LoginPopUp extends UiPart { + + private static final Logger logger = LogsCenter.getLogger(LoginPopUp.class); + private static final String FXML = "LoginPopUp.fxml"; + + /** + * Creates a new AnnouncementPopUp. + * + * @param root Stage to use as the root of the AnnouncementPopUp. + */ + public LoginPopUp(Stage root) { + super(FXML, root); + } + + /** + * Creates a new AnnouncementPopUp. + */ + public LoginPopUp() { + this(new Stage()); + } + + /** + * Shows the AnnouncementPopUp. + * @throws IllegalStateException + */ + public void show(String aTitle, String aContent) { + GridPane grid = new GridPane(); + grid.setAlignment(Pos.CENTER); + grid.setHgap(10); + grid.setVgap(10); + grid.setPadding(new Insets(25, 25, 25, 25)); + + Scene scene = new Scene(grid, 300, 200); + + Label lblContent = new Label(aContent); + lblContent.setWrapText(true); + lblContent.setFont(new Font("Arial", 20)); + grid.add(lblContent, 0, 0, 2, 1); + + Button btnClose = new Button(); + btnClose.setText("Close"); + + btnClose.setOnAction(event -> { + getRoot().close(); // return to main window + }); + HBox hbBtn = new HBox(10); + hbBtn.setAlignment(Pos.CENTER); + hbBtn.getChildren().add(btnClose); + grid.add(hbBtn, 1, 1, 2, 1); + + getRoot().setTitle(aTitle); + getRoot().setScene(scene); + logger.fine("Showing Login pop up."); + getRoot().show(); + } + + /** + * Returns true if the announcement pop up is currently being shown. + */ + public boolean isShowing() { + return getRoot().isShowing(); + } + + /** + * Focuses on the announcement pop up. + */ + public void focus() { + getRoot().requestFocus(); + } +} diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/com/t13g2/forum/ui/MainWindow.java similarity index 66% rename from src/main/java/seedu/address/ui/MainWindow.java rename to src/main/java/com/t13g2/forum/ui/MainWindow.java index 0e361a4d7baf..6f6c2c426005 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/com/t13g2/forum/ui/MainWindow.java @@ -1,24 +1,27 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import java.util.logging.Logger; import com.google.common.eventbus.Subscribe; +import com.t13g2.forum.commons.core.Config; +import com.t13g2.forum.commons.core.GuiSettings; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.events.model.ShowAnnouncementEvent; +import com.t13g2.forum.commons.events.model.UserLoginEvent; +import com.t13g2.forum.commons.events.ui.ExitAppRequestEvent; +import com.t13g2.forum.commons.events.ui.ShowHelpRequestEvent; +import com.t13g2.forum.logic.Logic; +import com.t13g2.forum.model.UserPrefs; import javafx.event.ActionEvent; import javafx.fxml.FXML; +import javafx.scene.control.Label; import javafx.scene.control.MenuItem; import javafx.scene.control.TextInputControl; import javafx.scene.input.KeyCombination; import javafx.scene.input.KeyEvent; import javafx.scene.layout.StackPane; import javafx.stage.Stage; -import seedu.address.commons.core.Config; -import seedu.address.commons.core.GuiSettings; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.ui.ExitAppRequestEvent; -import seedu.address.commons.events.ui.ShowHelpRequestEvent; -import seedu.address.logic.Logic; -import seedu.address.model.UserPrefs; /** * The Main Window. Provides the basic application layout containing @@ -39,6 +42,8 @@ public class MainWindow extends UiPart { private Config config; private UserPrefs prefs; private HelpWindow helpWindow; + private AnnouncementPopUp announcementPopUp; + private LoginPopUp loginPopUp; @FXML private StackPane browserPlaceholder; @@ -58,6 +63,9 @@ public class MainWindow extends UiPart { @FXML private StackPane statusbarPlaceholder; + @FXML + private Label lblUserName; + public MainWindow(Stage primaryStage, Config config, UserPrefs prefs, Logic logic) { super(FXML, primaryStage); @@ -75,6 +83,8 @@ public MainWindow(Stage primaryStage, Config config, UserPrefs prefs, Logic logi registerAsAnEventHandler(this); helpWindow = new HelpWindow(); + announcementPopUp = new AnnouncementPopUp(); + loginPopUp = new LoginPopUp(); } public Stage getPrimaryStage() { @@ -87,6 +97,7 @@ private void setAccelerators() { /** * Sets the accelerator of a MenuItem. + * * @param keyCombination the KeyCombination value of the accelerator */ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) { @@ -128,7 +139,7 @@ void fillInnerParts() { ResultDisplay resultDisplay = new ResultDisplay(); resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot()); - StatusBarFooter statusBarFooter = new StatusBarFooter(prefs.getAddressBookFilePath()); + StatusBarFooter statusBarFooter = new StatusBarFooter(prefs.getForumBookFilePath()); statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot()); CommandBox commandBox = new CommandBox(logic); @@ -160,7 +171,7 @@ private void setWindowDefaultSize(UserPrefs prefs) { */ GuiSettings getCurrentGuiSetting() { return new GuiSettings(primaryStage.getWidth(), primaryStage.getHeight(), - (int) primaryStage.getX(), (int) primaryStage.getY()); + (int) primaryStage.getX(), (int) primaryStage.getY()); } /** @@ -175,6 +186,48 @@ public void handleHelp() { } } + //@@author xllx1 + /** + * show user name and user type in the label + */ + @FXML + public void handleUserLogin(String userName, boolean isAdmin, boolean isBlocked) { + String userType = "(" + (isAdmin ? "Admin" : "User") + ")" + (isBlocked ? ", Blocked" : ""); + lblUserName.setText(""); + if (userName.equals("")) { + lblUserName.setText("Welcome to Forum Book. Please login to proceed! "); + } else { + lblUserName.setText(userName + userType); + } + } + + /** + * shows announcement in a pop up window. + */ + @FXML + public void handleShowAnnouncement(String announcementTitle, String announcementContent) { + announcementPopUp = new AnnouncementPopUp(); + if (!announcementPopUp.isShowing()) { + announcementPopUp.show(announcementTitle, announcementContent); + } else { + announcementPopUp.focus(); + } + } + + /** + * allows login in a pop up window. + */ + @FXML + public void handleLogin(String announcementTitle, String announcementContent) { + loginPopUp = new LoginPopUp(); + if (!loginPopUp.isShowing()) { + loginPopUp.show(announcementTitle, announcementContent); + } else { + loginPopUp.focus(); + } + } + + //@@author void show() { primaryStage.show(); } @@ -200,4 +253,22 @@ private void handleShowHelpEvent(ShowHelpRequestEvent event) { logger.info(LogsCenter.getEventHandlingLogMessage(event)); handleHelp(); } + + //@@author xllx1 + @Subscribe + private void handleUserLoginEvent(UserLoginEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + handleUserLogin(event.userName, event.userType, event.isBlocked); + } + + @Subscribe + private void handleShowAnnouncementEvent(ShowAnnouncementEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + handleShowAnnouncement(event.announcementTitle, event.announcementContent); + } + @Subscribe + private void handleLoginEvent(ShowAnnouncementEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + handleLogin(event.announcementTitle, event.announcementContent); + } } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/com/t13g2/forum/ui/PersonCard.java similarity index 93% rename from src/main/java/seedu/address/ui/PersonCard.java rename to src/main/java/com/t13g2/forum/ui/PersonCard.java index f6727ea83abd..57e90353a86d 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/com/t13g2/forum/ui/PersonCard.java @@ -1,11 +1,12 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; + +import com.t13g2.forum.model.person.Person; import javafx.fxml.FXML; 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; /** * An UI component that displays information of a {@code Person}. @@ -19,7 +20,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 ForumBook level 4 */ public final Person person; diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/com/t13g2/forum/ui/PersonListPanel.java similarity index 90% rename from src/main/java/seedu/address/ui/PersonListPanel.java rename to src/main/java/com/t13g2/forum/ui/PersonListPanel.java index 80080adb4305..8aba77fc9a6e 100644 --- a/src/main/java/seedu/address/ui/PersonListPanel.java +++ b/src/main/java/com/t13g2/forum/ui/PersonListPanel.java @@ -1,8 +1,12 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import java.util.logging.Logger; import com.google.common.eventbus.Subscribe; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.events.ui.JumpToListRequestEvent; +import com.t13g2.forum.commons.events.ui.PersonPanelSelectionChangedEvent; +import com.t13g2.forum.model.person.Person; import javafx.application.Platform; import javafx.collections.ObservableList; @@ -10,10 +14,6 @@ import javafx.scene.control.ListCell; import javafx.scene.control.ListView; 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.model.person.Person; /** * Panel containing the list of persons. diff --git a/src/main/java/seedu/address/ui/ResultDisplay.java b/src/main/java/com/t13g2/forum/ui/ResultDisplay.java similarity index 88% rename from src/main/java/seedu/address/ui/ResultDisplay.java rename to src/main/java/com/t13g2/forum/ui/ResultDisplay.java index d05536bbee96..1550b259a48c 100644 --- a/src/main/java/seedu/address/ui/ResultDisplay.java +++ b/src/main/java/com/t13g2/forum/ui/ResultDisplay.java @@ -1,8 +1,10 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import java.util.logging.Logger; import com.google.common.eventbus.Subscribe; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.events.ui.NewResultAvailableEvent; import javafx.application.Platform; import javafx.beans.property.SimpleStringProperty; @@ -10,8 +12,6 @@ import javafx.fxml.FXML; import javafx.scene.control.TextArea; import javafx.scene.layout.Region; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.ui.NewResultAvailableEvent; /** * A ui for the status bar that is displayed at the header of the application. diff --git a/src/main/java/seedu/address/ui/StatusBarFooter.java b/src/main/java/com/t13g2/forum/ui/StatusBarFooter.java similarity index 93% rename from src/main/java/seedu/address/ui/StatusBarFooter.java rename to src/main/java/com/t13g2/forum/ui/StatusBarFooter.java index f6ba29502422..b9103c428a43 100644 --- a/src/main/java/seedu/address/ui/StatusBarFooter.java +++ b/src/main/java/com/t13g2/forum/ui/StatusBarFooter.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import java.nio.file.Path; import java.nio.file.Paths; @@ -9,12 +9,12 @@ import org.controlsfx.control.StatusBar; import com.google.common.eventbus.Subscribe; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.events.model.AddressBookChangedEvent; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.layout.Region; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.model.AddressBookChangedEvent; /** * A ui for the status bar that is displayed at the footer of the application. @@ -26,7 +26,7 @@ public class StatusBarFooter extends UiPart { /** * Used to generate time stamps. - * + *

    * TODO: change clock to an instance variable. * We leave it as a static variable because manual dependency injection * will require passing down the clock reference all the way from MainApp, diff --git a/src/main/java/seedu/address/ui/Ui.java b/src/main/java/com/t13g2/forum/ui/Ui.java similarity index 88% rename from src/main/java/seedu/address/ui/Ui.java rename to src/main/java/com/t13g2/forum/ui/Ui.java index e6a67fe8c027..8020e6cda8a5 100644 --- a/src/main/java/seedu/address/ui/Ui.java +++ b/src/main/java/com/t13g2/forum/ui/Ui.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import javafx.stage.Stage; diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/com/t13g2/forum/ui/UiManager.java similarity index 91% rename from src/main/java/seedu/address/ui/UiManager.java rename to src/main/java/com/t13g2/forum/ui/UiManager.java index 3fd3c17be156..effcd12cc80d 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/com/t13g2/forum/ui/UiManager.java @@ -1,22 +1,22 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import java.util.logging.Logger; import com.google.common.eventbus.Subscribe; +import com.t13g2.forum.MainApp; +import com.t13g2.forum.commons.core.ComponentManager; +import com.t13g2.forum.commons.core.Config; +import com.t13g2.forum.commons.core.LogsCenter; +import com.t13g2.forum.commons.events.storage.DataSavingExceptionEvent; +import com.t13g2.forum.commons.util.StringUtil; +import com.t13g2.forum.logic.Logic; +import com.t13g2.forum.model.UserPrefs; import javafx.application.Platform; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.image.Image; import javafx.stage.Stage; -import seedu.address.MainApp; -import seedu.address.commons.core.ComponentManager; -import seedu.address.commons.core.Config; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.storage.DataSavingExceptionEvent; -import seedu.address.commons.util.StringUtil; -import seedu.address.logic.Logic; -import seedu.address.model.UserPrefs; /** * The manager of the UI component. diff --git a/src/main/java/seedu/address/ui/UiPart.java b/src/main/java/com/t13g2/forum/ui/UiPart.java similarity index 89% rename from src/main/java/seedu/address/ui/UiPart.java rename to src/main/java/com/t13g2/forum/ui/UiPart.java index 5c237e57154b..7b60ddbd1e36 100644 --- a/src/main/java/seedu/address/ui/UiPart.java +++ b/src/main/java/com/t13g2/forum/ui/UiPart.java @@ -1,22 +1,24 @@ -package seedu.address.ui; +package com.t13g2.forum.ui; import static java.util.Objects.requireNonNull; import java.io.IOException; import java.net.URL; -import javafx.fxml.FXMLLoader; -import seedu.address.MainApp; -import seedu.address.commons.core.EventsCenter; -import seedu.address.commons.events.BaseEvent; +import com.t13g2.forum.MainApp; +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.BaseEvent; +import javafx.fxml.FXMLLoader; /** * Represents a distinct part of the UI. e.g. Windows, dialogs, panels, status bars, etc. * It contains a scene graph with a root node of type {@code T}. */ public abstract class UiPart { - /** Resource folder where FXML files are stored. */ + /** + * Resource folder where FXML files are stored. + */ public static final String FXML_FILE_FOLDER = "/view/"; private final FXMLLoader fxmlLoader = new FXMLLoader(); @@ -31,6 +33,7 @@ public UiPart(URL fxmlFileUrl) { /** * Constructs a UiPart using the specified FXML file within {@link #FXML_FILE_FOLDER}. + * * @see #UiPart(URL) */ public UiPart(String fxmlFileName) { @@ -47,6 +50,7 @@ public UiPart(URL fxmlFileUrl, T root) { /** * Constructs a UiPart with the specified FXML file within {@link #FXML_FILE_FOLDER} and root object. + * * @see #UiPart(URL, T) */ public UiPart(String fxmlFileName, T root) { @@ -62,6 +66,7 @@ public T getRoot() { /** * Raises the event via {@link EventsCenter#post(BaseEvent)} + * * @param event */ protected void raise(BaseEvent event) { @@ -70,6 +75,7 @@ protected void raise(BaseEvent event) { /** * Registers the object as an event handler at the {@link EventsCenter} + * * @param handler usually {@code this} */ protected void registerAsAnEventHandler(Object handler) { @@ -78,8 +84,9 @@ protected void registerAsAnEventHandler(Object handler) { /** * Loads the object hierarchy from a FXML document. + * * @param location Location of the FXML document. - * @param root Specifies the root of the object hierarchy. + * @param root Specifies the root of the object hierarchy. */ private void loadFxmlFile(URL location, T root) { requireNonNull(location); diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java deleted file mode 100644 index 1deb3a1e4695..000000000000 --- a/src/main/java/seedu/address/commons/core/Messages.java +++ /dev/null @@ -1,13 +0,0 @@ -package seedu.address.commons.core; - -/** - * Container for user visible messages. - */ -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!"; - -} diff --git a/src/main/java/seedu/address/commons/events/model/AddressBookChangedEvent.java b/src/main/java/seedu/address/commons/events/model/AddressBookChangedEvent.java deleted file mode 100644 index b72ad4740e5a..000000000000 --- a/src/main/java/seedu/address/commons/events/model/AddressBookChangedEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package seedu.address.commons.events.model; - -import seedu.address.commons.events.BaseEvent; -import seedu.address.model.ReadOnlyAddressBook; - -/** Indicates the AddressBook in the model has changed*/ -public class AddressBookChangedEvent extends BaseEvent { - - public final ReadOnlyAddressBook data; - - public AddressBookChangedEvent(ReadOnlyAddressBook data) { - this.data = data; - } - - @Override - public String toString() { - return "number of persons " + data.getPersonList().size(); - } -} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java deleted file mode 100644 index b7d57f5db86a..000000000000 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ /dev/null @@ -1,92 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.ClearCommand; -import seedu.address.logic.commands.Command; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.HelpCommand; -import seedu.address.logic.commands.HistoryCommand; -import seedu.address.logic.commands.ListCommand; -import seedu.address.logic.commands.RedoCommand; -import seedu.address.logic.commands.SelectCommand; -import seedu.address.logic.commands.UndoCommand; -import seedu.address.logic.parser.exceptions.ParseException; - -/** - * Parses user input. - */ -public class AddressBookParser { - - /** - * Used for initial separation of command word and args. - */ - private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)"); - - /** - * Parses user input into command for execution. - * - * @param userInput full user input string - * @return the command based on the user input - * @throws ParseException if the user input does not conform the expected format - */ - public Command parseCommand(String userInput) throws ParseException { - final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim()); - if (!matcher.matches()) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); - } - - final String commandWord = matcher.group("commandWord"); - final String arguments = matcher.group("arguments"); - switch (commandWord) { - - case AddCommand.COMMAND_WORD: - return new AddCommandParser().parse(arguments); - - case EditCommand.COMMAND_WORD: - return new EditCommandParser().parse(arguments); - - case SelectCommand.COMMAND_WORD: - return new SelectCommandParser().parse(arguments); - - case DeleteCommand.COMMAND_WORD: - return new DeleteCommandParser().parse(arguments); - - case ClearCommand.COMMAND_WORD: - return new ClearCommand(); - - case FindCommand.COMMAND_WORD: - return new FindCommandParser().parse(arguments); - - case ListCommand.COMMAND_WORD: - return new ListCommand(); - - case HistoryCommand.COMMAND_WORD: - return new HistoryCommand(); - - case ExitCommand.COMMAND_WORD: - return new ExitCommand(); - - case HelpCommand.COMMAND_WORD: - return new HelpCommand(); - - case UndoCommand.COMMAND_WORD: - return new UndoCommand(); - - case RedoCommand.COMMAND_WORD: - return new RedoCommand(); - - default: - throw new ParseException(MESSAGE_UNKNOWN_COMMAND); - } - } - -} diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java deleted file mode 100644 index 75b1a9bf1190..000000000000 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ /dev/null @@ -1,15 +0,0 @@ -package seedu.address.logic.parser; - -/** - * Contains Command Line Interface (CLI) syntax definitions common to multiple commands - */ -public class CliSyntax { - - /* Prefix definitions */ - public static final Prefix PREFIX_NAME = new Prefix("n/"); - public static final Prefix PREFIX_PHONE = new Prefix("p/"); - public static final Prefix PREFIX_EMAIL = new Prefix("e/"); - public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); - public static final Prefix PREFIX_TAG = new Prefix("t/"); - -} diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java deleted file mode 100644 index 76daf40807e2..000000000000 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ /dev/null @@ -1,124 +0,0 @@ -package seedu.address.logic.parser; - -import static java.util.Objects.requireNonNull; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -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.tag.Tag; - -/** - * Contains utility methods used for parsing strings in the various *Parser classes. - */ -public class ParserUtil { - - public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer."; - - /** - * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be - * trimmed. - * @throws ParseException if the specified index is invalid (not non-zero unsigned integer). - */ - public static Index parseIndex(String oneBasedIndex) throws ParseException { - String trimmedIndex = oneBasedIndex.trim(); - if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) { - throw new ParseException(MESSAGE_INVALID_INDEX); - } - return Index.fromOneBased(Integer.parseInt(trimmedIndex)); - } - - /** - * Parses a {@code String name} into a {@code Name}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code name} is invalid. - */ - public static Name parseName(String name) throws ParseException { - requireNonNull(name); - String trimmedName = name.trim(); - if (!Name.isValidName(trimmedName)) { - throw new ParseException(Name.MESSAGE_NAME_CONSTRAINTS); - } - return new Name(trimmedName); - } - - /** - * Parses a {@code String phone} into a {@code Phone}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code phone} is invalid. - */ - public static Phone parsePhone(String phone) throws ParseException { - requireNonNull(phone); - String trimmedPhone = phone.trim(); - if (!Phone.isValidPhone(trimmedPhone)) { - throw new ParseException(Phone.MESSAGE_PHONE_CONSTRAINTS); - } - return new Phone(trimmedPhone); - } - - /** - * Parses a {@code String address} into an {@code Address}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code address} is invalid. - */ - public static Address parseAddress(String address) throws ParseException { - requireNonNull(address); - String trimmedAddress = address.trim(); - if (!Address.isValidAddress(trimmedAddress)) { - throw new ParseException(Address.MESSAGE_ADDRESS_CONSTRAINTS); - } - return new Address(trimmedAddress); - } - - /** - * Parses a {@code String email} into an {@code Email}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code email} is invalid. - */ - public static Email parseEmail(String email) throws ParseException { - requireNonNull(email); - String trimmedEmail = email.trim(); - if (!Email.isValidEmail(trimmedEmail)) { - throw new ParseException(Email.MESSAGE_EMAIL_CONSTRAINTS); - } - return new Email(trimmedEmail); - } - - /** - * Parses a {@code String tag} into a {@code Tag}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code tag} is invalid. - */ - public static Tag parseTag(String tag) throws ParseException { - requireNonNull(tag); - String trimmedTag = tag.trim(); - if (!Tag.isValidTagName(trimmedTag)) { - throw new ParseException(Tag.MESSAGE_TAG_CONSTRAINTS); - } - return new Tag(trimmedTag); - } - - /** - * Parses {@code Collection tags} into a {@code Set}. - */ - public static Set parseTags(Collection tags) throws ParseException { - requireNonNull(tags); - final Set tagSet = new HashSet<>(); - for (String tagName : tags) { - tagSet.add(parseTag(tagName)); - } - return tagSet; - } -} diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java deleted file mode 100644 index 4599182b3f92..000000000000 --- a/src/main/java/seedu/address/storage/AddressBookStorage.java +++ /dev/null @@ -1,45 +0,0 @@ -package seedu.address.storage; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; - -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; - -/** - * Represents a storage for {@link seedu.address.model.AddressBook}. - */ -public interface AddressBookStorage { - - /** - * Returns the file path of the data file. - */ - Path getAddressBookFilePath(); - - /** - * Returns AddressBook data as a {@link ReadOnlyAddressBook}. - * Returns {@code Optional.empty()} if storage file is not found. - * @throws DataConversionException if the data in storage is not in the expected format. - * @throws IOException if there was any problem when reading from the storage. - */ - Optional readAddressBook() throws DataConversionException, IOException; - - /** - * @see #getAddressBookFilePath() - */ - Optional readAddressBook(Path filePath) throws DataConversionException, IOException; - - /** - * Saves the given {@link ReadOnlyAddressBook} to the storage. - * @param addressBook cannot be null. - * @throws IOException if there was any problem writing to the file. - */ - void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; - - /** - * @see #saveAddressBook(ReadOnlyAddressBook) - */ - void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException; - -} diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java deleted file mode 100644 index b0df908a76a7..000000000000 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ /dev/null @@ -1,93 +0,0 @@ -package seedu.address.storage; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; -import java.util.logging.Logger; - -import com.google.common.eventbus.Subscribe; - -import seedu.address.commons.core.ComponentManager; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.model.AddressBookChangedEvent; -import seedu.address.commons.events.storage.DataSavingExceptionEvent; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.UserPrefs; - -/** - * Manages storage of AddressBook data in local storage. - */ -public class StorageManager extends ComponentManager implements Storage { - - private static final Logger logger = LogsCenter.getLogger(StorageManager.class); - private AddressBookStorage addressBookStorage; - private UserPrefsStorage userPrefsStorage; - - - public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) { - super(); - this.addressBookStorage = addressBookStorage; - this.userPrefsStorage = userPrefsStorage; - } - - // ================ UserPrefs methods ============================== - - @Override - public Path getUserPrefsFilePath() { - return userPrefsStorage.getUserPrefsFilePath(); - } - - @Override - public Optional readUserPrefs() throws DataConversionException, IOException { - return userPrefsStorage.readUserPrefs(); - } - - @Override - public void saveUserPrefs(UserPrefs userPrefs) throws IOException { - userPrefsStorage.saveUserPrefs(userPrefs); - } - - - // ================ AddressBook methods ============================== - - @Override - public Path getAddressBookFilePath() { - return addressBookStorage.getAddressBookFilePath(); - } - - @Override - public Optional readAddressBook() throws DataConversionException, IOException { - return readAddressBook(addressBookStorage.getAddressBookFilePath()); - } - - @Override - public Optional readAddressBook(Path filePath) throws DataConversionException, IOException { - logger.fine("Attempting to read data from file: " + filePath); - return addressBookStorage.readAddressBook(filePath); - } - - @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException { - saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath()); - } - - @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException { - logger.fine("Attempting to write to data file: " + filePath); - addressBookStorage.saveAddressBook(addressBook, filePath); - } - - - @Override - @Subscribe - public void handleAddressBookChangedEvent(AddressBookChangedEvent event) { - logger.info(LogsCenter.getEventHandlingLogMessage(event, "Local data changed, saving to file")); - try { - saveAddressBook(event.data); - } catch (IOException e) { - raise(new DataSavingExceptionEvent(e)); - } - } - -} diff --git a/src/main/resources/view/AnnouncementPopUp.fxml b/src/main/resources/view/AnnouncementPopUp.fxml new file mode 100644 index 000000000000..39986fdfad19 --- /dev/null +++ b/src/main/resources/view/AnnouncementPopUp.fxml @@ -0,0 +1,7 @@ + + + + + diff --git a/src/main/resources/view/LoginPopUp.fxml b/src/main/resources/view/LoginPopUp.fxml new file mode 100644 index 000000000000..39986fdfad19 --- /dev/null +++ b/src/main/resources/view/LoginPopUp.fxml @@ -0,0 +1,7 @@ + + + + + diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index daf386d8f5b8..dbb0fa0c29e1 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -11,6 +11,10 @@ + + + + @@ -24,14 +28,19 @@ - -

    - - - - - - + + + + + + + + + + + @@ -40,13 +49,13 @@ + minHeight="750" prefHeight="800" maxHeight="800"> - + diff --git a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json index 412dbd7cac65..5dcb50d31b4f 100644 --- a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json +++ b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json @@ -7,5 +7,5 @@ "y" : 100 } }, - "addressBookFilePath" : "addressbook.xml" + "addressBookFilePath" : "data/addressbook.xml" } diff --git a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml b/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml index d812b05e32bb..0d84fd8aa31c 100644 --- a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml +++ b/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml @@ -1,5 +1,5 @@ - + Alice Pauline diff --git a/src/test/java/seedu/address/AppParametersTest.java b/src/test/java/com/t13g2/forum/AppParametersTest.java similarity index 98% rename from src/test/java/seedu/address/AppParametersTest.java rename to src/test/java/com/t13g2/forum/AppParametersTest.java index e6ef73d83b50..03e67165ac2c 100644 --- a/src/test/java/seedu/address/AppParametersTest.java +++ b/src/test/java/com/t13g2/forum/AppParametersTest.java @@ -1,4 +1,4 @@ -package seedu.address; +package com.t13g2.forum; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/seedu/address/TestApp.java b/src/test/java/com/t13g2/forum/TestApp.java similarity index 71% rename from src/test/java/seedu/address/TestApp.java rename to src/test/java/com/t13g2/forum/TestApp.java index 74fe55a2e430..5321ce222d1b 100644 --- a/src/test/java/seedu/address/TestApp.java +++ b/src/test/java/com/t13g2/forum/TestApp.java @@ -1,24 +1,26 @@ -package seedu.address; +package com.t13g2.forum; import java.io.IOException; import java.nio.file.Path; import java.util.function.Supplier; +import com.t13g2.forum.commons.core.Config; +import com.t13g2.forum.commons.core.GuiSettings; +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.commons.util.FileUtil; +import com.t13g2.forum.commons.util.XmlUtil; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.ReadOnlyForumBook; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.storage.UserPrefsStorage; +import com.t13g2.forum.storage.XmlSerializableAddressBook; +import com.t13g2.forum.testutil.TestUtil; + import javafx.stage.Screen; import javafx.stage.Stage; -import seedu.address.commons.core.Config; -import seedu.address.commons.core.GuiSettings; -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.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.UserPrefs; -import seedu.address.storage.UserPrefsStorage; -import seedu.address.storage.XmlSerializableAddressBook; -import seedu.address.testutil.TestUtil; + import systemtests.ModelHelper; /** @@ -32,13 +34,13 @@ public class TestApp extends MainApp { protected static final Path DEFAULT_PREF_FILE_LOCATION_FOR_TESTING = TestUtil.getFilePathInSandboxFolder("pref_testing.json"); - protected Supplier initialDataSupplier = () -> null; + protected Supplier initialDataSupplier = () -> null; protected Path saveFileLocation = SAVE_LOCATION_FOR_TESTING; public TestApp() { } - public TestApp(Supplier initialDataSupplier, Path saveFileLocation) { + public TestApp(Supplier initialDataSupplier, Path saveFileLocation) { super(); this.initialDataSupplier = initialDataSupplier; this.saveFileLocation = saveFileLocation; @@ -64,18 +66,18 @@ 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.setForumBookFilePath(saveFileLocation); return userPrefs; } /** * Returns a defensive copy of the address book data stored inside the storage file. */ - public AddressBook readStorageAddressBook() { + public ForumBook readStorageAddressBook() { try { - return new AddressBook(storage.readAddressBook().get()); + return new ForumBook(storage.readForumBook().get()); } catch (DataConversionException dce) { - throw new AssertionError("Data is not in the AddressBook format.", dce); + throw new AssertionError("Data is not in the ForumBook format.", dce); } catch (IOException ioe) { throw new AssertionError("Storage file cannot be found.", ioe); } @@ -85,14 +87,14 @@ public AddressBook readStorageAddressBook() { * Returns the file path of the storage file. */ public Path getStorageSaveLocation() { - return storage.getAddressBookFilePath(); + return storage.getForumBookFilePath(); } /** * Returns a defensive copy of the model. */ public Model getModel() { - Model copy = new ModelManager((model.getAddressBook()), new UserPrefs()); + Model copy = new ModelManager((model.getForumBook()), new UserPrefs()); ModelHelper.setFilteredList(copy, model.getFilteredPersonList()); return copy; } diff --git a/src/test/java/seedu/address/commons/core/ConfigTest.java b/src/test/java/com/t13g2/forum/commons/core/ConfigTest.java similarity index 88% rename from src/test/java/seedu/address/commons/core/ConfigTest.java rename to src/test/java/com/t13g2/forum/commons/core/ConfigTest.java index cc4bf567cb44..f9403bdcc972 100644 --- a/src/test/java/seedu/address/commons/core/ConfigTest.java +++ b/src/test/java/com/t13g2/forum/commons/core/ConfigTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package com.t13g2.forum.commons.core; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -14,7 +14,7 @@ public class ConfigTest { @Test public void toString_defaultObject_stringReturned() { - String defaultConfigAsString = "App title : Address App\n" + String defaultConfigAsString = "App title : Forum Book\n" + "Current log level : INFO\n" + "Preference file Location : preferences.json"; diff --git a/src/test/java/seedu/address/commons/core/VersionTest.java b/src/test/java/com/t13g2/forum/commons/core/VersionTest.java similarity index 99% rename from src/test/java/seedu/address/commons/core/VersionTest.java rename to src/test/java/com/t13g2/forum/commons/core/VersionTest.java index c3014d633d27..0d580a8257e8 100644 --- a/src/test/java/seedu/address/commons/core/VersionTest.java +++ b/src/test/java/com/t13g2/forum/commons/core/VersionTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package com.t13g2.forum.commons.core; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/seedu/address/commons/core/index/IndexTest.java b/src/test/java/com/t13g2/forum/commons/core/index/IndexTest.java similarity index 98% rename from src/test/java/seedu/address/commons/core/index/IndexTest.java rename to src/test/java/com/t13g2/forum/commons/core/index/IndexTest.java index 2364e0afbd68..8fd360e6741d 100644 --- a/src/test/java/seedu/address/commons/core/index/IndexTest.java +++ b/src/test/java/com/t13g2/forum/commons/core/index/IndexTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core.index; +package com.t13g2.forum.commons.core.index; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/src/test/java/seedu/address/commons/util/AppUtilTest.java b/src/test/java/com/t13g2/forum/commons/util/AppUtilTest.java similarity index 96% rename from src/test/java/seedu/address/commons/util/AppUtilTest.java rename to src/test/java/com/t13g2/forum/commons/util/AppUtilTest.java index 8a6fe5fcb7d6..f8c29108efe1 100644 --- a/src/test/java/seedu/address/commons/util/AppUtilTest.java +++ b/src/test/java/com/t13g2/forum/commons/util/AppUtilTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static org.junit.Assert.assertNotNull; diff --git a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java b/src/test/java/com/t13g2/forum/commons/util/CollectionUtilTest.java similarity index 97% rename from src/test/java/seedu/address/commons/util/CollectionUtilTest.java rename to src/test/java/com/t13g2/forum/commons/util/CollectionUtilTest.java index 7739103f4f80..bcc605d3465b 100644 --- a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java +++ b/src/test/java/com/t13g2/forum/commons/util/CollectionUtilTest.java @@ -1,8 +1,8 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; +import static com.t13g2.forum.commons.util.CollectionUtil.requireAllNonNull; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.util.Arrays; import java.util.Collection; diff --git a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java b/src/test/java/com/t13g2/forum/commons/util/ConfigUtilTest.java similarity index 96% rename from src/test/java/seedu/address/commons/util/ConfigUtilTest.java rename to src/test/java/com/t13g2/forum/commons/util/ConfigUtilTest.java index 2014aa3a8eda..27ebff7c63d9 100644 --- a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java +++ b/src/test/java/com/t13g2/forum/commons/util/ConfigUtilTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -14,8 +14,8 @@ import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; -import seedu.address.commons.core.Config; -import seedu.address.commons.exceptions.DataConversionException; +import com.t13g2.forum.commons.core.Config; +import com.t13g2.forum.commons.exceptions.DataConversionException; public class ConfigUtilTest { diff --git a/src/test/java/seedu/address/commons/util/FileUtilTest.java b/src/test/java/com/t13g2/forum/commons/util/FileUtilTest.java similarity index 86% rename from src/test/java/seedu/address/commons/util/FileUtilTest.java rename to src/test/java/com/t13g2/forum/commons/util/FileUtilTest.java index 4b30ea91ffcb..d02005b1a4d2 100644 --- a/src/test/java/seedu/address/commons/util/FileUtilTest.java +++ b/src/test/java/com/t13g2/forum/commons/util/FileUtilTest.java @@ -1,11 +1,11 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; -import seedu.address.testutil.Assert; +import com.t13g2.forum.testutil.Assert; public class FileUtilTest { diff --git a/src/test/java/seedu/address/commons/util/JsonUtilTest.java b/src/test/java/com/t13g2/forum/commons/util/JsonUtilTest.java similarity index 92% rename from src/test/java/seedu/address/commons/util/JsonUtilTest.java rename to src/test/java/com/t13g2/forum/commons/util/JsonUtilTest.java index 847b40ad181a..078d02d5cb9a 100644 --- a/src/test/java/seedu/address/commons/util/JsonUtilTest.java +++ b/src/test/java/com/t13g2/forum/commons/util/JsonUtilTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static org.junit.Assert.assertEquals; @@ -7,8 +7,8 @@ import org.junit.Test; -import seedu.address.testutil.SerializableTestClass; -import seedu.address.testutil.TestUtil; +import com.t13g2.forum.testutil.SerializableTestClass; +import com.t13g2.forum.testutil.TestUtil; /** * Tests JSON Read and Write diff --git a/src/test/java/seedu/address/commons/util/StringUtilTest.java b/src/test/java/com/t13g2/forum/commons/util/StringUtilTest.java similarity index 99% rename from src/test/java/seedu/address/commons/util/StringUtilTest.java rename to src/test/java/com/t13g2/forum/commons/util/StringUtilTest.java index 168bdb93c0d3..e8a1c1d2d3db 100644 --- a/src/test/java/seedu/address/commons/util/StringUtilTest.java +++ b/src/test/java/com/t13g2/forum/commons/util/StringUtilTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/src/test/java/seedu/address/commons/util/XmlUtilTest.java b/src/test/java/com/t13g2/forum/commons/util/XmlUtilTest.java similarity index 86% rename from src/test/java/seedu/address/commons/util/XmlUtilTest.java rename to src/test/java/com/t13g2/forum/commons/util/XmlUtilTest.java index f409f974a233..02299ff092b1 100644 --- a/src/test/java/seedu/address/commons/util/XmlUtilTest.java +++ b/src/test/java/com/t13g2/forum/commons/util/XmlUtilTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package com.t13g2.forum.commons.util; import static org.junit.Assert.assertEquals; @@ -7,7 +7,6 @@ import java.nio.file.Paths; import java.util.Collections; import java.util.List; - import javax.xml.bind.JAXBException; import javax.xml.bind.annotation.XmlRootElement; @@ -15,13 +14,13 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -import seedu.address.model.AddressBook; -import seedu.address.storage.XmlAdaptedPerson; -import seedu.address.storage.XmlAdaptedTag; -import seedu.address.storage.XmlSerializableAddressBook; -import seedu.address.testutil.AddressBookBuilder; -import seedu.address.testutil.PersonBuilder; -import seedu.address.testutil.TestUtil; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.storage.XmlAdaptedPerson; +import com.t13g2.forum.storage.XmlAdaptedTag; +import com.t13g2.forum.storage.XmlSerializableAddressBook; +import com.t13g2.forum.testutil.AddressBookBuilder; +import com.t13g2.forum.testutil.PersonBuilder; +import com.t13g2.forum.testutil.TestUtil; public class XmlUtilTest { @@ -48,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, ForumBook.class); } @Test @@ -60,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, ForumBook.class); } @Test public void getDataFromFile_emptyFile_dataFormatMismatchException() throws Exception { thrown.expect(JAXBException.class); - XmlUtil.getDataFromFile(EMPTY_FILE, AddressBook.class); + XmlUtil.getDataFromFile(EMPTY_FILE, ForumBook.class); } @Test public void getDataFromFile_validFile_validResult() throws Exception { - AddressBook dataFromFile = XmlUtil.getDataFromFile(VALID_FILE, XmlSerializableAddressBook.class).toModelType(); + ForumBook dataFromFile = XmlUtil.getDataFromFile(VALID_FILE, XmlSerializableAddressBook.class).toModelType(); assertEquals(9, dataFromFile.getPersonList().size()); } @@ -105,7 +104,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 ForumBook()); } @Test @@ -117,18 +116,18 @@ 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 ForumBook()); } @Test public void saveDataToFile_validFile_dataSaved() throws Exception { FileUtil.createFile(TEMP_FILE); - XmlSerializableAddressBook dataToWrite = new XmlSerializableAddressBook(new AddressBook()); + XmlSerializableAddressBook dataToWrite = new XmlSerializableAddressBook(new ForumBook()); XmlUtil.saveDataToFile(TEMP_FILE, dataToWrite); XmlSerializableAddressBook dataFromFile = XmlUtil.getDataFromFile(TEMP_FILE, XmlSerializableAddressBook.class); assertEquals(dataToWrite, dataFromFile); - AddressBookBuilder builder = new AddressBookBuilder(new AddressBook()); + AddressBookBuilder builder = new AddressBookBuilder(new ForumBook()); dataToWrite = new XmlSerializableAddressBook( builder.withPerson(new PersonBuilder().build()).build()); diff --git a/src/test/java/seedu/address/logic/CommandHistoryTest.java b/src/test/java/com/t13g2/forum/logic/CommandHistoryTest.java similarity index 98% rename from src/test/java/seedu/address/logic/CommandHistoryTest.java rename to src/test/java/com/t13g2/forum/logic/CommandHistoryTest.java index 2cf127e42588..29fc76fbbd0f 100644 --- a/src/test/java/seedu/address/logic/CommandHistoryTest.java +++ b/src/test/java/com/t13g2/forum/logic/CommandHistoryTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic; +package com.t13g2.forum.logic; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/src/test/java/seedu/address/logic/ListElementPointerTest.java b/src/test/java/com/t13g2/forum/logic/ListElementPointerTest.java similarity index 99% rename from src/test/java/seedu/address/logic/ListElementPointerTest.java rename to src/test/java/com/t13g2/forum/logic/ListElementPointerTest.java index 21ac5872f3c2..71dcd115f330 100644 --- a/src/test/java/seedu/address/logic/ListElementPointerTest.java +++ b/src/test/java/com/t13g2/forum/logic/ListElementPointerTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic; +package com.t13g2.forum.logic; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/com/t13g2/forum/logic/LogicManagerTest.java similarity index 73% rename from src/test/java/seedu/address/logic/LogicManagerTest.java rename to src/test/java/com/t13g2/forum/logic/LogicManagerTest.java index 954c1fb04388..2943bfafffef 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/com/t13g2/forum/logic/LogicManagerTest.java @@ -1,21 +1,24 @@ -package seedu.address.logic; +package com.t13g2.forum.logic; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; import static org.junit.Assert.assertEquals; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; -import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.HistoryCommand; -import seedu.address.logic.commands.ListCommand; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; +import com.t13g2.forum.logic.commands.CommandResult; +import com.t13g2.forum.logic.commands.DeleteUserCommand; +import com.t13g2.forum.logic.commands.HistoryCommand; +import com.t13g2.forum.logic.commands.LogoutCommand; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.UserBuilder; public class LogicManagerTest { @@ -34,16 +37,24 @@ public void execute_invalidCommandFormat_throwsParseException() { @Test public void execute_commandExecutionError_throwsCommandException() { - String deleteCommand = "delete 9"; - assertCommandException(deleteCommand, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - assertHistoryCorrect(deleteCommand); + //set the current logged in user as an admin. + User loginUser = new UserBuilder().build(); + Context.getInstance().setCurrentUser(loginUser); + + String deleteUserCommand = "deleteUser uName/jane"; + assertCommandException(deleteUserCommand, String.format(DeleteUserCommand.MESSAGE_INVALID_USER, "jane")); + assertHistoryCorrect(deleteUserCommand); } @Test public void execute_validCommand_success() { - String listCommand = ListCommand.COMMAND_WORD; - assertCommandSuccess(listCommand, ListCommand.MESSAGE_SUCCESS, model); - assertHistoryCorrect(listCommand); + //set the current logged in user as an admin. + User loginUser = new UserBuilder().build(); + Context.getInstance().setCurrentUser(loginUser); + + String logoutCommand = LogoutCommand.COMMAND_WORD; + assertCommandSuccess(logoutCommand, String.format(LogoutCommand.MESSAGE_SUCCESS, "testAdmin"), model); + assertHistoryCorrect(logoutCommand); } @Test @@ -82,7 +93,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.getForumBook(), new UserPrefs()); assertCommandBehavior(expectedException, inputCommand, expectedMessage, expectedModel); } diff --git a/src/test/java/com/t13g2/forum/logic/commands/AddCommandIntegrationTest.java b/src/test/java/com/t13g2/forum/logic/commands/AddCommandIntegrationTest.java new file mode 100644 index 000000000000..81c584a66423 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/AddCommandIntegrationTest.java @@ -0,0 +1,46 @@ +package com.t13g2.forum.logic.commands; + +import org.junit.Before; +import org.junit.Test; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.testutil.PersonBuilder; +import com.t13g2.forum.testutil.TypicalPersons; + +/** + * Contains integration tests (interaction with the Model) for {@code AddCommand}. + */ +public class AddCommandIntegrationTest { + + private Model model; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + } + + @Test + public void execute_newPerson_success() { + Person validPerson = new PersonBuilder().build(); + + Model expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + expectedModel.addPerson(validPerson); + expectedModel.commitForumBook(); + + CommandTestUtil.assertCommandSuccess(new AddCommand(validPerson), model, commandHistory, + String.format(AddCommand.MESSAGE_SUCCESS, validPerson), expectedModel); + } + + @Test + public void execute_duplicatePerson_throwsCommandException() { + Person personInList = model.getForumBook().getPersonList().get(0); + CommandTestUtil.assertCommandFailure(new AddCommand(personInList), model, commandHistory, + AddCommand.MESSAGE_DUPLICATE_PERSON); + } + +} diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/AddCommandTest.java similarity index 87% rename from src/test/java/seedu/address/logic/commands/AddCommandTest.java rename to src/test/java/com/t13g2/forum/logic/commands/AddCommandTest.java index c7077829f434..c7bb7a4817c0 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/com/t13g2/forum/logic/commands/AddCommandTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; import static java.util.Objects.requireNonNull; import static org.junit.Assert.assertEquals; @@ -13,14 +13,15 @@ import org.junit.Test; import org.junit.rules.ExpectedException; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ReadOnlyForumBook; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.testutil.PersonBuilder; + import javafx.collections.ObservableList; -import seedu.address.logic.CommandHistory; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; -import seedu.address.testutil.PersonBuilder; public class AddCommandTest { @@ -94,12 +95,12 @@ public void addPerson(Person person) { } @Override - public void resetData(ReadOnlyAddressBook newData) { + public void resetData(ReadOnlyForumBook newData) { throw new AssertionError("This method should not be called."); } @Override - public ReadOnlyAddressBook getAddressBook() { + public ReadOnlyForumBook getForumBook() { throw new AssertionError("This method should not be called."); } @@ -129,27 +130,27 @@ public void updateFilteredPersonList(Predicate predicate) { } @Override - public boolean canUndoAddressBook() { + public boolean canUndoForumBook() { throw new AssertionError("This method should not be called."); } @Override - public boolean canRedoAddressBook() { + public boolean canRedoForumBook() { throw new AssertionError("This method should not be called."); } @Override - public void undoAddressBook() { + public void undoForumBook() { throw new AssertionError("This method should not be called."); } @Override - public void redoAddressBook() { + public void redoForumBook() { throw new AssertionError("This method should not be called."); } @Override - public void commitAddressBook() { + public void commitForumBook() { throw new AssertionError("This method should not be called."); } } @@ -191,14 +192,13 @@ public void addPerson(Person person) { } @Override - public void commitAddressBook() { + public void commitForumBook() { // called by {@code AddCommand#execute()} } @Override - public ReadOnlyAddressBook getAddressBook() { - return new AddressBook(); + public ReadOnlyForumBook getForumBook() { + return new ForumBook(); } } - } diff --git a/src/test/java/com/t13g2/forum/logic/commands/AddUserCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/AddUserCommandTest.java new file mode 100644 index 000000000000..06b61d95feef --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/AddUserCommandTest.java @@ -0,0 +1,96 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class AddUserCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullModuleCode_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new LoginCommand(null, null); + } + + @Test + public void execute_validUserNameAndValidUserPassword_loginSuccess() { + Context.getInstance().setCurrentUser(null); + User validUser = TypicalUsers.JOSH; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getUserRepository().addUser(validUser); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + LoginCommand loginCommand = + new LoginCommand(validUser.getUsername(), validUser.getPassword()); + + CommandTestUtil.assertCommandSuccess(loginCommand, model, commandHistory, + String.format(String.format(LoginCommand.MESSAGE_SUCCESS, validUser.getUsername()), validUser.getUsername(), + validUser.getPassword()), expectedModel); + } + + @Test + public void execute_invalidUserNameAndValidUserPassword_loginFailed() throws Exception { + + String invalidUserName = "abcde"; + LoginCommand loginCommand = new LoginCommand(invalidUserName, "000"); + + //thrown.expect(CommandException.class); + thrown.expectMessage(String.format(LoginCommand.MESSAGE_FAIL, invalidUserName)); + + CommandResult commandResult = loginCommand.execute(model, commandHistory); + assertEquals(String.format(LoginCommand.MESSAGE_FAIL, + invalidUserName), commandResult.feedbackToUser); + } + + + @Test + public void execute_userLoginWithNullUserName_loginFailed() { + //set the current logged in user as a user. + + User validUser = TypicalUsers.JOSH; + thrown.expect(NullPointerException.class); + LoginCommand loginCommand = + new LoginCommand(null, validUser.getPassword()); + } + + @Test + public void execute_userLoginWithNullUserPassword_loginFailed() { + //set the current logged in user as a user. + + User validUser = TypicalUsers.JOSH; + thrown.expect(NullPointerException.class); + LoginCommand loginCommand = + new LoginCommand(validUser.getUsername(), null); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/AdminUpdatePasswordCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/AdminUpdatePasswordCommandTest.java new file mode 100644 index 000000000000..8537b966df3c --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/AdminUpdatePasswordCommandTest.java @@ -0,0 +1,115 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; +import com.t13g2.forum.testutil.UserBuilder; + +//@@author xllx1 +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class AdminUpdatePasswordCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullModuleCode_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new AdminUpdatePasswordCommand(null, null); + } + + @Test + public void execute_adminLoggedInAndValidUserName_updateSuccess() { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + User validUser = TypicalUsers.JOSH; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getUserRepository().addUser(validUser); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + AdminUpdatePasswordCommand adminUpdatePasswordCommand = + new AdminUpdatePasswordCommand(validUser.getUsername(), "000"); + + CommandTestUtil.assertCommandSuccess(adminUpdatePasswordCommand, model, commandHistory, + String.format(AdminUpdatePasswordCommand.MESSAGE_SUCCESS, validUser.getUsername(), + "000"), expectedModel); + } + + @Test + public void execute_adminLoggedInInvalidUserName_updateFailed() throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + String invalidUserName = "abcde"; + AdminUpdatePasswordCommand adminUpdatePasswordCommand = new AdminUpdatePasswordCommand(invalidUserName, "000"); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(AdminUpdatePasswordCommand.MESSAGE_INVALID_USER, invalidUserName)); + + CommandResult commandResult = adminUpdatePasswordCommand.execute(model, commandHistory); + assertEquals(String.format(AdminUpdatePasswordCommand.MESSAGE_INVALID_USER, + invalidUserName), commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedIn_updateFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + User validUser = TypicalUsers.JOSH; + AdminUpdatePasswordCommand adminUpdatePasswordCommand = + new AdminUpdatePasswordCommand(validUser.getUsername(), "000"); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = adminUpdatePasswordCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedIn_updateFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + User validUserToUpdate = TypicalUsers.JOSH; + AdminUpdatePasswordCommand adminUpdatePasswordCommand = + new AdminUpdatePasswordCommand(validUserToUpdate.getUsername(), "000"); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_ADMIN); + + CommandResult commandResult = adminUpdatePasswordCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_ADMIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/AnnounceCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/AnnounceCommandTest.java new file mode 100644 index 000000000000..e06264ad0f3f --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/AnnounceCommandTest.java @@ -0,0 +1,88 @@ +package com.t13g2.forum.logic.commands; + +import static junit.framework.TestCase.assertEquals; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.AnnouncementBuilder; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; +import com.t13g2.forum.testutil.UserBuilder; + +//@@author xllx1 +/** + * integration test for AnnounceCommand. + */ +public class AnnounceCommandTest { + private static final CommandHistory EMPTY_COMMAND_HISTORY = new CommandHistory(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private Model model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + private CommandHistory commandHistory = new CommandHistory(); + + + @Test + public void constructor_nullAnnouncement_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new AnnounceCommand(null); + } + + @Test + public void execute_userNotLogin_announceFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Announcement validAnnouncement = new AnnouncementBuilder().build(); + AnnounceCommand announceCommand = new AnnounceCommand(validAnnouncement); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = announceCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedIn_announceFailed() throws Exception { + //set the current logged in user as a user. + User loginUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(loginUser); + + Announcement validAnnouncement = new AnnouncementBuilder().build(); + AnnounceCommand announceCommand = new AnnounceCommand(validAnnouncement); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_ADMIN); + + CommandResult commandResult = announceCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_ADMIN, commandResult.feedbackToUser); + } + + + @Test + public void execute_announcementAccepted_announceSuccessful() throws Exception { + //set the current logged in user as an admin. + User loginUser = new UserBuilder().build(); + Context.getInstance().setCurrentUser(loginUser); + + Announcement validAnnouncement = new AnnouncementBuilder().build(); + + CommandResult commandResult = new AnnounceCommand(validAnnouncement).execute(model, commandHistory); + + assertEquals(String.format(AnnounceCommand.MESSAGE_SUCCESS, validAnnouncement), + commandResult.feedbackToUser); + assertEquals(EMPTY_COMMAND_HISTORY, commandHistory); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/BlockUserFromCreatingCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/BlockUserFromCreatingCommandTest.java new file mode 100644 index 000000000000..99fb806cb721 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/BlockUserFromCreatingCommandTest.java @@ -0,0 +1,167 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; +import com.t13g2.forum.testutil.UserBuilder; + +//@@author xllx1 +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class BlockUserFromCreatingCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_adminAndDuplicateUnblock_blockUserFailed () throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + User toBlock = TypicalUsers.JIM; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getUserRepository().addUser(toBlock); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + BlockUserFromCreatingCommand blockCommand = + new BlockUserFromCreatingCommand(toBlock.getUsername(), false); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(BlockUserFromCreatingCommand.MESSAGE_DUPLICATE_UNBLOCK, + toBlock.getUsername())); + + CommandResult commandResult = blockCommand.execute(model, commandHistory); + assertEquals(String.format(BlockUserFromCreatingCommand.MESSAGE_DUPLICATE_UNBLOCK, + toBlock.getUsername()), commandResult.feedbackToUser); + } + + @Test + public void execute_adminAndValidUserName_blockUserSuccess () { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + User toBlock = TypicalUsers.JIM; + BlockUserFromCreatingCommand blockCommand = new BlockUserFromCreatingCommand(toBlock.getUsername(), true); + + CommandTestUtil.assertCommandSuccess(blockCommand, model, commandHistory, + String.format(BlockUserFromCreatingCommand.MESSAGE_SUCCESS, "blocked", toBlock.getUsername()), + expectedModel); + } + + @Test + public void execute_adminBlockAdmin_blockUserFailed () throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getUserRepository().addUser(validAdmin); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + + BlockUserFromCreatingCommand blockCommand = new BlockUserFromCreatingCommand(validAdmin.getUsername(), true); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(BlockUserFromCreatingCommand.MESSAGE_USER_IS_ADMIN, + validAdmin.getUsername())); + + CommandResult commandResult = blockCommand.execute(model, commandHistory); + assertEquals(String.format(BlockUserFromCreatingCommand.MESSAGE_USER_IS_ADMIN, + validAdmin.getUsername()), commandResult.feedbackToUser); + } + + @Test + public void execute_adminDuplicateBlock_blockUserFailed () throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + User toBlock = TypicalUsers.JIM; + BlockUserFromCreatingCommand blockCommand = + new BlockUserFromCreatingCommand(toBlock.getUsername(), true); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(BlockUserFromCreatingCommand.MESSAGE_DUPLICATE_BLOCK, + toBlock.getUsername())); + + CommandResult commandResult = blockCommand.execute(model, commandHistory); + assertEquals(String.format(BlockUserFromCreatingCommand.MESSAGE_DUPLICATE_BLOCK, + toBlock.getUsername()), commandResult.feedbackToUser); + } + + @Test + public void execute_adminInvalidUserName_blockUserFailed () throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + BlockUserFromCreatingCommand blockCommand = new BlockUserFromCreatingCommand("abcd", true); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(BlockUserFromCreatingCommand.MESSAGE_INVALID_USER, "abcd")); + + CommandResult commandResult = blockCommand.execute(model, commandHistory); + assertEquals(String.format(BlockUserFromCreatingCommand.MESSAGE_INVALID_USER, "abcd"), + commandResult.feedbackToUser); + } + + @Test + public void execute_userNotLogin_blockUserFailed () throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + User validUser = TypicalUsers.JIM; + BlockUserFromCreatingCommand blockCommand = new BlockUserFromCreatingCommand(validUser.getUsername(), true); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = blockCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedIn_blockUserFailed () throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JIM; + Context.getInstance().setCurrentUser(validUser); + + BlockUserFromCreatingCommand blockCommand = + new BlockUserFromCreatingCommand(TypicalUsers.JANEDOE.getUsername(), true); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_ADMIN); + + CommandResult commandResult = blockCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_ADMIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/CheckAnnounceCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/CheckAnnounceCommandTest.java new file mode 100644 index 000000000000..af370348f4e0 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/CheckAnnounceCommandTest.java @@ -0,0 +1,76 @@ +package com.t13g2.forum.logic.commands; + +import static junit.framework.TestCase.assertEquals; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.AnnouncementBuilder; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; +import com.t13g2.forum.testutil.UserBuilder; + +//@@author xllx1 +/** + * integration test for CheckAnnounceCommand. + */ +public class CheckAnnounceCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_userLoggedIn_checkAnnounceSuccessful() throws Exception { + //set the current logged in user as an admin. + User admin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(admin); + + Announcement validAnnouncement = new AnnouncementBuilder().build(); + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getAnnouncementRepository().addAnnouncement(validAnnouncement); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + + //set the current logged in user as a user. + User loginUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(loginUser); + + String expectedMessage = String.format(CheckAnnouncmentCommand.MESSAGE_SUCCESS, validAnnouncement); + CommandTestUtil.assertCommandSuccess(new CheckAnnouncmentCommand(), model, commandHistory, + expectedMessage, expectedModel); + } + + @Test + public void execute_userNotLogin_checkAnnounceFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + CheckAnnouncmentCommand checkAnnouncmentCommand = new CheckAnnouncmentCommand(); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = checkAnnouncmentCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/ClearCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/ClearCommandTest.java new file mode 100644 index 000000000000..69031a14224e --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/ClearCommandTest.java @@ -0,0 +1,37 @@ +package com.t13g2.forum.logic.commands; + +import org.junit.Test; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.testutil.TypicalPersons; + +public class ClearCommandTest { + + private CommandHistory commandHistory = new CommandHistory(); + + @Test + public void execute_emptyAddressBook_success() { + Model model = new ModelManager(); + Model expectedModel = new ModelManager(); + expectedModel.commitForumBook(); + + CommandTestUtil.assertCommandSuccess(new ClearCommand(), model, commandHistory, + ClearCommand.MESSAGE_SUCCESS, expectedModel); + } + + @Test + public void execute_nonEmptyAddressBook_success() { + Model model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel.resetData(new ForumBook()); + expectedModel.commitForumBook(); + + CommandTestUtil.assertCommandSuccess(new ClearCommand(), model, commandHistory, + ClearCommand.MESSAGE_SUCCESS, expectedModel); + } + +} diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/com/t13g2/forum/logic/commands/CommandTestUtil.java similarity index 66% rename from src/test/java/seedu/address/logic/commands/CommandTestUtil.java rename to src/test/java/com/t13g2/forum/logic/commands/CommandTestUtil.java index bf861fcb36c3..006112dbc519 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/com/t13g2/forum/logic/commands/CommandTestUtil.java @@ -1,31 +1,32 @@ -package seedu.address.logic.commands; - +package com.t13g2.forum.logic.commands; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_EMAIL; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_TITLE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_PHONE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_TAG; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -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_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.CommandHistory; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.model.person.Person; -import seedu.address.testutil.EditPersonDescriptorBuilder; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.person.NameContainsKeywordsPredicate; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.testutil.EditPersonDescriptorBuilder; /** * Contains helper methods for testing commands. */ 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_PHONE_AMY = "11111111"; @@ -37,6 +38,24 @@ public class CommandTestUtil { public static final String VALID_TAG_HUSBAND = "husband"; public static final String VALID_TAG_FRIEND = "friend"; + //@@author xllx1 + public static final String VALID_MODULE_CODE_MA1508E = "MA1508E"; + public static final String VALID_MODULE_TITLE_MA1508E = "Linear Algebra for Engineering"; + public static final String VALID_MODULE_CODE_GET1020 = "GET1020"; + public static final String VALID_MODULE_TITLE_GET1020 = "Darwin and Evolution"; + public static final String VALID_MODULE_CODE_CS1231 = "CS1231"; + public static final String VALID_MODULE_TITLE_CS1231 = "Discrete Math"; + + public static final String MODULE_CODE_DESC_MA1508E = " " + PREFIX_MODULE_CODE + VALID_MODULE_CODE_MA1508E; + public static final String MODULE_TITLE_DESC_MA1508E = " " + PREFIX_MODULE_TITLE + VALID_MODULE_TITLE_MA1508E; + public static final String MODULE_CODE_DESC_GET1020 = " " + PREFIX_MODULE_CODE + VALID_MODULE_CODE_GET1020; + public static final String MODULE_TITLE_DESC_GET1020 = " " + PREFIX_MODULE_TITLE + VALID_MODULE_TITLE_GET1020; + public static final String MODULE_CODE_DESC_CS1231 = " " + PREFIX_MODULE_CODE + VALID_MODULE_CODE_CS1231; + public static final String MODULE_TITLE_DESC_CS1231 = " " + PREFIX_MODULE_TITLE + VALID_MODULE_TITLE_CS1231; + public static final String INVALID_MODULE_CODE_DESC = " " + PREFIX_MODULE_CODE + "A1508"; + public static final String INVALID_MODULE_TITLE_DESC = " " + PREFIX_MODULE_TITLE + ""; + + //@@author 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 PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY; @@ -62,11 +81,11 @@ public class CommandTestUtil { static { DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY) - .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY) - .withTags(VALID_TAG_FRIEND).build(); + .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY) + .withTags(VALID_TAG_FRIEND).build(); DESC_BOB = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB) - .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB) - .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build(); + .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB) + .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build(); } /** @@ -76,7 +95,7 @@ public class CommandTestUtil { * - the {@code actualCommandHistory} remains unchanged. */ public static void assertCommandSuccess(Command command, Model actualModel, CommandHistory actualCommandHistory, - String expectedMessage, Model expectedModel) { + String expectedMessage, Model expectedModel) { CommandHistory expectedCommandHistory = new CommandHistory(actualCommandHistory); try { CommandResult result = command.execute(actualModel, actualCommandHistory); @@ -96,10 +115,10 @@ public static void assertCommandSuccess(Command command, Model actualModel, Comm * - {@code actualCommandHistory} remains unchanged. */ public static void assertCommandFailure(Command command, Model actualModel, CommandHistory actualCommandHistory, - String expectedMessage) { + 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()); + ForumBook expectedForumBook = new ForumBook(actualModel.getForumBook()); List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPersonList()); CommandHistory expectedCommandHistory = new CommandHistory(actualCommandHistory); @@ -109,7 +128,7 @@ public static void assertCommandFailure(Command command, Model actualModel, Comm throw new AssertionError("The expected CommandException was not thrown."); } catch (CommandException e) { assertEquals(expectedMessage, e.getMessage()); - assertEquals(expectedAddressBook, actualModel.getAddressBook()); + assertEquals(expectedForumBook, actualModel.getForumBook()); assertEquals(expectedFilteredList, actualModel.getFilteredPersonList()); assertEquals(expectedCommandHistory, actualCommandHistory); } @@ -135,7 +154,6 @@ public static void showPersonAtIndex(Model model, Index targetIndex) { public static void deleteFirstPerson(Model model) { Person firstPerson = model.getFilteredPersonList().get(0); model.deletePerson(firstPerson); - model.commitAddressBook(); + model.commitForumBook(); } - } diff --git a/src/test/java/com/t13g2/forum/logic/commands/CreateCommentCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/CreateCommentCommandTest.java new file mode 100644 index 000000000000..d06bad99d455 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/CreateCommentCommandTest.java @@ -0,0 +1,137 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.CommentBuilder; +import com.t13g2.forum.testutil.ForumThreadBuilder; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + +//@@author HansKoh +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class CreateCommentCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullThread_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new CreateThreadCommand(null, null, null); + } + + @Test + public void execute_userLoggedInCreateComment_createCommentSuccess() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + } catch (Exception e) { + e.printStackTrace(); + } + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + + CreateCommentCommand createCommentCommand = + new CreateCommentCommand(forumThread.getId(), comment.getContent()); + + CommandResult commandResult = createCommentCommand.execute(model, commandHistory); + + int commentId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + List commentList = unitOfWork.getCommentRepository().getCommentsByThread(forumThread); + commentId = commentList.get(1).getId(); + } catch (Exception e) { + e.printStackTrace(); + } + + String message = "\n" + + "Module ID: " + moduleId + "\n" + + "Thread ID: " + forumThread.getId() + "\n" + + "Comment ID: " + commentId + "\n" + + "Comment Content: " + comment.getContent(); + + assertEquals(String.format(createCommentCommand.MESSAGE_SUCCESS, message), commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedIn_createCommentFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + moduleId = unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + CreateCommentCommand createCommentCommand = + new CreateCommentCommand(forumThread.getId(), comment.getContent()); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = createCommentCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedInInvalidThreadId_createCommentFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + int inValidThreadId = 8888; + Comment comment = new CommentBuilder().build(); + CreateCommentCommand createCommentCommand = + new CreateCommentCommand(inValidThreadId, comment.getContent()); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_INVALID_THREAD_ID); + + CommandResult commandResult = createCommentCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_INVALID_THREAD_ID, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/CreateModuleCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/CreateModuleCommandTest.java new file mode 100644 index 000000000000..f225d11957c3 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/CreateModuleCommandTest.java @@ -0,0 +1,106 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; +import com.t13g2.forum.testutil.UserBuilder; + +//@@author xllx1 +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class CreateModuleCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullModule_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new CreateModuleCommand(null); + } + + @Test + public void execute_adminLoggedInCreateModule_createModuleSuccess() { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + Module validModule = TypicalModules.GET1020; + CreateModuleCommand createModuleCommand = new CreateModuleCommand(validModule); + + CommandTestUtil.assertCommandSuccess(createModuleCommand, model, commandHistory, + String.format(CreateModuleCommand.MESSAGE_SUCCESS, validModule.getModuleCode()), expectedModel); + } + + @Test + public void execute_adminLoggedInDuplicateModule_createModuleFailed() throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + Module validModule = TypicalModules.GET1020; + CreateModuleCommand createModuleCommand = new CreateModuleCommand(validModule); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(CreateModuleCommand.MESSAGE_DUPLICATE_MODULE, validModule.getModuleCode())); + + CommandResult commandResult = createModuleCommand.execute(model, commandHistory); + assertEquals(String.format(CreateModuleCommand.MESSAGE_DUPLICATE_MODULE, + validModule.getModuleCode()), commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedIn_createModuleFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.GET1020; + CreateModuleCommand createModuleCommand = new CreateModuleCommand(validModule); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = createModuleCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedIn_createModuleFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.GET1020; + CreateModuleCommand createModuleCommand = new CreateModuleCommand(validModule); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_ADMIN); + + CommandResult commandResult = createModuleCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_ADMIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/CreateThreadCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/CreateThreadCommandTest.java new file mode 100644 index 000000000000..bdea4aa9140f --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/CreateThreadCommandTest.java @@ -0,0 +1,120 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.CommentBuilder; +import com.t13g2.forum.testutil.ForumThreadBuilder; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + +//@@author HansKoh +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class CreateThreadCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullThread_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new CreateThreadCommand(null, null, null); + } + + @Test + public void execute_userLoggedInCreateThread_createThreadSuccess() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + } catch (Exception e) { + e.printStackTrace(); + } + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + String message = "\n" + + "Module: " + validModule.getModuleCode() + "\n" + + "Thread Title: " + forumThread.getTitle() + "\n" + + "Comment: " + comment.getContent(); + + CommandTestUtil.assertCommandSuccess(createThreadCommand, model, commandHistory, + String.format(createThreadCommand.MESSAGE_SUCCESS, message), expectedModel); + } + + @Test + public void execute_notLoggedIn_createThreadFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + moduleId = unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = createThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedInInvalidModuleCode_createThreadFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + String inValidModuleCode = "AB1234"; + ForumThread forumThread = new ForumThread(); + Comment comment = new Comment(); + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(inValidModuleCode, forumThread, comment); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_INVALID_MODULE_CODE); + + CommandResult commandResult = createThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_INVALID_MODULE_CODE, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/DeleteCommentCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/DeleteCommentCommandTest.java new file mode 100644 index 000000000000..801c07ee60b0 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/DeleteCommentCommandTest.java @@ -0,0 +1,163 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.CommentBuilder; +import com.t13g2.forum.testutil.ForumThreadBuilder; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + +//@@author HansKoh +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class DeleteCommentCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_userLoggedInDeleteComment_deleteCommentSuccess() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int commentId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(moduleId); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Context.getInstance().setCurrentThreadId(forumThread.getId()); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + commentId = comment.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + DeleteCommentCommand deleteCommentCommand = new DeleteCommentCommand(commentId); + String deleteMessage = "\n\n" + + "Under Module Code: " + validModule.getModuleCode() + "\n" + + "Under Thread ID: " + Context.getInstance().getCurrentThreadId() + "\n" + + "Deleted Comment ID: " + commentId + "\n"; + + CommandTestUtil.assertCommandSuccess(deleteCommentCommand, model, commandHistory, + String.format(deleteCommentCommand.MESSAGE_SUCCESS, deleteMessage), expectedModel); + } + + @Test + public void execute_userLoggedInNotCommentOwner_deleteCommentFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int commentId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(moduleId); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Context.getInstance().setCurrentThreadId(forumThread.getId()); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + commentId = comment.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + Context.getInstance().setCurrentUser(TypicalUsers.JIM); + DeleteCommentCommand deleteCommentCommand = new DeleteCommentCommand(commentId); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_COMMENT_OWNER); + + CommandResult commandResult = deleteCommentCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_COMMENT_OWNER, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedInNotUnderCurrentScope_deleteCommentFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int commentId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(8888); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + commentId = comment.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + DeleteCommentCommand deleteCommentCommand = new DeleteCommentCommand(commentId); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_INVALID_COMMENT); + + CommandResult commandResult = deleteCommentCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_INVALID_COMMENT, commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedInDeleteComment_deleteCommentFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.CS1231; + ForumThread forumThread = new ForumThreadBuilder().withModuleId(validModule.getId()).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + DeleteCommentCommand deleteCommentCommand = + new DeleteCommentCommand(comment.getId()); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = deleteCommentCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/DeleteModuleCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/DeleteModuleCommandTest.java new file mode 100644 index 000000000000..791d1169a5d4 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/DeleteModuleCommandTest.java @@ -0,0 +1,113 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; +import com.t13g2.forum.testutil.UserBuilder; + +//@@author xllx1 +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class DeleteModuleCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullModuleCode_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new DeleteModuleCommand(null); + } + + @Test + public void execute_adminLoggedInAndValidModule_deleteModuleSuccess() { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + Module validModule = TypicalModules.GET1020; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + DeleteModuleCommand deleteModuleCommand = new DeleteModuleCommand(validModule.getModuleCode()); + + CommandTestUtil.assertCommandSuccess(deleteModuleCommand, model, commandHistory, + String.format(DeleteModuleCommand.MESSAGE_SUCCESS, validModule.getModuleCode()), expectedModel); + } + + @Test + public void execute_adminLoggedInInvalidModule_deleteModuleFailed() throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + Module validModule = TypicalModules.GET1020; + DeleteModuleCommand deleteModuleCommand = new DeleteModuleCommand(validModule.getModuleCode()); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(DeleteModuleCommand.MESSAGE_INVALID_MODULE, validModule.getModuleCode())); + + CommandResult commandResult = deleteModuleCommand.execute(model, commandHistory); + assertEquals(String.format(deleteModuleCommand.MESSAGE_INVALID_MODULE, + validModule.getModuleCode()), commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedIn_deleteModuleFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.GET1020; + DeleteModuleCommand deleteModuleCommand = new DeleteModuleCommand(validModule.getModuleCode()); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = deleteModuleCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedIn_deleteModuleFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.GET1020; + DeleteModuleCommand deleteModuleCommand = new DeleteModuleCommand(validModule.getModuleCode()); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_ADMIN); + + CommandResult commandResult = deleteModuleCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_ADMIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/DeleteThreadCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/DeleteThreadCommandTest.java new file mode 100644 index 000000000000..200ab1c97981 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/DeleteThreadCommandTest.java @@ -0,0 +1,163 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.CommentBuilder; +import com.t13g2.forum.testutil.ForumThreadBuilder; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + +//@@author HansKoh +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class DeleteThreadCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_userLoggedInDeleteThread_deleteThreadSuccess() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int threadId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(moduleId); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + threadId = forumThread.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + DeleteThreadCommand deleteThreadCommand = new DeleteThreadCommand(threadId); + String deletedMessage = "\n\n" + + "Under Module Code: " + validModule.getModuleCode() + "\n" + + "Deleted Thread ID: " + threadId + "\n"; + + CommandTestUtil.assertCommandSuccess(deleteThreadCommand, model, commandHistory, + String.format(deleteThreadCommand.MESSAGE_SUCCESS, deletedMessage), expectedModel); + + } + + @Test + public void execute_userLoggedInNotThreadOwner_deleteThreadFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int threadId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(moduleId); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + threadId = forumThread.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + Context.getInstance().setCurrentUser(TypicalUsers.JIM); + DeleteThreadCommand deleteThreadCommand = new DeleteThreadCommand(threadId); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_THREAD_OWNER); + + CommandResult commandResult = deleteThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_THREAD_OWNER, commandResult.feedbackToUser); + + } + + @Test + public void execute_userLoggedInNotUnderCurrentScope_deleteThreadFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int threadId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(8888); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + threadId = forumThread.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + DeleteThreadCommand deleteThreadCommand = new DeleteThreadCommand(threadId); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_INVALID_THREAD); + + CommandResult commandResult = deleteThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_INVALID_THREAD, commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedInDeleteThread_deleteThreadFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.CS1231; + ForumThread forumThread = new ForumThreadBuilder().withModuleId(validModule.getId()).build(); + DeleteThreadCommand deleteThreadCommand = + new DeleteThreadCommand(forumThread.getId()); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = deleteThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/DeleteUserCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/DeleteUserCommandTest.java new file mode 100644 index 000000000000..636e9836fb22 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/DeleteUserCommandTest.java @@ -0,0 +1,111 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; +import com.t13g2.forum.testutil.UserBuilder; + +//@@author xllx1 +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class DeleteUserCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullModuleCode_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new DeleteUserCommand(null); + } + + @Test + public void execute_adminLoggedInAndValidUserName_deleteSuccess() { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + User validUser = TypicalUsers.JOSHUA; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getUserRepository().addUser(validUser); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + DeleteUserCommand deleteUserCommand = new DeleteUserCommand(validUser.getUsername()); + + CommandTestUtil.assertCommandSuccess(deleteUserCommand, model, commandHistory, + String.format(DeleteUserCommand.MESSAGE_SUCCESS, validUser.getUsername()), expectedModel); + } + + @Test + public void execute_adminLoggedInInvalidUserName_deleteFailed() throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + String invalidUserName = "abcde"; + DeleteUserCommand deleteUserCommand = new DeleteUserCommand(invalidUserName); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(DeleteUserCommand.MESSAGE_INVALID_USER, invalidUserName)); + + CommandResult commandResult = deleteUserCommand.execute(model, commandHistory); + assertEquals(String.format(DeleteUserCommand.MESSAGE_INVALID_USER, + invalidUserName), commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedIn_deleteFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + User validUser = TypicalUsers.JOSHUA; + DeleteUserCommand deleteUserCommand = new DeleteUserCommand(validUser.getUsername()); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = deleteUserCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedIn_deleteFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + User validUserToDelete = TypicalUsers.JOSHUA; + DeleteUserCommand deleteUserCommand = new DeleteUserCommand(validUserToDelete.getUsername()); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_ADMIN); + + CommandResult commandResult = deleteUserCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_ADMIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/EditCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/EditCommandTest.java new file mode 100644 index 000000000000..fc787b20373a --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/EditCommandTest.java @@ -0,0 +1,255 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.EditCommand.EditPersonDescriptor; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.testutil.EditPersonDescriptorBuilder; +import com.t13g2.forum.testutil.PersonBuilder; +import com.t13g2.forum.testutil.TypicalIndexes; +import com.t13g2.forum.testutil.TypicalPersons; + +/** + * Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for EditCommand. + */ +public class EditCommandTest { + + private Model model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + private CommandHistory commandHistory = new CommandHistory(); + + @Test + public void execute_allFieldsSpecifiedUnfilteredList_success() { + Person editedPerson = new PersonBuilder().build(); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, descriptor); + + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); + + Model expectedModel = new ModelManager(new ForumBook(model.getForumBook()), new UserPrefs()); + expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedPerson); + expectedModel.commitForumBook(); + + CommandTestUtil.assertCommandSuccess(editCommand, model, commandHistory, expectedMessage, expectedModel); + } + + @Test + public void execute_someFieldsSpecifiedUnfilteredList_success() { + Index indexLastPerson = Index.fromOneBased(model.getFilteredPersonList().size()); + Person lastPerson = model.getFilteredPersonList().get(indexLastPerson.getZeroBased()); + + PersonBuilder personInList = new PersonBuilder(lastPerson); + Person editedPerson = personInList.withName(CommandTestUtil.VALID_NAME_BOB) + .withPhone(CommandTestUtil.VALID_PHONE_BOB) + .withTags(CommandTestUtil.VALID_TAG_HUSBAND).build(); + + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(CommandTestUtil.VALID_NAME_BOB) + .withPhone(CommandTestUtil.VALID_PHONE_BOB).withTags(CommandTestUtil.VALID_TAG_HUSBAND).build(); + EditCommand editCommand = new EditCommand(indexLastPerson, descriptor); + + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); + + Model expectedModel = new ModelManager(new ForumBook(model.getForumBook()), new UserPrefs()); + expectedModel.updatePerson(lastPerson, editedPerson); + expectedModel.commitForumBook(); + + CommandTestUtil.assertCommandSuccess(editCommand, model, commandHistory, expectedMessage, expectedModel); + } + + @Test + public void execute_noFieldSpecifiedUnfilteredList_success() { + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, new EditPersonDescriptor()); + Person editedPerson = model.getFilteredPersonList().get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()); + + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); + + Model expectedModel = new ModelManager(new ForumBook(model.getForumBook()), new UserPrefs()); + expectedModel.commitForumBook(); + + CommandTestUtil.assertCommandSuccess(editCommand, model, commandHistory, expectedMessage, expectedModel); + } + + @Test + public void execute_filteredList_success() { + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); + + Person personInFilteredList = model.getFilteredPersonList().get(TypicalIndexes + .INDEX_FIRST_PERSON.getZeroBased()); + Person editedPerson = new PersonBuilder(personInFilteredList).withName(CommandTestUtil.VALID_NAME_BOB).build(); + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, + new EditPersonDescriptorBuilder().withName(CommandTestUtil.VALID_NAME_BOB).build()); + + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); + + Model expectedModel = new ModelManager(new ForumBook(model.getForumBook()), new UserPrefs()); + expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedPerson); + expectedModel.commitForumBook(); + + CommandTestUtil.assertCommandSuccess(editCommand, model, commandHistory, expectedMessage, expectedModel); + } + + @Test + public void execute_duplicatePersonUnfilteredList_failure() { + Person firstPerson = model.getFilteredPersonList().get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstPerson).build(); + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_SECOND_PERSON, descriptor); + + CommandTestUtil.assertCommandFailure(editCommand, model, commandHistory, EditCommand.MESSAGE_DUPLICATE_PERSON); + } + + @Test + public void execute_duplicatePersonFilteredList_failure() { + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); + + // edit person in filtered list into a duplicate in address book + Person personInList = model.getForumBook().getPersonList() + .get(TypicalIndexes.INDEX_SECOND_PERSON.getZeroBased()); + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, + new EditPersonDescriptorBuilder(personInList).build()); + + CommandTestUtil.assertCommandFailure(editCommand, model, commandHistory, EditCommand.MESSAGE_DUPLICATE_PERSON); + } + + @Test + public void execute_invalidPersonIndexUnfilteredList_failure() { + Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder() + .withName(CommandTestUtil.VALID_NAME_BOB).build(); + EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor); + + CommandTestUtil.assertCommandFailure(editCommand, model, commandHistory, + Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + /** + * Edit filtered list where index is larger than size of filtered list, + * but smaller than size of address book + */ + @Test + public void execute_invalidPersonIndexFilteredList_failure() { + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); + Index outOfBoundIndex = TypicalIndexes.INDEX_SECOND_PERSON; + // ensures that outOfBoundIndex is still in bounds of address book list + assertTrue(outOfBoundIndex.getZeroBased() < model.getForumBook().getPersonList().size()); + + EditCommand editCommand = new EditCommand(outOfBoundIndex, + new EditPersonDescriptorBuilder().withName(CommandTestUtil.VALID_NAME_BOB).build()); + + CommandTestUtil.assertCommandFailure(editCommand, model, commandHistory, + Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + @Test + public void executeUndoRedo_validIndexUnfilteredList_success() throws Exception { + Person editedPerson = new PersonBuilder().build(); + Person personToEdit = model.getFilteredPersonList().get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, descriptor); + Model expectedModel = new ModelManager(new ForumBook(model.getForumBook()), new UserPrefs()); + expectedModel.updatePerson(personToEdit, editedPerson); + expectedModel.commitForumBook(); + + // edit -> first person edited + editCommand.execute(model, commandHistory); + + // undo -> reverts addressbook back to previous state and filtered person list to show all persons + expectedModel.undoForumBook(); + CommandTestUtil.assertCommandSuccess(new UndoCommand(), model, commandHistory, + UndoCommand.MESSAGE_SUCCESS, expectedModel); + + // redo -> same first person edited again + expectedModel.redoForumBook(); + CommandTestUtil.assertCommandSuccess(new RedoCommand(), model, commandHistory, + RedoCommand.MESSAGE_SUCCESS, expectedModel); + } + + @Test + public void executeUndoRedo_invalidIndexUnfilteredList_failure() { + Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder() + .withName(CommandTestUtil.VALID_NAME_BOB).build(); + EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor); + + // execution failed -> address book state not added into model + CommandTestUtil.assertCommandFailure(editCommand, model, commandHistory, + Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + + // single address book state in model -> undoCommand and redoCommand fail + CommandTestUtil.assertCommandFailure(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_FAILURE); + CommandTestUtil.assertCommandFailure(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_FAILURE); + } + + /** + * 1. Edits a {@code Person} 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 + * 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. + */ + @Test + public void executeUndoRedo_validIndexFilteredList_samePersonEdited() throws Exception { + Person editedPerson = new PersonBuilder().build(); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, descriptor); + Model expectedModel = new ModelManager(new ForumBook(model.getForumBook()), new UserPrefs()); + + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_SECOND_PERSON); + Person personToEdit = model.getFilteredPersonList().get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()); + expectedModel.updatePerson(personToEdit, editedPerson); + expectedModel.commitForumBook(); + + // edit -> edits second person in unfiltered person list / first person in filtered person list + editCommand.execute(model, commandHistory); + + // undo -> reverts addressbook back to previous state and filtered person list to show all persons + expectedModel.undoForumBook(); + CommandTestUtil.assertCommandSuccess(new UndoCommand(), model, commandHistory, + UndoCommand.MESSAGE_SUCCESS, expectedModel); + + assertNotEquals(model.getFilteredPersonList().get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()), + personToEdit); + // redo -> edits same second person in unfiltered person list + expectedModel.redoForumBook(); + CommandTestUtil.assertCommandSuccess(new RedoCommand(), model, commandHistory, + RedoCommand.MESSAGE_SUCCESS, expectedModel); + } + + @Test + public void equals() { + final EditCommand standardCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, + CommandTestUtil.DESC_AMY); + + // same values -> returns true + EditPersonDescriptor copyDescriptor = new EditPersonDescriptor(CommandTestUtil.DESC_AMY); + EditCommand commandWithSameValues = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, copyDescriptor); + assertTrue(standardCommand.equals(commandWithSameValues)); + + // same object -> returns true + assertTrue(standardCommand.equals(standardCommand)); + + // null -> returns false + assertFalse(standardCommand.equals(null)); + + // different types -> returns false + assertFalse(standardCommand.equals(new ClearCommand())); + + // different index -> returns false + assertFalse(standardCommand.equals(new EditCommand(TypicalIndexes.INDEX_SECOND_PERSON, + CommandTestUtil.DESC_AMY))); + + // different descriptor -> returns false + assertFalse(standardCommand.equals(new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, + CommandTestUtil.DESC_BOB))); + } + +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/EditPersonDescriptorTest.java b/src/test/java/com/t13g2/forum/logic/commands/EditPersonDescriptorTest.java new file mode 100644 index 000000000000..6888c8f013d1 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/EditPersonDescriptorTest.java @@ -0,0 +1,60 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.t13g2.forum.logic.commands.EditCommand.EditPersonDescriptor; +import com.t13g2.forum.testutil.EditPersonDescriptorBuilder; + +public class EditPersonDescriptorTest { + + @Test + public void equals() { + // same values -> returns true + EditPersonDescriptor descriptorWithSameValues = new EditPersonDescriptor(CommandTestUtil.DESC_AMY); + assertTrue(CommandTestUtil.DESC_AMY.equals(descriptorWithSameValues)); + + // same object -> returns true + assertTrue(CommandTestUtil.DESC_AMY.equals(CommandTestUtil.DESC_AMY)); + + // null -> returns false + assertFalse(CommandTestUtil.DESC_AMY.equals(null)); + + // different types -> returns false + assertFalse(CommandTestUtil.DESC_AMY.equals(5)); + + // different values -> returns false + assertFalse(CommandTestUtil.DESC_AMY.equals(CommandTestUtil.DESC_BOB)); + + // different name -> returns false + EditPersonDescriptor editedAmy = + new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY).withName(CommandTestUtil.VALID_NAME_BOB).build(); + assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + + // different phone -> returns false + editedAmy = + new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY) + .withPhone(CommandTestUtil.VALID_PHONE_BOB).build(); + assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + + // different email -> returns false + editedAmy = + new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY) + .withEmail(CommandTestUtil.VALID_EMAIL_BOB).build(); + assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + + // different address -> returns false + editedAmy = + new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY) + .withAddress(CommandTestUtil.VALID_ADDRESS_BOB).build(); + assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + + // different tags -> returns false + editedAmy = + new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY) + .withTags(CommandTestUtil.VALID_TAG_HUSBAND).build(); + assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + } +} diff --git a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/ExitCommandTest.java similarity index 67% rename from src/test/java/seedu/address/logic/commands/ExitCommandTest.java rename to src/test/java/com/t13g2/forum/logic/commands/ExitCommandTest.java index 60c52950ede2..a1c58d48bd4b 100644 --- a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java +++ b/src/test/java/com/t13g2/forum/logic/commands/ExitCommandTest.java @@ -1,17 +1,17 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; +import static com.t13g2.forum.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static seedu.address.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT; import org.junit.Rule; import org.junit.Test; -import seedu.address.commons.events.ui.ExitAppRequestEvent; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.ui.testutil.EventsCollectorRule; +import com.t13g2.forum.commons.events.ui.ExitAppRequestEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.ui.testutil.EventsCollectorRule; public class ExitCommandTest { @Rule diff --git a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/HelpCommandTest.java similarity index 62% rename from src/test/java/seedu/address/logic/commands/HelpCommandTest.java rename to src/test/java/com/t13g2/forum/logic/commands/HelpCommandTest.java index 6a1e34bf476f..7252e2d92be6 100644 --- a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java +++ b/src/test/java/com/t13g2/forum/logic/commands/HelpCommandTest.java @@ -1,17 +1,17 @@ -package seedu.address.logic.commands; +package com.t13g2.forum.logic.commands; +import static com.t13g2.forum.logic.commands.CommandTestUtil.assertCommandSuccess; +import static com.t13g2.forum.logic.commands.HelpCommand.SHOWING_HELP_MESSAGE; import static org.junit.Assert.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.HelpCommand.SHOWING_HELP_MESSAGE; import org.junit.Rule; import org.junit.Test; -import seedu.address.commons.events.ui.ShowHelpRequestEvent; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.ui.testutil.EventsCollectorRule; +import com.t13g2.forum.commons.events.ui.ShowHelpRequestEvent; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.ui.testutil.EventsCollectorRule; public class HelpCommandTest { @Rule diff --git a/src/test/java/seedu/address/logic/commands/HistoryCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/HistoryCommandTest.java similarity index 57% rename from src/test/java/seedu/address/logic/commands/HistoryCommandTest.java rename to src/test/java/com/t13g2/forum/logic/commands/HistoryCommandTest.java index 8d2ecab4d940..7d2d6e6d5de1 100644 --- a/src/test/java/seedu/address/logic/commands/HistoryCommandTest.java +++ b/src/test/java/com/t13g2/forum/logic/commands/HistoryCommandTest.java @@ -1,12 +1,10 @@ -package seedu.address.logic.commands; - -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +package com.t13g2.forum.logic.commands; import org.junit.Test; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; public class HistoryCommandTest { private CommandHistory history = new CommandHistory(); @@ -15,11 +13,12 @@ public class HistoryCommandTest { @Test public void execute() { - assertCommandSuccess(new HistoryCommand(), model, history, HistoryCommand.MESSAGE_NO_HISTORY, expectedModel); + CommandTestUtil.assertCommandSuccess(new HistoryCommand(), model, history, + HistoryCommand.MESSAGE_NO_HISTORY, expectedModel); String command1 = "clear"; history.add(command1); - assertCommandSuccess(new HistoryCommand(), model, history, + CommandTestUtil.assertCommandSuccess(new HistoryCommand(), model, history, String.format(HistoryCommand.MESSAGE_SUCCESS, command1), expectedModel); String command2 = "randomCommand"; @@ -29,7 +28,7 @@ public void execute() { String expectedMessage = String.format(HistoryCommand.MESSAGE_SUCCESS, String.join("\n", command3, command2, command1)); - assertCommandSuccess(new HistoryCommand(), model, history, expectedMessage, expectedModel); + CommandTestUtil.assertCommandSuccess(new HistoryCommand(), model, history, expectedMessage, expectedModel); } } diff --git a/src/test/java/com/t13g2/forum/logic/commands/ListCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/ListCommandTest.java new file mode 100644 index 000000000000..57dd3346b0df --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/ListCommandTest.java @@ -0,0 +1,40 @@ +package com.t13g2.forum.logic.commands; + +import org.junit.Before; +import org.junit.Test; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.testutil.TypicalIndexes; +import com.t13g2.forum.testutil.TypicalPersons; + +/** + * Contains integration tests (interaction with the Model) and unit tests for ListCommand. + */ +public class ListCommandTest { + + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_listIsNotFiltered_showsSameList() { + CommandTestUtil.assertCommandSuccess(new ListCommand(), model, commandHistory, + ListCommand.MESSAGE_SUCCESS, expectedModel); + } + + @Test + public void execute_listIsFiltered_showsEverything() { + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); + CommandTestUtil.assertCommandSuccess(new ListCommand(), model, commandHistory, + ListCommand.MESSAGE_SUCCESS, expectedModel); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/ListModuleCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/ListModuleCommandTest.java new file mode 100644 index 000000000000..b3274dde524f --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/ListModuleCommandTest.java @@ -0,0 +1,75 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.util.DisplayFormatter; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + +//@@author HansKoh +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ListModuleCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_userLoggedInListModule_listModuleSuccess() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + String message = ""; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + List moduleList = unitOfWork.getModuleRepository().getAllModule(); + message = DisplayFormatter.displayModuleList(moduleList); + } catch (Exception e) { + e.printStackTrace(); + } + ListModuleCommand listModuleCommand = new ListModuleCommand(); + + CommandTestUtil.assertCommandSuccess(listModuleCommand, model, commandHistory, + String.format(listModuleCommand.MESSAGE_SUCCESS, message), expectedModel); + } + + @Test + public void execute_notLoggedInListModule_listModuleFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + ListModuleCommand listModuleCommand = new ListModuleCommand(); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = listModuleCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/LogoutCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/LogoutCommandTest.java new file mode 100644 index 000000000000..3fed897bf343 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/LogoutCommandTest.java @@ -0,0 +1,68 @@ +package com.t13g2.forum.logic.commands; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class LogoutCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullModuleCode_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new LoginCommand(null, null); + } + + @Test + public void execute_userActive_logoutSuccess() { + //set the current logged in user as an user. + User loggedInUser = TypicalUsers.JOSH; + Context.getInstance().setCurrentUser(loggedInUser); + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getUserRepository().addUser(loggedInUser); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + LogoutCommand logoutCommand = new LogoutCommand(); + + CommandTestUtil.assertCommandSuccess(logoutCommand, model, commandHistory, + String.format(LogoutCommand.MESSAGE_SUCCESS , loggedInUser.getUsername()), expectedModel); + } + + @Test + public void execute_invalidUserNameAndValidUserPassword_loginFailed() { + //set the current logged in user as an user. + Context.getInstance().setCurrentUser(null); + + LogoutCommand logoutCommand = new LogoutCommand(); + + CommandTestUtil.assertCommandSuccess(logoutCommand, model, commandHistory, + LogoutCommand.MESSAGE_FAIL, expectedModel); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/RedoCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/RedoCommandTest.java new file mode 100644 index 000000000000..3db9917fac3a --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/RedoCommandTest.java @@ -0,0 +1,47 @@ +package com.t13g2.forum.logic.commands; + +import org.junit.Before; +import org.junit.Test; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.testutil.TypicalPersons; + +public class RedoCommandTest { + + private final Model model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + private final Model expectedModel = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + private final CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + // set up of both models' undo/redo history + CommandTestUtil.deleteFirstPerson(model); + CommandTestUtil.deleteFirstPerson(model); + model.undoForumBook(); + model.undoForumBook(); + + CommandTestUtil.deleteFirstPerson(expectedModel); + CommandTestUtil.deleteFirstPerson(expectedModel); + expectedModel.undoForumBook(); + expectedModel.undoForumBook(); + } + + @Test + public void execute() { + // multiple redoable states in model + expectedModel.redoForumBook(); + CommandTestUtil.assertCommandSuccess(new RedoCommand(), model, commandHistory, + RedoCommand.MESSAGE_SUCCESS, expectedModel); + + // single redoable state in model + expectedModel.redoForumBook(); + CommandTestUtil.assertCommandSuccess(new RedoCommand(), model, commandHistory, + RedoCommand.MESSAGE_SUCCESS, expectedModel); + + // no redoable state in model + CommandTestUtil.assertCommandFailure(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_FAILURE); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/SelectModuleCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/SelectModuleCommandTest.java new file mode 100644 index 000000000000..34400cf2c141 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/SelectModuleCommandTest.java @@ -0,0 +1,105 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.util.DisplayFormatter; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + +//@@author HansKoh +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class SelectModuleCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_userLoggedInSelectModule_selectModuleSuccess() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS2113; + String message = ""; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + Module module = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()); + List threadList = unitOfWork.getForumThreadRepository().getThreadsByModule(module); + message = DisplayFormatter.diplayThreadList(threadList); + + } catch (Exception e) { + e.printStackTrace(); + } + String messageSuccess = "Listed all threads under Module Code: " + validModule.getModuleCode() + "\n" + + "****************************************************************************\n" + + "****************************************************************************\n" + + "%s"; + + SelectModuleCommand selectModuleCommand = new SelectModuleCommand(validModule.getModuleCode()); + + CommandTestUtil.assertCommandSuccess(selectModuleCommand, model, commandHistory, + String.format(messageSuccess, message), expectedModel); + + } + + @Test + public void execute_userLoggedInInvalidModule_selectModuleFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + String invalidModule = "AB1234"; + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_INVALID_MODULE_CODE); + + SelectModuleCommand selectModuleCommand = new SelectModuleCommand(invalidModule); + + CommandResult commandResult = selectModuleCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_INVALID_MODULE_CODE, commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedInSelectModule_selectModuleFail() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.CS2113; + SelectModuleCommand selectModuleCommand = new SelectModuleCommand(validModule.getModuleCode()); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = selectModuleCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/SelectThreadCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/SelectThreadCommandTest.java new file mode 100644 index 000000000000..d65edda2d56e --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/SelectThreadCommandTest.java @@ -0,0 +1,125 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.logic.util.DisplayFormatter; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.CommentBuilder; +import com.t13g2.forum.testutil.ForumThreadBuilder; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + +//@@author HansKoh +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class SelectThreadCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_userLoggedInSelectThread_selectThreadSuccess() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int threadId = 0; + String mCode = validModule.getModuleCode(); + String tTitle = ""; + String message = ""; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + + CreateCommentCommand createCommentCommand = + new CreateCommentCommand(forumThread.getId(), comment.getContent()); + createCommentCommand.execute(model, commandHistory); + List commentList = unitOfWork.getCommentRepository().getCommentsByThread(forumThread); + message = DisplayFormatter.displayCommentList(commentList); + threadId = forumThread.getId(); + tTitle = forumThread.getTitle(); + } catch (Exception e) { + e.printStackTrace(); + } + + SelectThreadCommand selectThreadCommand = new SelectThreadCommand(threadId); + String messageSuccess = "Listed all comments under \n" + + "Module Code: %s\n" + + "Thread ID : %s\n" + + "Thread Title : %s\n" + + "****************************************************************************\n" + + "****************************************************************************\n" + + "%s"; + CommandTestUtil.assertCommandSuccess(selectThreadCommand, model, commandHistory, + String.format(messageSuccess, mCode, threadId, tTitle, message), expectedModel); + + } + + @Test + public void execute_userLoggedInInvalidThreadId_selectThreadFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + int inValidThreadId = 8888; + SelectThreadCommand selectThreadCommand = new SelectThreadCommand(inValidThreadId); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_INVALID_THREAD_ID); + + CommandResult commandResult = selectThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_INVALID_THREAD_ID, commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedInSelectThread_selectThreadFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.CS2113; + ForumThread forumThread = new ForumThreadBuilder().withModuleId(validModule.getId()).build(); + SelectThreadCommand selectThreadCommand = new SelectThreadCommand(forumThread.getId()); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = selectThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/SetAdminCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/SetAdminCommandTest.java new file mode 100644 index 000000000000..1c3f7e6b37a0 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/SetAdminCommandTest.java @@ -0,0 +1,155 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; +import com.t13g2.forum.testutil.UserBuilder; + +//@@author xllx1 +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class SetAdminCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_adminAndDuplicateRevert_setAdminFailed() throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + User toSet = TypicalUsers.JONE; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getUserRepository().addUser(toSet); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + SetAdminCommand setAdminCommand = new SetAdminCommand(toSet.getUsername(), false); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(SetAdminCommand.MESSAGE_DUPLICATE_REVERT, toSet.getUsername())); + + CommandResult commandResult = setAdminCommand.execute(model, commandHistory); + assertEquals(String.format(SetAdminCommand.MESSAGE_DUPLICATE_REVERT, + toSet.getUsername()), commandResult.feedbackToUser); + } + + @Test + public void execute_adminAndRevertYourself_setAdminFailed() { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getUserRepository().addUser(validAdmin); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + SetAdminCommand setAdminCommand = new SetAdminCommand(validAdmin.getUsername(), false); + + CommandTestUtil.assertCommandSuccess(setAdminCommand, model, commandHistory, + SetAdminCommand.MESSAGE_FAILED, expectedModel); + } + + @Test + public void execute_adminAndValidUser_setAdminSuccess() { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + User toSet = TypicalUsers.JONE; + SetAdminCommand setAdminCommand = new SetAdminCommand(toSet.getUsername(), true); + + CommandTestUtil.assertCommandSuccess(setAdminCommand, model, commandHistory, + String.format(SetAdminCommand.MESSAGE_SUCCESS, toSet.getUsername(), "an admin"), expectedModel); + } + + @Test + public void execute_adminDuplicateSet_setAdminFailed() throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + User toSet = TypicalUsers.JONE; + SetAdminCommand setAdminCommand = new SetAdminCommand(toSet.getUsername(), true); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(SetAdminCommand.MESSAGE_DUPLICATE_SET, toSet.getUsername())); + + CommandResult commandResult = setAdminCommand.execute(model, commandHistory); + assertEquals(String.format(SetAdminCommand.MESSAGE_DUPLICATE_SET, + toSet.getUsername()), commandResult.feedbackToUser); + } + + @Test + public void execute_adminInvalidUserName_setAdminFailed() throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + SetAdminCommand setAdminCommand = new SetAdminCommand("abcd", true); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(BlockUserFromCreatingCommand.MESSAGE_INVALID_USER, "abcd")); + + CommandResult commandResult = setAdminCommand.execute(model, commandHistory); + assertEquals(String.format(SetAdminCommand.MESSAGE_INVALID_USER, "abcd"), + commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedIn_setAdminFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + User validUser = TypicalUsers.JONE; + SetAdminCommand setAdminCommand = new SetAdminCommand(validUser.getUsername(), false); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = setAdminCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedIn_setAdminFailed() throws Exception { + //set the current logged in user as null. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + SetAdminCommand setAdminCommand = new SetAdminCommand(validUser.getUsername(), false); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_ADMIN); + + CommandResult commandResult = setAdminCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_ADMIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/UndoCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/UndoCommandTest.java new file mode 100644 index 000000000000..496b3585d2b3 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/UndoCommandTest.java @@ -0,0 +1,43 @@ +package com.t13g2.forum.logic.commands; + +import org.junit.Before; +import org.junit.Test; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.testutil.TypicalPersons; + +public class UndoCommandTest { + + private final Model model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + private final Model expectedModel = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + private final CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + // set up of models' undo/redo history + CommandTestUtil.deleteFirstPerson(model); + CommandTestUtil.deleteFirstPerson(model); + + CommandTestUtil.deleteFirstPerson(expectedModel); + CommandTestUtil.deleteFirstPerson(expectedModel); + } + + @Test + public void execute() { + // multiple undoable states in model + expectedModel.undoForumBook(); + CommandTestUtil.assertCommandSuccess(new UndoCommand(), model, commandHistory, + UndoCommand.MESSAGE_SUCCESS, expectedModel); + + // single undoable state in model + expectedModel.undoForumBook(); + CommandTestUtil.assertCommandSuccess(new UndoCommand(), model, commandHistory, + UndoCommand.MESSAGE_SUCCESS, expectedModel); + + // no undoable states in model + CommandTestUtil.assertCommandFailure(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_FAILURE); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/UpdateCommentCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/UpdateCommentCommandTest.java new file mode 100644 index 000000000000..eb6c0280fde2 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/UpdateCommentCommandTest.java @@ -0,0 +1,170 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.CommentBuilder; +import com.t13g2.forum.testutil.ForumThreadBuilder; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + +//@@author HansKoh +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class UpdateCommentCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_userLoggedInUpdateComment_updateCommentSuccess() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int threadId = 0; + int commentId = 0; + + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(moduleId); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Context.getInstance().setCurrentThreadId(forumThread.getId()); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + commentId = comment.getId(); + threadId = forumThread.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + String cContentToUpdate = "new comment content"; + UpdateCommentCommand updateCommentCommand = new UpdateCommentCommand(commentId, cContentToUpdate); + String updateMessage = "\n\n" + + "Under Module Code: " + validModule.getModuleCode() + "\n" + + "Under Thread ID: " + threadId + "\n" + + "Updated Comment ID: " + commentId + "\n" + + "Updated Comment Content: " + cContentToUpdate + "\n"; + CommandTestUtil.assertCommandSuccess(updateCommentCommand, model, commandHistory, + String.format(updateCommentCommand.MESSAGE_SUCCESS, updateMessage), expectedModel); + } + + @Test + public void execute_userLoggedInNotCommentOwner_updateCommentFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int commentId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(moduleId); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Context.getInstance().setCurrentThreadId(forumThread.getId()); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + commentId = comment.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + Context.getInstance().setCurrentUser(TypicalUsers.JIM); + String cContentToUpdate = "new comment content"; + UpdateCommentCommand updateCommentCommand = new UpdateCommentCommand(commentId, cContentToUpdate); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_COMMENT_OWNER); + + CommandResult commandResult = updateCommentCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_COMMENT_OWNER, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedInNotUnderCurrentScope_updateCommentFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int commentId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(validModule.getId()); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Context.getInstance().setCurrentThreadId(8888); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + commentId = comment.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + String cContentToUpdate = "new comment content"; + UpdateCommentCommand updateCommentCommand = new UpdateCommentCommand(commentId, cContentToUpdate); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_INVALID_COMMENT); + + CommandResult commandResult = updateCommentCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_INVALID_COMMENT, commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedInDeleteComment_deleteCommentFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.CS1231; + ForumThread forumThread = new ForumThreadBuilder().withModuleId(validModule.getId()).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + String cContentToUpdate = "new comment content"; + UpdateCommentCommand updateCommentCommand = new UpdateCommentCommand(comment.getThreadId(), cContentToUpdate); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = updateCommentCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/UpdateModuleCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/UpdateModuleCommandTest.java new file mode 100644 index 000000000000..c77f8e6d8d05 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/UpdateModuleCommandTest.java @@ -0,0 +1,115 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; +import com.t13g2.forum.testutil.UserBuilder; + +//@@author xllx1 +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class UpdateModuleCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullModule_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new CreateModuleCommand(null); + } + + @Test + public void execute_adminAndUpdateValidModuleId_updateModuleSuccess() { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + Module validModule = TypicalModules.CS1111; + int moduleId = 0; + String updatedTitle = "CS module"; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + moduleId = unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + UpdateModuleCommand updateModuleCommand = new UpdateModuleCommand(moduleId, "", updatedTitle); + + CommandTestUtil.assertCommandSuccess(updateModuleCommand, model, commandHistory, + String.format(UpdateModuleCommand.MESSAGE_SUCCESS, validModule.getModuleCode(), + updatedTitle), expectedModel); + } + + @Test + public void execute_adminAndUpdateInvalidModuleId_updateModuleFailed() throws Exception { + //set the current logged in user as an admin. + User validAdmin = new UserBuilder().build(); + Context.getInstance().setCurrentUser(validAdmin); + + Module validModule = TypicalModules.GET1020; + int invalidModuleId = 999999999; + UpdateModuleCommand updateModuleCommand = new UpdateModuleCommand(invalidModuleId, "", "Darwin"); + + thrown.expect(CommandException.class); + thrown.expectMessage(String.format(UpdateModuleCommand.MESSAGE_INVALID_MODULE_ID, invalidModuleId)); + + CommandResult commandResult = updateModuleCommand.execute(model, commandHistory); + assertEquals(String.format(UpdateModuleCommand.MESSAGE_INVALID_MODULE_ID, + invalidModuleId), commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedIn_updateModuleFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + UpdateModuleCommand updateModuleCommand = new UpdateModuleCommand(1, "GET1020", "Darwin"); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = updateModuleCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + } + + @Test + public void execute_userLoggedIn_createModuleFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + UpdateModuleCommand updateModuleCommand = new UpdateModuleCommand(1, "GET1002", ""); + + thrown.expect(CommandException.class); + thrown.expectMessage(User.MESSAGE_NOT_ADMIN); + + CommandResult commandResult = updateModuleCommand.execute(model, commandHistory); + assertEquals(User.MESSAGE_NOT_ADMIN, commandResult.feedbackToUser); + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/UpdateThreadCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/UpdateThreadCommandTest.java new file mode 100644 index 000000000000..8474e6eed982 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/UpdateThreadCommandTest.java @@ -0,0 +1,168 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.commons.core.Messages; +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.logic.commands.exceptions.CommandException; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.CommentBuilder; +import com.t13g2.forum.testutil.ForumThreadBuilder; +import com.t13g2.forum.testutil.TypicalModules; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + +//@@author HansKoh +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class UpdateThreadCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void execute_userLoggedInUpdateThread_updateThreadSuccess() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int threadId = 0; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(moduleId); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + threadId = forumThread.getId(); + } catch (Exception e) { + e.printStackTrace(); + } + String threadTitleToUpdate = "new thread title"; + UpdateThreadCommand updateThreadCommand = new UpdateThreadCommand(threadId, threadTitleToUpdate); + String updateMessage = "\n\n" + + "Under Module Code: " + validModule.getModuleCode() + "\n" + + "Updated Thread ID: " + threadId + "\n" + + "Updated Thread Title: " + threadTitleToUpdate + "\n"; + + CommandTestUtil.assertCommandSuccess(updateThreadCommand, model, commandHistory, + String.format(updateThreadCommand.MESSAGE_SUCCESS, updateMessage), expectedModel); + + } + + @Test + public void execute_userLoggedInNotThreadOwner_updateThreadFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int threadId = 0; + String tTitle = ""; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(moduleId); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + threadId = forumThread.getId(); + tTitle = forumThread.getTitle(); + } catch (Exception e) { + e.printStackTrace(); + } + Context.getInstance().setCurrentUser(TypicalUsers.JIM); + UpdateThreadCommand updateThreadCommand = new UpdateThreadCommand(threadId, tTitle); + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_THREAD_OWNER); + + CommandResult commandResult = updateThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_THREAD_OWNER, commandResult.feedbackToUser); + + } + + @Test + public void execute_userLoggedInNotUnderCurrentScope_updateThreadFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + Module validModule = TypicalModules.CS1231; + int moduleId = 0; + int threadId = 0; + String tTitle = ""; + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getModuleRepository().addModule(validModule); + unitOfWork.commit(); + moduleId = unitOfWork.getModuleRepository().getModuleByCode(validModule.getModuleCode()).getId(); + Context.getInstance().setCurrentModuleId(8888); + ForumThread forumThread = new ForumThreadBuilder().withModuleId(moduleId).build(); + Comment comment = new CommentBuilder().withThreadId(forumThread.getId()).build(); + + CreateThreadCommand createThreadCommand = + new CreateThreadCommand(validModule.getModuleCode(), forumThread, comment); + createThreadCommand.execute(model, commandHistory); + threadId = forumThread.getId(); + tTitle = forumThread.getTitle(); + } catch (Exception e) { + e.printStackTrace(); + } + UpdateThreadCommand updateThreadCommand = new UpdateThreadCommand(threadId, tTitle); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_INVALID_THREAD); + + CommandResult commandResult = updateThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_INVALID_THREAD, commandResult.feedbackToUser); + } + + @Test + public void execute_notLoggedInDeleteThread_deleteThreadFailed() throws Exception { + //set the current logged in user as null. + Context.getInstance().setCurrentUser(null); + + Module validModule = TypicalModules.CS1231; + ForumThread forumThread = new ForumThreadBuilder().withModuleId(validModule.getId()).build(); + UpdateThreadCommand updateThreadCommand = + new UpdateThreadCommand(forumThread.getId(), forumThread.getTitle()); + + thrown.expect(CommandException.class); + thrown.expectMessage(Messages.MESSAGE_NOT_LOGIN); + + CommandResult commandResult = updateThreadCommand.execute(model, commandHistory); + assertEquals(Messages.MESSAGE_NOT_LOGIN, commandResult.feedbackToUser); + + } +} diff --git a/src/test/java/com/t13g2/forum/logic/commands/UserLoginCommandTest.java b/src/test/java/com/t13g2/forum/logic/commands/UserLoginCommandTest.java new file mode 100644 index 000000000000..83c54999c094 --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/commands/UserLoginCommandTest.java @@ -0,0 +1,89 @@ +package com.t13g2.forum.logic.commands; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; + +import com.t13g2.forum.logic.CommandHistory; +import com.t13g2.forum.model.Context; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.ModelManager; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.testutil.TypicalUsers; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class UserLoginCommandTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private Model model; + private Model expectedModel; + private CommandHistory commandHistory = new CommandHistory(); + + @Before + public void setUp() { + model = new ModelManager(TypicalPersons.getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getForumBook(), new UserPrefs()); + } + + @Test + public void constructor_nullModuleCode_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new LoginCommand(null, null); + } + + @Test + public void execute_validUserNameAndValidUserPassword_loginSuccess() { + //set the current logged in user as an admin. + Context.getInstance().setCurrentUser(null); + User validUser = new User("test user a", "pwd", false, false, "1@1.com", "12345678"); + try (UnitOfWork unitOfWork = new UnitOfWork()) { + unitOfWork.getUserRepository().addUser(validUser); + unitOfWork.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + LoginCommand loginCommand = + new LoginCommand(validUser.getUsername(), validUser.getPassword()); + + CommandTestUtil.assertCommandSuccess(loginCommand, model, commandHistory, + String.format(LoginCommand.MESSAGE_SUCCESS, validUser.getUsername()), expectedModel); + } + + @Test + public void execute_invalidUserNameAndValidUserPassword_loginFailed() throws Exception { + + String invalidUserName = "abcde"; + LoginCommand loginCommand = new LoginCommand(invalidUserName, "000"); + + //thrown.expect(CommandException.class); + thrown.expectMessage(String.format(LoginCommand.MESSAGE_FAIL, invalidUserName)); + + CommandResult commandResult = loginCommand.execute(model, commandHistory); + assertEquals(String.format(LoginCommand.MESSAGE_FAIL, + invalidUserName), commandResult.feedbackToUser); + } + + @Test + public void execute_attemptMultipleLogin_loginFailed() throws Exception { + //set the current logged in user as a user. + User validUser = TypicalUsers.JANEDOE; + Context.getInstance().setCurrentUser(validUser); + + User validUserToLogin = TypicalUsers.JOSH; + LoginCommand loginCommand = + new LoginCommand (validUserToLogin.getUsername(), validUserToLogin.getPassword()); + + CommandResult commandResult = loginCommand.execute(model, commandHistory); + assertEquals(String.format(LoginCommand.MESSAGE_USER_ACTIVE, + validUserToLogin.getUsername()), commandResult.feedbackToUser); + } +} diff --git a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java b/src/test/java/com/t13g2/forum/logic/parser/ArgumentTokenizerTest.java similarity index 99% rename from src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java rename to src/test/java/com/t13g2/forum/logic/parser/ArgumentTokenizerTest.java index 310eeee1863d..b04c410d5115 100644 --- a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java +++ b/src/test/java/com/t13g2/forum/logic/parser/ArgumentTokenizerTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java b/src/test/java/com/t13g2/forum/logic/parser/CommandParserTestUtil.java similarity index 88% rename from src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java rename to src/test/java/com/t13g2/forum/logic/parser/CommandParserTestUtil.java index 382360a85f8f..92c2783433d7 100644 --- a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java +++ b/src/test/java/com/t13g2/forum/logic/parser/CommandParserTestUtil.java @@ -1,9 +1,9 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; import static org.junit.Assert.assertEquals; -import seedu.address.logic.commands.Command; -import seedu.address.logic.parser.exceptions.ParseException; +import com.t13g2.forum.logic.commands.Command; +import com.t13g2.forum.logic.parser.exceptions.ParseException; /** * Contains helper methods for testing command parsers. diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/com/t13g2/forum/logic/parser/DeleteCommandParserTest.java similarity index 52% rename from src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java rename to src/test/java/com/t13g2/forum/logic/parser/DeleteCommandParserTest.java index 825732ced6ac..a36068e51157 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java +++ b/src/test/java/com/t13g2/forum/logic/parser/DeleteCommandParserTest.java @@ -1,13 +1,11 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import org.junit.Test; -import seedu.address.logic.commands.DeleteCommand; +import com.t13g2.forum.logic.commands.DeleteCommand; +import com.t13g2.forum.testutil.TypicalIndexes; /** * As we are only doing white-box testing, our test cases do not cover path variations @@ -22,11 +20,13 @@ public class DeleteCommandParserTest { @Test public void parse_validArgs_returnsDeleteCommand() { - assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_PERSON)); + CommandParserTestUtil.assertParseSuccess(parser, "1", + new DeleteCommand(TypicalIndexes.INDEX_FIRST_PERSON)); } @Test public void parse_invalidArgs_throwsParseException() { - assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + CommandParserTestUtil.assertParseFailure(parser, "a", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); } } diff --git a/src/test/java/com/t13g2/forum/logic/parser/FindCommandParserTest.java b/src/test/java/com/t13g2/forum/logic/parser/FindCommandParserTest.java new file mode 100644 index 000000000000..565e8aa8fccc --- /dev/null +++ b/src/test/java/com/t13g2/forum/logic/parser/FindCommandParserTest.java @@ -0,0 +1,33 @@ +package com.t13g2.forum.logic.parser; + +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + +import java.util.Arrays; + +import org.junit.Test; + +import com.t13g2.forum.logic.commands.FindCommand; +import com.t13g2.forum.model.person.NameContainsKeywordsPredicate; + +public class FindCommandParserTest { + + private FindCommandParser parser = new FindCommandParser(); + + @Test + public void parse_emptyArg_throwsParseException() { + CommandParserTestUtil.assertParseFailure(parser, " ", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); + } + + @Test + public void parse_validArgs_returnsFindCommand() { + // no leading and trailing whitespaces + FindCommand expectedFindCommand = + new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"))); + CommandParserTestUtil.assertParseSuccess(parser, "Alice Bob", expectedFindCommand); + + // multiple whitespaces between keywords + CommandParserTestUtil.assertParseSuccess(parser, " \n Alice \n \t Bob \t", expectedFindCommand); + } + +} diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/com/t13g2/forum/logic/parser/ParserUtilTest.java similarity index 91% rename from src/test/java/seedu/address/logic/parser/ParserUtilTest.java rename to src/test/java/com/t13g2/forum/logic/parser/ParserUtilTest.java index 78fd9c877708..8e4315a141cc 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/com/t13g2/forum/logic/parser/ParserUtilTest.java @@ -1,11 +1,8 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; - import java.util.Arrays; import java.util.Collections; import java.util.HashSet; @@ -15,13 +12,14 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -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.tag.Tag; -import seedu.address.testutil.Assert; +import com.t13g2.forum.logic.parser.exceptions.ParseException; +import com.t13g2.forum.model.person.Address; +import com.t13g2.forum.model.person.Email; +import com.t13g2.forum.model.person.Name; +import com.t13g2.forum.model.person.Phone; +import com.t13g2.forum.model.tag.Tag; +import com.t13g2.forum.testutil.Assert; +import com.t13g2.forum.testutil.TypicalIndexes; public class ParserUtilTest { private static final String INVALID_NAME = "R@chel"; @@ -51,17 +49,17 @@ public void parseIndex_invalidInput_throwsParseException() throws Exception { @Test public void parseIndex_outOfRangeInput_throwsParseException() throws Exception { thrown.expect(ParseException.class); - thrown.expectMessage(MESSAGE_INVALID_INDEX); + thrown.expectMessage(ParserUtil.MESSAGE_INVALID_INDEX); ParserUtil.parseIndex(Long.toString(Integer.MAX_VALUE + 1)); } @Test public void parseIndex_validInput_success() throws Exception { // No whitespaces - assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex("1")); + assertEquals(TypicalIndexes.INDEX_FIRST_PERSON, ParserUtil.parseIndex("1")); // Leading and trailing whitespaces - assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 ")); + assertEquals(TypicalIndexes.INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 ")); } @Test diff --git a/src/test/java/seedu/address/logic/parser/SelectCommandParserTest.java b/src/test/java/com/t13g2/forum/logic/parser/SelectCommandParserTest.java similarity index 50% rename from src/test/java/seedu/address/logic/parser/SelectCommandParserTest.java rename to src/test/java/com/t13g2/forum/logic/parser/SelectCommandParserTest.java index 513ee46acd33..e4a36d60c4e4 100644 --- a/src/test/java/seedu/address/logic/parser/SelectCommandParserTest.java +++ b/src/test/java/com/t13g2/forum/logic/parser/SelectCommandParserTest.java @@ -1,13 +1,13 @@ -package seedu.address.logic.parser; +package com.t13g2.forum.logic.parser; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static com.t13g2.forum.logic.parser.CommandParserTestUtil.assertParseFailure; +import static com.t13g2.forum.logic.parser.CommandParserTestUtil.assertParseSuccess; import org.junit.Test; -import seedu.address.logic.commands.SelectCommand; +import com.t13g2.forum.logic.commands.SelectCommand; +import com.t13g2.forum.testutil.TypicalIndexes; /** * Test scope: similar to {@code DeleteCommandParserTest}. @@ -19,7 +19,7 @@ public class SelectCommandParserTest { @Test public void parse_validArgs_returnsSelectCommand() { - assertParseSuccess(parser, "1", new SelectCommand(INDEX_FIRST_PERSON)); + assertParseSuccess(parser, "1", new SelectCommand(TypicalIndexes.INDEX_FIRST_PERSON)); } @Test diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/com/t13g2/forum/model/AddressBookTest.java similarity index 61% rename from src/test/java/seedu/address/model/AddressBookTest.java rename to src/test/java/com/t13g2/forum/model/AddressBookTest.java index 0d33cff49ab1..37a75023c374 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/com/t13g2/forum/model/AddressBookTest.java @@ -1,12 +1,10 @@ -package seedu.address.model; +package com.t13g2.forum.model; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import java.util.Arrays; import java.util.Collection; @@ -17,18 +15,20 @@ import org.junit.Test; import org.junit.rules.ExpectedException; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.model.person.exceptions.DuplicatePersonException; +import com.t13g2.forum.testutil.PersonBuilder; +import com.t13g2.forum.testutil.TypicalPersons; + import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.testutil.PersonBuilder; public class AddressBookTest { @Rule public ExpectedException thrown = ExpectedException.none(); - private final AddressBook addressBook = new AddressBook(); + private final ForumBook addressBook = new ForumBook(); @Test public void constructor() { @@ -43,7 +43,7 @@ public void resetData_null_throwsNullPointerException() { @Test public void resetData_withValidReadOnlyAddressBook_replacesData() { - AddressBook newData = getTypicalAddressBook(); + ForumBook newData = TypicalPersons.getTypicalAddressBook(); addressBook.resetData(newData); assertEquals(newData, addressBook); } @@ -51,10 +51,11 @@ public void resetData_withValidReadOnlyAddressBook_replacesData() { @Test public void resetData_withDuplicatePersons_throwsDuplicatePersonException() { // Two persons with the same identity fields - Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) + Person editedAlice = new PersonBuilder(TypicalPersons.ALICE).withAddress(VALID_ADDRESS_BOB) + .withTags(VALID_TAG_HUSBAND) .build(); - List newPersons = Arrays.asList(ALICE, editedAlice); - AddressBookStub newData = new AddressBookStub(newPersons); + List newPersons = Arrays.asList(TypicalPersons.ALICE, editedAlice); + ForumBookStub newData = new ForumBookStub(newPersons); thrown.expect(DuplicatePersonException.class); addressBook.resetData(newData); @@ -68,19 +69,20 @@ public void hasPerson_nullPerson_throwsNullPointerException() { @Test public void hasPerson_personNotInAddressBook_returnsFalse() { - assertFalse(addressBook.hasPerson(ALICE)); + assertFalse(addressBook.hasPerson(TypicalPersons.ALICE)); } @Test public void hasPerson_personInAddressBook_returnsTrue() { - addressBook.addPerson(ALICE); - assertTrue(addressBook.hasPerson(ALICE)); + addressBook.addPerson(TypicalPersons.ALICE); + assertTrue(addressBook.hasPerson(TypicalPersons.ALICE)); } @Test public void hasPerson_personWithSameIdentityFieldsInAddressBook_returnsTrue() { - addressBook.addPerson(ALICE); - Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) + addressBook.addPerson(TypicalPersons.ALICE); + Person editedAlice = new PersonBuilder(TypicalPersons.ALICE).withAddress(VALID_ADDRESS_BOB) + .withTags(VALID_TAG_HUSBAND) .build(); assertTrue(addressBook.hasPerson(editedAlice)); } @@ -92,12 +94,12 @@ public void getPersonList_modifyList_throwsUnsupportedOperationException() { } /** - * A stub ReadOnlyAddressBook whose persons list can violate interface constraints. + * A stub ReadOnlyForumBook whose persons list can violate interface constraints. */ - private static class AddressBookStub implements ReadOnlyAddressBook { + private static class ForumBookStub implements ReadOnlyForumBook { private final ObservableList persons = FXCollections.observableArrayList(); - AddressBookStub(Collection persons) { + ForumBookStub(Collection persons) { this.persons.setAll(persons); } diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/com/t13g2/forum/model/ModelManagerTest.java similarity index 73% rename from src/test/java/seedu/address/model/ModelManagerTest.java rename to src/test/java/com/t13g2/forum/model/ModelManagerTest.java index 7eab39d5de43..f7b6d397019b 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/com/t13g2/forum/model/ModelManagerTest.java @@ -1,10 +1,8 @@ -package seedu.address.model; +package com.t13g2.forum.model; +import static com.t13g2.forum.model.Model.PREDICATE_SHOW_ALL_PERSONS; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.BENSON; import java.nio.file.Paths; import java.util.Arrays; @@ -13,8 +11,9 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.testutil.AddressBookBuilder; +import com.t13g2.forum.model.person.NameContainsKeywordsPredicate; +import com.t13g2.forum.testutil.AddressBookBuilder; +import com.t13g2.forum.testutil.TypicalPersons; public class ModelManagerTest { @Rule @@ -30,13 +29,13 @@ public void hasPerson_nullPerson_throwsNullPointerException() { @Test public void hasPerson_personNotInAddressBook_returnsFalse() { - assertFalse(modelManager.hasPerson(ALICE)); + assertFalse(modelManager.hasPerson(TypicalPersons.ALICE)); } @Test public void hasPerson_personInAddressBook_returnsTrue() { - modelManager.addPerson(ALICE); - assertTrue(modelManager.hasPerson(ALICE)); + modelManager.addPerson(TypicalPersons.ALICE); + assertTrue(modelManager.hasPerson(TypicalPersons.ALICE)); } @Test @@ -47,8 +46,9 @@ public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException @Test public void equals() { - AddressBook addressBook = new AddressBookBuilder().withPerson(ALICE).withPerson(BENSON).build(); - AddressBook differentAddressBook = new AddressBook(); + ForumBook addressBook = new AddressBookBuilder() + .withPerson(TypicalPersons.ALICE).withPerson(TypicalPersons.BENSON).build(); + ForumBook differentAddressBook = new ForumBook(); UserPrefs userPrefs = new UserPrefs(); // same values -> returns true @@ -69,7 +69,7 @@ public void equals() { assertFalse(modelManager.equals(new ModelManager(differentAddressBook, userPrefs))); // different filteredList -> returns false - String[] keywords = ALICE.getName().fullName.split("\\s+"); + String[] keywords = TypicalPersons.ALICE.getName().fullName.split("\\s+"); modelManager.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(keywords))); assertFalse(modelManager.equals(new ModelManager(addressBook, userPrefs))); @@ -78,7 +78,7 @@ public void equals() { // different userPrefs -> returns true UserPrefs differentUserPrefs = new UserPrefs(); - differentUserPrefs.setAddressBookFilePath(Paths.get("differentFilePath")); + differentUserPrefs.setForumBookFilePath(Paths.get("differentFilePath")); assertTrue(modelManager.equals(new ModelManager(addressBook, differentUserPrefs))); } } diff --git a/src/test/java/seedu/address/model/VersionedAddressBookTest.java b/src/test/java/com/t13g2/forum/model/VersionedAddressBookTest.java similarity index 66% rename from src/test/java/seedu/address/model/VersionedAddressBookTest.java rename to src/test/java/com/t13g2/forum/model/VersionedAddressBookTest.java index d5a31a48e53f..7533c2cbbca9 100644 --- a/src/test/java/seedu/address/model/VersionedAddressBookTest.java +++ b/src/test/java/com/t13g2/forum/model/VersionedAddressBookTest.java @@ -1,12 +1,9 @@ -package seedu.address.model; +package com.t13g2.forum.model; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.jupiter.api.Assertions.assertThrows; -import static seedu.address.testutil.TypicalPersons.AMY; -import static seedu.address.testutil.TypicalPersons.BOB; -import static seedu.address.testutil.TypicalPersons.CARL; import java.util.Arrays; import java.util.Collections; @@ -14,18 +11,23 @@ import org.junit.Test; -import seedu.address.testutil.AddressBookBuilder; +import com.t13g2.forum.testutil.AddressBookBuilder; +import com.t13g2.forum.testutil.TypicalPersons; public class VersionedAddressBookTest { - private final ReadOnlyAddressBook addressBookWithAmy = new AddressBookBuilder().withPerson(AMY).build(); - private final ReadOnlyAddressBook addressBookWithBob = new AddressBookBuilder().withPerson(BOB).build(); - private final ReadOnlyAddressBook addressBookWithCarl = new AddressBookBuilder().withPerson(CARL).build(); - private final ReadOnlyAddressBook emptyAddressBook = new AddressBookBuilder().build(); + private final ReadOnlyForumBook addressBookWithAmy = + new AddressBookBuilder().withPerson(TypicalPersons.AMY).build(); + private final ReadOnlyForumBook addressBookWithBob = + new AddressBookBuilder().withPerson(TypicalPersons.BOB).build(); + private final ReadOnlyForumBook addressBookWithCarl = + new AddressBookBuilder().withPerson(TypicalPersons.CARL).build(); + private final ReadOnlyForumBook emptyAddressBook = + new AddressBookBuilder().build(); @Test public void commit_singleAddressBook_noStatesRemovedCurrentStateSaved() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); + VersionedForumBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); versionedAddressBook.commit(); assertAddressBookListStatus(versionedAddressBook, @@ -36,7 +38,7 @@ public void commit_singleAddressBook_noStatesRemovedCurrentStateSaved() { @Test public void commit_multipleAddressBookPointerAtEndOfStateList_noStatesRemovedCurrentStateSaved() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); versionedAddressBook.commit(); @@ -48,7 +50,7 @@ public void commit_multipleAddressBookPointerAtEndOfStateList_noStatesRemovedCur @Test public void commit_multipleAddressBookPointerNotAtEndOfStateList_statesAfterPointerRemovedCurrentStateSaved() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 2); @@ -61,7 +63,7 @@ public void commit_multipleAddressBookPointerNotAtEndOfStateList_statesAfterPoin @Test public void canUndo_multipleAddressBookPointerAtEndOfStateList_returnsTrue() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); assertTrue(versionedAddressBook.canUndo()); @@ -69,7 +71,7 @@ public void canUndo_multipleAddressBookPointerAtEndOfStateList_returnsTrue() { @Test public void canUndo_multipleAddressBookPointerAtStartOfStateList_returnsTrue() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 1); @@ -78,14 +80,14 @@ public void canUndo_multipleAddressBookPointerAtStartOfStateList_returnsTrue() { @Test public void canUndo_singleAddressBook_returnsFalse() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); + VersionedForumBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); assertFalse(versionedAddressBook.canUndo()); } @Test public void canUndo_multipleAddressBookPointerAtStartOfStateList_returnsFalse() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 2); @@ -94,7 +96,7 @@ public void canUndo_multipleAddressBookPointerAtStartOfStateList_returnsFalse() @Test public void canRedo_multipleAddressBookPointerNotAtEndOfStateList_returnsTrue() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 1); @@ -103,7 +105,7 @@ public void canRedo_multipleAddressBookPointerNotAtEndOfStateList_returnsTrue() @Test public void canRedo_multipleAddressBookPointerAtStartOfStateList_returnsTrue() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 2); @@ -112,14 +114,14 @@ public void canRedo_multipleAddressBookPointerAtStartOfStateList_returnsTrue() { @Test public void canRedo_singleAddressBook_returnsFalse() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); + VersionedForumBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); assertFalse(versionedAddressBook.canRedo()); } @Test public void canRedo_multipleAddressBookPointerAtEndOfStateList_returnsFalse() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); assertFalse(versionedAddressBook.canRedo()); @@ -127,7 +129,7 @@ public void canRedo_multipleAddressBookPointerAtEndOfStateList_returnsFalse() { @Test public void undo_multipleAddressBookPointerAtEndOfStateList_success() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); versionedAddressBook.undo(); @@ -139,7 +141,7 @@ public void undo_multipleAddressBookPointerAtEndOfStateList_success() { @Test public void undo_multipleAddressBookPointerNotAtStartOfStateList_success() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 1); @@ -152,23 +154,23 @@ public void undo_multipleAddressBookPointerNotAtStartOfStateList_success() { @Test public void undo_singleAddressBook_throwsNoUndoableStateException() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); + VersionedForumBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); - assertThrows(VersionedAddressBook.NoUndoableStateException.class, versionedAddressBook::undo); + assertThrows(VersionedForumBook.NoUndoableStateException.class, versionedAddressBook::undo); } @Test public void undo_multipleAddressBookPointerAtStartOfStateList_throwsNoUndoableStateException() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 2); - assertThrows(VersionedAddressBook.NoUndoableStateException.class, versionedAddressBook::undo); + assertThrows(VersionedForumBook.NoUndoableStateException.class, versionedAddressBook::undo); } @Test public void redo_multipleAddressBookPointerNotAtEndOfStateList_success() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 1); @@ -181,7 +183,7 @@ public void redo_multipleAddressBookPointerNotAtEndOfStateList_success() { @Test public void redo_multipleAddressBookPointerAtStartOfStateList_success() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 2); @@ -194,25 +196,25 @@ public void redo_multipleAddressBookPointerAtStartOfStateList_success() { @Test public void redo_singleAddressBook_throwsNoRedoableStateException() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); + VersionedForumBook versionedAddressBook = prepareAddressBookList(emptyAddressBook); - assertThrows(VersionedAddressBook.NoRedoableStateException.class, versionedAddressBook::redo); + assertThrows(VersionedForumBook.NoRedoableStateException.class, versionedAddressBook::redo); } @Test public void redo_multipleAddressBookPointerAtEndOfStateList_throwsNoRedoableStateException() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList( + VersionedForumBook versionedAddressBook = prepareAddressBookList( emptyAddressBook, addressBookWithAmy, addressBookWithBob); - assertThrows(VersionedAddressBook.NoRedoableStateException.class, versionedAddressBook::redo); + assertThrows(VersionedForumBook.NoRedoableStateException.class, versionedAddressBook::redo); } @Test public void equals() { - VersionedAddressBook versionedAddressBook = prepareAddressBookList(addressBookWithAmy, addressBookWithBob); + VersionedForumBook versionedAddressBook = prepareAddressBookList(addressBookWithAmy, addressBookWithBob); // same values -> returns true - VersionedAddressBook copy = prepareAddressBookList(addressBookWithAmy, addressBookWithBob); + VersionedForumBook copy = prepareAddressBookList(addressBookWithAmy, addressBookWithBob); assertTrue(versionedAddressBook.equals(copy)); // same object -> returns true @@ -225,11 +227,11 @@ public void equals() { assertFalse(versionedAddressBook.equals(1)); // different state list -> returns false - VersionedAddressBook differentAddressBookList = prepareAddressBookList(addressBookWithBob, addressBookWithCarl); + VersionedForumBook differentAddressBookList = prepareAddressBookList(addressBookWithBob, addressBookWithCarl); assertFalse(versionedAddressBook.equals(differentAddressBookList)); // different current pointer index -> returns false - VersionedAddressBook differentCurrentStatePointer = prepareAddressBookList( + VersionedForumBook differentCurrentStatePointer = prepareAddressBookList( addressBookWithAmy, addressBookWithBob); shiftCurrentStatePointerLeftwards(versionedAddressBook, 1); assertFalse(versionedAddressBook.equals(differentCurrentStatePointer)); @@ -240,12 +242,12 @@ public void equals() { * states before {@code versionedAddressBook#currentStatePointer} is equal to {@code expectedStatesBeforePointer}, * and states after {@code versionedAddressBook#currentStatePointer} is equal to {@code expectedStatesAfterPointer}. */ - private void assertAddressBookListStatus(VersionedAddressBook versionedAddressBook, - List expectedStatesBeforePointer, - ReadOnlyAddressBook expectedCurrentState, - List expectedStatesAfterPointer) { + private void assertAddressBookListStatus(VersionedForumBook versionedAddressBook, + List expectedStatesBeforePointer, + ReadOnlyForumBook expectedCurrentState, + List expectedStatesAfterPointer) { // check state currently pointing at is correct - assertEquals(new AddressBook(versionedAddressBook), expectedCurrentState); + assertEquals(new ForumBook(versionedAddressBook), expectedCurrentState); // shift pointer to start of state list while (versionedAddressBook.canUndo()) { @@ -253,15 +255,15 @@ private void assertAddressBookListStatus(VersionedAddressBook versionedAddressBo } // check states before pointer are correct - for (ReadOnlyAddressBook expectedAddressBook : expectedStatesBeforePointer) { - assertEquals(expectedAddressBook, new AddressBook(versionedAddressBook)); + for (ReadOnlyForumBook expectedAddressBook : expectedStatesBeforePointer) { + assertEquals(expectedAddressBook, new ForumBook(versionedAddressBook)); versionedAddressBook.redo(); } // check states after pointer are correct - for (ReadOnlyAddressBook expectedAddressBook : expectedStatesAfterPointer) { + for (ReadOnlyForumBook expectedAddressBook : expectedStatesAfterPointer) { versionedAddressBook.redo(); - assertEquals(expectedAddressBook, new AddressBook(versionedAddressBook)); + assertEquals(expectedAddressBook, new ForumBook(versionedAddressBook)); } // check that there are no more states after pointer @@ -272,13 +274,13 @@ private void assertAddressBookListStatus(VersionedAddressBook versionedAddressBo } /** - * Creates and returns a {@code VersionedAddressBook} with the {@code addressBookStates} added into it, and the - * {@code VersionedAddressBook#currentStatePointer} at the end of list. + * Creates and returns a {@code VersionedForumBook} with the {@code addressBookStates} added into it, and the + * {@code VersionedForumBook#currentStatePointer} at the end of list. */ - private VersionedAddressBook prepareAddressBookList(ReadOnlyAddressBook... addressBookStates) { + private VersionedForumBook prepareAddressBookList(ReadOnlyForumBook... addressBookStates) { assertFalse(addressBookStates.length == 0); - VersionedAddressBook versionedAddressBook = new VersionedAddressBook(addressBookStates[0]); + VersionedForumBook versionedAddressBook = new VersionedForumBook(addressBookStates[0]); for (int i = 1; i < addressBookStates.length; i++) { versionedAddressBook.resetData(addressBookStates[i]); versionedAddressBook.commit(); @@ -290,7 +292,7 @@ private VersionedAddressBook prepareAddressBookList(ReadOnlyAddressBook... addre /** * Shifts the {@code versionedAddressBook#currentStatePointer} by {@code count} to the left of its list. */ - private void shiftCurrentStatePointerLeftwards(VersionedAddressBook versionedAddressBook, int count) { + private void shiftCurrentStatePointerLeftwards(VersionedForumBook versionedAddressBook, int count) { for (int i = 0; i < count; i++) { versionedAddressBook.undo(); } diff --git a/src/test/java/seedu/address/model/person/AddressTest.java b/src/test/java/com/t13g2/forum/model/person/AddressTest.java similarity index 93% rename from src/test/java/seedu/address/model/person/AddressTest.java rename to src/test/java/com/t13g2/forum/model/person/AddressTest.java index 11974544d81d..85d5900c4726 100644 --- a/src/test/java/seedu/address/model/person/AddressTest.java +++ b/src/test/java/com/t13g2/forum/model/person/AddressTest.java @@ -1,11 +1,11 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; -import seedu.address.testutil.Assert; +import com.t13g2.forum.testutil.Assert; public class AddressTest { diff --git a/src/test/java/seedu/address/model/person/EmailTest.java b/src/test/java/com/t13g2/forum/model/person/EmailTest.java similarity index 97% rename from src/test/java/seedu/address/model/person/EmailTest.java rename to src/test/java/com/t13g2/forum/model/person/EmailTest.java index 10187e8eb884..235547cd8a71 100644 --- a/src/test/java/seedu/address/model/person/EmailTest.java +++ b/src/test/java/com/t13g2/forum/model/person/EmailTest.java @@ -1,11 +1,11 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; -import seedu.address.testutil.Assert; +import com.t13g2.forum.testutil.Assert; public class EmailTest { diff --git a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java b/src/test/java/com/t13g2/forum/model/person/NameContainsKeywordsPredicateTest.java similarity index 97% rename from src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java rename to src/test/java/com/t13g2/forum/model/person/NameContainsKeywordsPredicateTest.java index 76841215e3a0..fd478cb8e8dc 100644 --- a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java +++ b/src/test/java/com/t13g2/forum/model/person/NameContainsKeywordsPredicateTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -9,7 +9,7 @@ import org.junit.Test; -import seedu.address.testutil.PersonBuilder; +import com.t13g2.forum.testutil.PersonBuilder; public class NameContainsKeywordsPredicateTest { diff --git a/src/test/java/seedu/address/model/person/NameTest.java b/src/test/java/com/t13g2/forum/model/person/NameTest.java similarity index 94% rename from src/test/java/seedu/address/model/person/NameTest.java rename to src/test/java/com/t13g2/forum/model/person/NameTest.java index b4a356b6f011..84e10a05fdcd 100644 --- a/src/test/java/seedu/address/model/person/NameTest.java +++ b/src/test/java/com/t13g2/forum/model/person/NameTest.java @@ -1,11 +1,11 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; -import seedu.address.testutil.Assert; +import com.t13g2.forum.testutil.Assert; public class NameTest { diff --git a/src/test/java/com/t13g2/forum/model/person/PersonTest.java b/src/test/java/com/t13g2/forum/model/person/PersonTest.java new file mode 100644 index 000000000000..bb4153e5022a --- /dev/null +++ b/src/test/java/com/t13g2/forum/model/person/PersonTest.java @@ -0,0 +1,100 @@ +package com.t13g2.forum.model.person; + +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_PHONE_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import com.t13g2.forum.testutil.PersonBuilder; +import com.t13g2.forum.testutil.TypicalPersons; + +public class PersonTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void asObservableList_modifyList_throwsUnsupportedOperationException() { + Person person = new PersonBuilder().build(); + thrown.expect(UnsupportedOperationException.class); + person.getTags().remove(0); + } + + @Test + public void isSamePerson() { + // same object -> returns true + assertTrue(TypicalPersons.ALICE.isSamePerson(TypicalPersons.ALICE)); + + // null -> returns false + assertFalse(TypicalPersons.ALICE.isSamePerson(null)); + + // different phone and email -> returns false + Person editedAlice = new PersonBuilder(TypicalPersons.ALICE) + .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).build(); + assertFalse(TypicalPersons.ALICE.isSamePerson(editedAlice)); + + // different name -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withName(VALID_NAME_BOB).build(); + assertFalse(TypicalPersons.ALICE.isSamePerson(editedAlice)); + + // same name, same phone, different attributes -> returns true + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB) + .withTags(VALID_TAG_HUSBAND).build(); + assertTrue(TypicalPersons.ALICE.isSamePerson(editedAlice)); + + // same name, same email, different attributes -> returns true + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withPhone(VALID_PHONE_BOB).withAddress(VALID_ADDRESS_BOB) + .withTags(VALID_TAG_HUSBAND).build(); + assertTrue(TypicalPersons.ALICE.isSamePerson(editedAlice)); + + // same name, same phone, same email, different attributes -> returns true + editedAlice = new PersonBuilder(TypicalPersons.ALICE) + .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); + assertTrue(TypicalPersons.ALICE.isSamePerson(editedAlice)); + } + + @Test + public void equals() { + // same values -> returns true + Person aliceCopy = new PersonBuilder(TypicalPersons.ALICE).build(); + assertTrue(TypicalPersons.ALICE.equals(aliceCopy)); + + // same object -> returns true + assertTrue(TypicalPersons.ALICE.equals(TypicalPersons.ALICE)); + + // null -> returns false + assertFalse(TypicalPersons.ALICE.equals(null)); + + // different type -> returns false + assertFalse(TypicalPersons.ALICE.equals(5)); + + // different person -> returns false + assertFalse(TypicalPersons.ALICE.equals(TypicalPersons.BOB)); + + // different name -> returns false + Person editedAlice = new PersonBuilder(TypicalPersons.ALICE).withName(VALID_NAME_BOB).build(); + assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + + // different phone -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withPhone(VALID_PHONE_BOB).build(); + assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + + // different email -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withEmail(VALID_EMAIL_BOB).build(); + assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + + // different address -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withAddress(VALID_ADDRESS_BOB).build(); + assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + + // different tags -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withTags(VALID_TAG_HUSBAND).build(); + assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + } +} diff --git a/src/test/java/seedu/address/model/person/PhoneTest.java b/src/test/java/com/t13g2/forum/model/person/PhoneTest.java similarity index 94% rename from src/test/java/seedu/address/model/person/PhoneTest.java rename to src/test/java/com/t13g2/forum/model/person/PhoneTest.java index c721cbbfc048..7e15b0c11f33 100644 --- a/src/test/java/seedu/address/model/person/PhoneTest.java +++ b/src/test/java/com/t13g2/forum/model/person/PhoneTest.java @@ -1,11 +1,11 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; -import seedu.address.testutil.Assert; +import com.t13g2.forum.testutil.Assert; public class PhoneTest { diff --git a/src/test/java/seedu/address/model/person/UniquePersonListTest.java b/src/test/java/com/t13g2/forum/model/person/UniquePersonListTest.java similarity index 64% rename from src/test/java/seedu/address/model/person/UniquePersonListTest.java rename to src/test/java/com/t13g2/forum/model/person/UniquePersonListTest.java index 6389cd81703f..2b440a6dd609 100644 --- a/src/test/java/seedu/address/model/person/UniquePersonListTest.java +++ b/src/test/java/com/t13g2/forum/model/person/UniquePersonListTest.java @@ -1,12 +1,10 @@ -package seedu.address.model.person; +package com.t13g2.forum.model.person; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.BOB; import java.util.Arrays; import java.util.Collections; @@ -16,9 +14,10 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; -import seedu.address.testutil.PersonBuilder; +import com.t13g2.forum.model.person.exceptions.DuplicatePersonException; +import com.t13g2.forum.model.person.exceptions.PersonNotFoundException; +import com.t13g2.forum.testutil.PersonBuilder; +import com.t13g2.forum.testutil.TypicalPersons; public class UniquePersonListTest { @Rule @@ -34,19 +33,20 @@ public void contains_nullPerson_throwsNullPointerException() { @Test public void contains_personNotInList_returnsFalse() { - assertFalse(uniquePersonList.contains(ALICE)); + assertFalse(uniquePersonList.contains(TypicalPersons.ALICE)); } @Test public void contains_personInList_returnsTrue() { - uniquePersonList.add(ALICE); - assertTrue(uniquePersonList.contains(ALICE)); + uniquePersonList.add(TypicalPersons.ALICE); + assertTrue(uniquePersonList.contains(TypicalPersons.ALICE)); } @Test public void contains_personWithSameIdentityFieldsInList_returnsTrue() { - uniquePersonList.add(ALICE); - Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) + uniquePersonList.add(TypicalPersons.ALICE); + Person editedAlice = new PersonBuilder(TypicalPersons.ALICE) + .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) .build(); assertTrue(uniquePersonList.contains(editedAlice)); } @@ -59,44 +59,45 @@ public void add_nullPerson_throwsNullPointerException() { @Test public void add_duplicatePerson_throwsDuplicatePersonException() { - uniquePersonList.add(ALICE); + uniquePersonList.add(TypicalPersons.ALICE); thrown.expect(DuplicatePersonException.class); - uniquePersonList.add(ALICE); + uniquePersonList.add(TypicalPersons.ALICE); } @Test public void setPerson_nullTargetPerson_throwsNullPointerException() { thrown.expect(NullPointerException.class); - uniquePersonList.setPerson(null, ALICE); + uniquePersonList.setPerson(null, TypicalPersons.ALICE); } @Test public void setPerson_nullEditedPerson_throwsNullPointerException() { thrown.expect(NullPointerException.class); - uniquePersonList.setPerson(ALICE, null); + uniquePersonList.setPerson(TypicalPersons.ALICE, null); } @Test public void setPerson_targetPersonNotInList_throwsPersonNotFoundException() { thrown.expect(PersonNotFoundException.class); - uniquePersonList.setPerson(ALICE, ALICE); + uniquePersonList.setPerson(TypicalPersons.ALICE, TypicalPersons.ALICE); } @Test public void setPerson_editedPersonIsSamePerson_success() { - uniquePersonList.add(ALICE); - uniquePersonList.setPerson(ALICE, ALICE); + uniquePersonList.add(TypicalPersons.ALICE); + uniquePersonList.setPerson(TypicalPersons.ALICE, TypicalPersons.ALICE); UniquePersonList expectedUniquePersonList = new UniquePersonList(); - expectedUniquePersonList.add(ALICE); + expectedUniquePersonList.add(TypicalPersons.ALICE); assertEquals(expectedUniquePersonList, uniquePersonList); } @Test public void setPerson_editedPersonHasSameIdentity_success() { - uniquePersonList.add(ALICE); - Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) + uniquePersonList.add(TypicalPersons.ALICE); + Person editedAlice = new PersonBuilder(TypicalPersons.ALICE) + .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) .build(); - uniquePersonList.setPerson(ALICE, editedAlice); + uniquePersonList.setPerson(TypicalPersons.ALICE, editedAlice); UniquePersonList expectedUniquePersonList = new UniquePersonList(); expectedUniquePersonList.add(editedAlice); assertEquals(expectedUniquePersonList, uniquePersonList); @@ -104,19 +105,19 @@ public void setPerson_editedPersonHasSameIdentity_success() { @Test public void setPerson_editedPersonHasDifferentIdentity_success() { - uniquePersonList.add(ALICE); - uniquePersonList.setPerson(ALICE, BOB); + uniquePersonList.add(TypicalPersons.ALICE); + uniquePersonList.setPerson(TypicalPersons.ALICE, TypicalPersons.BOB); UniquePersonList expectedUniquePersonList = new UniquePersonList(); - expectedUniquePersonList.add(BOB); + expectedUniquePersonList.add(TypicalPersons.BOB); assertEquals(expectedUniquePersonList, uniquePersonList); } @Test public void setPerson_editedPersonHasNonUniqueIdentity_throwsDuplicatePersonException() { - uniquePersonList.add(ALICE); - uniquePersonList.add(BOB); + uniquePersonList.add(TypicalPersons.ALICE); + uniquePersonList.add(TypicalPersons.BOB); thrown.expect(DuplicatePersonException.class); - uniquePersonList.setPerson(ALICE, BOB); + uniquePersonList.setPerson(TypicalPersons.ALICE, TypicalPersons.BOB); } @Test @@ -128,13 +129,13 @@ public void remove_nullPerson_throwsNullPointerException() { @Test public void remove_personDoesNotExist_throwsPersonNotFoundException() { thrown.expect(PersonNotFoundException.class); - uniquePersonList.remove(ALICE); + uniquePersonList.remove(TypicalPersons.ALICE); } @Test public void remove_existingPerson_removesPerson() { - uniquePersonList.add(ALICE); - uniquePersonList.remove(ALICE); + uniquePersonList.add(TypicalPersons.ALICE); + uniquePersonList.remove(TypicalPersons.ALICE); UniquePersonList expectedUniquePersonList = new UniquePersonList(); assertEquals(expectedUniquePersonList, uniquePersonList); } @@ -147,9 +148,9 @@ public void setPersons_nullUniquePersonList_throwsNullPointerException() { @Test public void setPersons_uniquePersonList_replacesOwnListWithProvidedUniquePersonList() { - uniquePersonList.add(ALICE); + uniquePersonList.add(TypicalPersons.ALICE); UniquePersonList expectedUniquePersonList = new UniquePersonList(); - expectedUniquePersonList.add(BOB); + expectedUniquePersonList.add(TypicalPersons.BOB); uniquePersonList.setPersons(expectedUniquePersonList); assertEquals(expectedUniquePersonList, uniquePersonList); } @@ -162,17 +163,17 @@ public void setPersons_nullList_throwsNullPointerException() { @Test public void setPersons_list_replacesOwnListWithProvidedList() { - uniquePersonList.add(ALICE); - List personList = Collections.singletonList(BOB); + uniquePersonList.add(TypicalPersons.ALICE); + List personList = Collections.singletonList(TypicalPersons.BOB); uniquePersonList.setPersons(personList); UniquePersonList expectedUniquePersonList = new UniquePersonList(); - expectedUniquePersonList.add(BOB); + expectedUniquePersonList.add(TypicalPersons.BOB); assertEquals(expectedUniquePersonList, uniquePersonList); } @Test public void setPersons_listWithDuplicatePersons_throwsDuplicatePersonException() { - List listWithDuplicatePersons = Arrays.asList(ALICE, ALICE); + List listWithDuplicatePersons = Arrays.asList(TypicalPersons.ALICE, TypicalPersons.ALICE); thrown.expect(DuplicatePersonException.class); uniquePersonList.setPersons(listWithDuplicatePersons); } diff --git a/src/test/java/seedu/address/model/tag/TagTest.java b/src/test/java/com/t13g2/forum/model/tag/TagTest.java similarity index 88% rename from src/test/java/seedu/address/model/tag/TagTest.java rename to src/test/java/com/t13g2/forum/model/tag/TagTest.java index 80bfd156d816..9736eeefc0e7 100644 --- a/src/test/java/seedu/address/model/tag/TagTest.java +++ b/src/test/java/com/t13g2/forum/model/tag/TagTest.java @@ -1,8 +1,8 @@ -package seedu.address.model.tag; +package com.t13g2.forum.model.tag; import org.junit.Test; -import seedu.address.testutil.Assert; +import com.t13g2.forum.testutil.Assert; public class TagTest { diff --git a/src/test/java/com/t13g2/forum/storage/FileStorageTest.java b/src/test/java/com/t13g2/forum/storage/FileStorageTest.java new file mode 100644 index 000000000000..c5f0779efa7f --- /dev/null +++ b/src/test/java/com/t13g2/forum/storage/FileStorageTest.java @@ -0,0 +1,58 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage; + +import java.io.Serializable; + +import org.junit.Assert; +import org.junit.Test; + +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.storage.forum.AnnouncementStorage; +import com.t13g2.forum.storage.forum.IStorage; +import com.t13g2.forum.storage.forum.JsonFileStorage; +import com.t13g2.forum.storage.forum.StorageMapping; + +public class FileStorageTest { + @Test + public void readAndWrite() { + JsonFileStorage fileStorage = new JsonFileStorage(); + StorageMapping.getInstance().addMapping(DummyClass.class, "dummyClass"); + DummyClass dummy = new DummyClass(); + dummy.setName("hehe"); + fileStorage.write(dummy); + + DummyClass dummyFromDisk = fileStorage.read(DummyClass.class); + Assert.assertEquals(dummy.getName(), dummyFromDisk.getName()); + + } + + @Test + public void readWriteWithActualStorage() { + IStorage fileStorage = new JsonFileStorage(); + Announcement announcement = new Announcement("hey", "ha"); + AnnouncementStorage announcementStorage = new AnnouncementStorage(); + announcementStorage.getList().add(announcement); + fileStorage.write(announcementStorage); + + AnnouncementStorage readBack = fileStorage.read(AnnouncementStorage.class); + Announcement readBackAnnouncement = readBack.getList().get(0); + Assert.assertEquals(announcement.getId(), readBackAnnouncement.getId()); + Assert.assertEquals(announcement.getTitle(), readBackAnnouncement.getTitle()); + Assert.assertEquals(announcement.getContent(), readBackAnnouncement.getContent()); + + + } + + + static class DummyClass implements Serializable { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/src/test/java/com/t13g2/forum/storage/ForumBookStorageStub.java b/src/test/java/com/t13g2/forum/storage/ForumBookStorageStub.java new file mode 100644 index 000000000000..09aeec997625 --- /dev/null +++ b/src/test/java/com/t13g2/forum/storage/ForumBookStorageStub.java @@ -0,0 +1,116 @@ +package com.t13g2.forum.storage; + +import com.t13g2.forum.storage.forum.AnnouncementStorage; +import com.t13g2.forum.storage.forum.CommentStorage; +import com.t13g2.forum.storage.forum.ForumBookStorage; +import com.t13g2.forum.storage.forum.ForumThreadStorage; +import com.t13g2.forum.storage.forum.IForumBookStorage; +import com.t13g2.forum.storage.forum.IStorage; +import com.t13g2.forum.storage.forum.ModuleStorage; +import com.t13g2.forum.storage.forum.UserStorage; + +/** + * Defines a stub for ForumBookStorage + */ +public class ForumBookStorageStub implements IForumBookStorage { + private ForumBookStorage forumBookStorage; + + public ForumBookStorageStub(IStorage storage) { + forumBookStorage = new ForumBookStorage(storage); + } + + @Override + public void commit() { + forumBookStorage.commit(); + } + + @Override + public void save(Class clazz) { + forumBookStorage.save(clazz); + } + + @Override + public void load(Class clazz) { + forumBookStorage.load(clazz); + } + + @Override + public void saveAnnouncement() { + forumBookStorage.saveAnnouncement(); + } + + @Override + public void loadAnnouncement() { + forumBookStorage.loadAnnouncement(); + } + + @Override + public void saveComment() { + forumBookStorage.saveComment(); + } + + @Override + public void loadComment() { + forumBookStorage.loadComment(); + } + + @Override + public void saveForumThread() { + forumBookStorage.saveForumThread(); + } + + @Override + public void loadForumThread() { + forumBookStorage.loadForumThread(); + } + + @Override + public void saveUser() { + forumBookStorage.saveUser(); + } + + @Override + public void loadUser() { + forumBookStorage.loadUser(); + } + + @Override + public void saveModule() { + forumBookStorage.saveModule(); + } + + @Override + public void loadModule() { + forumBookStorage.loadModule(); + } + + @Override + public boolean isFresh() { + return forumBookStorage.isFresh(); + } + + @Override + public AnnouncementStorage getAnnouncements() { + return forumBookStorage.getAnnouncements(); + } + + @Override + public ForumThreadStorage getForumThreads() { + return forumBookStorage.getForumThreads(); + } + + @Override + public UserStorage getUsers() { + return forumBookStorage.getUsers(); + } + + @Override + public ModuleStorage getModules() { + return forumBookStorage.getModules(); + } + + @Override + public CommentStorage getComments() { + return forumBookStorage.getComments(); + } +} diff --git a/src/test/java/com/t13g2/forum/storage/ForumBookStorageTest.java b/src/test/java/com/t13g2/forum/storage/ForumBookStorageTest.java new file mode 100644 index 000000000000..d9dff0ec95a0 --- /dev/null +++ b/src/test/java/com/t13g2/forum/storage/ForumBookStorageTest.java @@ -0,0 +1,312 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.model.forum.Comment; +import com.t13g2.forum.model.forum.ForumThread; +import com.t13g2.forum.model.forum.Module; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.ForumBookStorage; +import com.t13g2.forum.testutil.ForumBookStorageBuilder; + +public class ForumBookStorageTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void announceInited() { + Assert.assertNotNull(new ForumBookStorageBuilder().build().getAnnouncements()); + } + + @Test + public void commentInited() { + Assert.assertNotNull(new ForumBookStorageBuilder().build().getComments()); + } + + @Test + public void threadInited() { + Assert.assertNotNull(new ForumBookStorageBuilder().build().getForumThreads()); + } + + @Test + public void userInited() { + Assert.assertNotNull(new ForumBookStorageBuilder().build().getUsers()); + } + + @Test + public void modulesInited() { + Assert.assertNotNull(new ForumBookStorageBuilder().build().getModules()); + } + + @Test + public void announcementTest() { + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + Announcement announcement = new Announcement("title", "content"); + + fs.getAnnouncements().getList().add(announcement); + fs.getAnnouncements().setDirty(); + fs.commit(); + + ForumBookStorage freshFs = builder.build(); + Assert.assertEquals(freshFs.getAnnouncements().getList().get(0).getId(), announcement.getId()); + Assert.assertEquals(freshFs.getAnnouncements().getList().get(0).getTitle(), announcement.getTitle()); + Assert.assertEquals(freshFs.getAnnouncements().getList().get(0).getContent(), announcement.getContent()); + } + + // @Test + // public void announcementNoDirty() { + // + // ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + // + // ForumBookStorage fs = builder.build(); + // Announcement announcement = new Announcement("title", "content"); + // + // fs.getAnnouncements().getList().add(announcement); + // fs.commit(); + // + // ForumBookStorage freshFs = builder.build(); + // thrown.expect(IndexOutOfBoundsException.class); + // freshFs.getAnnouncements().getList().get(0); + // } + + @Test + public void announcementNoCommit() { + + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + Announcement announcement = new Announcement("title", "content"); + + fs.getAnnouncements().getList().add(announcement); + fs.getAnnouncements().setDirty(); + + ForumBookStorage freshFs = builder.build(); + thrown.expect(IndexOutOfBoundsException.class); + freshFs.getAnnouncements().getList().get(0); + } + + @Test + public void commentTest() { + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + Comment comment = new Comment(); + comment.setContent("a"); + comment.setThreadId(5); + + fs.getComments().getList().add(comment); + fs.getComments().setDirty(); + fs.commit(); + + ForumBookStorage freshFs = builder.build(); + Assert.assertEquals(freshFs.getComments().getList().get(0).getId(), comment.getId()); + Assert.assertEquals(freshFs.getComments().getList().get(0).getContent(), comment.getContent()); + Assert.assertEquals(freshFs.getComments().getList().get(0).getThreadId(), comment.getThreadId()); + } + + @Test + public void commentNoCommit() { + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + Comment comment = new Comment(); + comment.setContent("a"); + comment.setThreadId(5); + + fs.getComments().getList().add(comment); + fs.getComments().setDirty(); + + + ForumBookStorage freshFs = builder.build(); + thrown.expect(IndexOutOfBoundsException.class); + freshFs.getComments().getList().get(0); + } + + // @Test + // public void commentNoDirty() { + // ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + // + // ForumBookStorage fs = builder.build(); + // Comment comment = new Comment(); + // comment.setContent("a"); + // comment.setThreadId(5); + // + // fs.getComments().getList().add(comment); + // fs.commit(); + // + // + // ForumBookStorage freshFs = builder.build(); + // thrown.expect(IndexOutOfBoundsException.class); + // freshFs.getComments().getList().get(0); + // } + + @Test + public void threadTest() { + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + ForumThread forumThread = new ForumThread(); + forumThread.setTitle("b"); + forumThread.setModuleId(6); + + fs.getForumThreads().getList().add(forumThread); + fs.getForumThreads().setDirty(); + fs.commit(); + + ForumBookStorage freshFs = builder.build(); + Assert.assertEquals(freshFs.getForumThreads().getList().get(0).getId(), forumThread.getId()); + Assert.assertEquals(freshFs.getForumThreads().getList().get(0).getTitle(), forumThread.getTitle()); + Assert.assertEquals(freshFs.getForumThreads().getList().get(0).getModuleId(), forumThread.getModuleId()); + } + + @Test + public void threadNoCommit() { + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + ForumThread forumThread = new ForumThread(); + forumThread.setTitle("b"); + forumThread.setModuleId(6); + + fs.getForumThreads().getList().add(forumThread); + fs.getForumThreads().setDirty(); + + + ForumBookStorage freshFs = builder.build(); + thrown.expect(IndexOutOfBoundsException.class); + freshFs.getForumThreads().getList().get(0); + } + + // @Test + // public void threadNoDirty() { + // ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + // + // ForumBookStorage fs = builder.build(); + // ForumThread forumThread = new ForumThread(); + // forumThread.setTitle("b"); + // forumThread.setModuleId(6); + // + // fs.getForumThreads().getList().add(forumThread); + // fs.commit(); + // + // + // ForumBookStorage freshFs = builder.build(); + // thrown.expect(IndexOutOfBoundsException.class); + // freshFs.getForumThreads().getList().get(0); + // } + + @Test + public void userTest() { + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + User user = new User(); + user.setUsername("uname"); + user.setPassword("hehe"); + + + fs.getUsers().getList().add(user); + fs.getUsers().setDirty(); + fs.commit(); + + ForumBookStorage freshFs = builder.build(); + Assert.assertEquals(freshFs.getUsers().getList().get(0).getId(), user.getId()); + Assert.assertEquals(freshFs.getUsers().getList().get(0).getUsername(), user.getUsername()); + Assert.assertEquals(freshFs.getUsers().getList().get(0).getPassword(), user.getPassword()); + + } + + @Test + public void userNoCommit() { + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + User user = new User(); + user.setUsername("uname"); + user.setPassword("hehe"); + + + fs.getUsers().getList().add(user); + fs.getUsers().setDirty(); + + + ForumBookStorage freshFs = builder.build(); + thrown.expect(IndexOutOfBoundsException.class); + freshFs.getUsers().getList().get(0); + } + + // @Test + // public void userNoDirty() { + // ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + // + // ForumBookStorage fs = builder.build(); + // User user = new User(); + // user.setUsername("uname"); + // user.setPassword("hehe"); + // + // + // fs.getUsers().getList().add(user); + // fs.commit(); + // + // ForumBookStorage freshFs = builder.build(); + // thrown.expect(IndexOutOfBoundsException.class); + // freshFs.getUsers().getList().get(0); + // } + + @Test + public void moduleTest() { + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + Module module = new Module("mTitle", "mCode"); + + + fs.getModules().getList().add(module); + fs.getModules().setDirty(); + fs.commit(); + + ForumBookStorage freshFs = builder.build(); + Assert.assertEquals(freshFs.getModules().getList().get(0).getId(), module.getId()); + Assert.assertEquals(freshFs.getModules().getList().get(0).getTitle(), module.getTitle()); + Assert.assertEquals(freshFs.getModules().getList().get(0).getModuleCode(), module.getModuleCode()); + } + + @Test + public void moduleNoCommit() { + ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + + ForumBookStorage fs = builder.build(); + Module module = new Module("mTitle", "mCode"); + + + fs.getModules().getList().add(module); + fs.getModules().setDirty(); + + ForumBookStorage freshFs = builder.build(); + thrown.expect(IndexOutOfBoundsException.class); + freshFs.getModules().getList().get(0); + } + + // @Test + // public void moduleNoDirty() { + // ForumBookStorageBuilder builder = new ForumBookStorageBuilder(); + // + // ForumBookStorage fs = builder.build(); + // Module module = new Module("mTitle", "mCode"); + // + // + // fs.getModules().getList().add(module); + // fs.commit(); + // + // ForumBookStorage freshFs = builder.build(); + // thrown.expect(IndexOutOfBoundsException.class); + // freshFs.getModules().getList().get(0); + // } +} diff --git a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java b/src/test/java/com/t13g2/forum/storage/JsonUserPrefsStorageTest.java similarity index 84% rename from src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java rename to src/test/java/com/t13g2/forum/storage/JsonUserPrefsStorageTest.java index 50334e4ad45d..458ae055e734 100644 --- a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java +++ b/src/test/java/com/t13g2/forum/storage/JsonUserPrefsStorageTest.java @@ -1,4 +1,4 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -13,8 +13,8 @@ import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.UserPrefs; +import com.t13g2.forum.commons.exceptions.DataConversionException; +import com.t13g2.forum.model.UserPrefs; public class JsonUserPrefsStorageTest { @@ -58,12 +58,6 @@ private Path addToTestDataPathIfNotNull(String userPrefsFileInTestDataFolder) { : null; } - @Test - public void readUserPrefs_fileInOrder_successfullyRead() throws DataConversionException { - UserPrefs expected = getTypicalUserPrefs(); - UserPrefs actual = readUserPrefs("TypicalUserPref.json").get(); - assertEquals(expected, actual); - } @Test public void readUserPrefs_valuesMissingFromFile_defaultValuesUsed() throws DataConversionException { @@ -71,18 +65,12 @@ public void readUserPrefs_valuesMissingFromFile_defaultValuesUsed() throws DataC assertEquals(new UserPrefs(), actual); } - @Test - public void readUserPrefs_extraValuesInFile_extraValuesIgnored() throws DataConversionException { - UserPrefs expected = getTypicalUserPrefs(); - UserPrefs actual = readUserPrefs("ExtraValuesUserPref.json").get(); - assertEquals(expected, actual); - } private UserPrefs getTypicalUserPrefs() { UserPrefs userPrefs = new UserPrefs(); userPrefs.setGuiSettings(1000, 500, 300, 100); - userPrefs.setAddressBookFilePath(Paths.get("addressbook.xml")); + userPrefs.setForumBookFilePath(Paths.get("data/addressbook.xml")); return userPrefs; } diff --git a/src/test/java/com/t13g2/forum/storage/RunningIdTest.java b/src/test/java/com/t13g2/forum/storage/RunningIdTest.java new file mode 100644 index 000000000000..ce5e6d0c7bdb --- /dev/null +++ b/src/test/java/com/t13g2/forum/storage/RunningIdTest.java @@ -0,0 +1,18 @@ +package com.t13g2.forum.storage; + +import org.junit.Assert; +import org.junit.Test; + +import com.t13g2.forum.storage.forum.RunningId; + +/** + * Tests running Id + */ +public class RunningIdTest { + @Test + public void testRunningId() { + int currentId = RunningId.getInstance().nextId(); + int nextId = RunningId.getInstance().nextId(); + Assert.assertEquals(nextId, currentId + 1); + } +} diff --git a/src/test/java/com/t13g2/forum/storage/SimpleEncryptorTest.java b/src/test/java/com/t13g2/forum/storage/SimpleEncryptorTest.java new file mode 100644 index 000000000000..a94cccd7436e --- /dev/null +++ b/src/test/java/com/t13g2/forum/storage/SimpleEncryptorTest.java @@ -0,0 +1,40 @@ +package com.t13g2.forum.storage; + +import org.hamcrest.core.IsEqual; +import org.hamcrest.core.IsNot; +import org.junit.Assert; +import org.junit.Test; + +import com.t13g2.forum.storage.forum.SimpleEncryptor; + +public class SimpleEncryptorTest { + + @Test + public void testString() { + + String original = "hahahaha I AM A TEST MESSAGE"; + SimpleEncryptor encryptor = new SimpleEncryptor(); + String encrypted = encryptor.encryptToString(original); + + Assert.assertNotEquals(original, encrypted); + + + String decrypted = encryptor.decryptToString(encrypted); + Assert.assertEquals(original, decrypted); + + } + + @Test + public void testBytes() { + String original = "hahahaha I AM A TEST MESSAGE"; + SimpleEncryptor encryptor = new SimpleEncryptor(); + byte[] encrypted = encryptor.encryptToBytes(original); + + Assert.assertThat(original, IsNot.not(IsEqual.equalTo(encrypted))); + + SimpleEncryptor decryptor = new SimpleEncryptor(); + byte[] decrypted = decryptor.decryptToBytes(new String(encrypted)); + Assert.assertArrayEquals(original.getBytes(), decrypted); + + } +} diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/com/t13g2/forum/storage/StorageManagerTest.java similarity index 65% rename from src/test/java/seedu/address/storage/StorageManagerTest.java rename to src/test/java/com/t13g2/forum/storage/StorageManagerTest.java index 215ce2bcb0e1..b1ccf41b7e6e 100644 --- a/src/test/java/seedu/address/storage/StorageManagerTest.java +++ b/src/test/java/com/t13g2/forum/storage/StorageManagerTest.java @@ -1,9 +1,8 @@ -package seedu.address.storage; +package com.t13g2.forum.storage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import java.io.IOException; import java.nio.file.Path; @@ -14,12 +13,13 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; -import seedu.address.commons.events.model.AddressBookChangedEvent; -import seedu.address.commons.events.storage.DataSavingExceptionEvent; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.UserPrefs; -import seedu.address.ui.testutil.EventsCollectorRule; +import com.t13g2.forum.commons.events.model.AddressBookChangedEvent; +import com.t13g2.forum.commons.events.storage.DataSavingExceptionEvent; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.ReadOnlyForumBook; +import com.t13g2.forum.model.UserPrefs; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.ui.testutil.EventsCollectorRule; public class StorageManagerTest { @@ -32,7 +32,7 @@ public class StorageManagerTest { @Before public void setUp() { - XmlAddressBookStorage addressBookStorage = new XmlAddressBookStorage(getTempFilePath("ab")); + XmlForumBookStorage addressBookStorage = new XmlForumBookStorage(getTempFilePath("ab")); JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(getTempFilePath("prefs")); storageManager = new StorageManager(addressBookStorage, userPrefsStorage); } @@ -60,26 +60,26 @@ 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 XmlForumBookStorage} class. + * More extensive testing of UserPref saving/reading is done in class. */ - AddressBook original = getTypicalAddressBook(); - storageManager.saveAddressBook(original); - ReadOnlyAddressBook retrieved = storageManager.readAddressBook().get(); - assertEquals(original, new AddressBook(retrieved)); + ForumBook original = TypicalPersons.getTypicalAddressBook(); + storageManager.saveForumBook(original); + ReadOnlyForumBook retrieved = storageManager.readForumBook().get(); + assertEquals(original, new ForumBook(retrieved)); } @Test public void getAddressBookFilePath() { - assertNotNull(storageManager.getAddressBookFilePath()); + assertNotNull(storageManager.getForumBookFilePath()); } @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(Paths.get("dummy")), + Storage storage = new StorageManager(new XmlForumBookStorageExceptionThrowingStub(Paths.get("dummy")), new JsonUserPrefsStorage(Paths.get("dummy"))); - storage.handleAddressBookChangedEvent(new AddressBookChangedEvent(new AddressBook())); + storage.handleAddressBookChangedEvent(new AddressBookChangedEvent(new ForumBook())); assertTrue(eventsCollectorRule.eventsCollector.getMostRecent() instanceof DataSavingExceptionEvent); } @@ -87,14 +87,14 @@ public void handleAddressBookChangedEvent_exceptionThrown_eventRaised() { /** * A Stub class to throw an exception when the save method is called */ - class XmlAddressBookStorageExceptionThrowingStub extends XmlAddressBookStorage { + class XmlForumBookStorageExceptionThrowingStub extends XmlForumBookStorage { - public XmlAddressBookStorageExceptionThrowingStub(Path filePath) { + public XmlForumBookStorageExceptionThrowingStub(Path filePath) { super(filePath); } @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException { + public void saveForumBook(ReadOnlyForumBook addressBook, Path filePath) throws IOException { throw new IOException("dummy exception"); } } diff --git a/src/test/java/com/t13g2/forum/storage/StorageStub.java b/src/test/java/com/t13g2/forum/storage/StorageStub.java new file mode 100644 index 000000000000..d287bd18c55a --- /dev/null +++ b/src/test/java/com/t13g2/forum/storage/StorageStub.java @@ -0,0 +1,87 @@ +//@@author Meowzz95 +package com.t13g2.forum.storage; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; + +import com.t13g2.forum.storage.forum.IStorage; + +/** + * Defines a stub for Storage + */ +public class StorageStub implements IStorage { + private static StorageStub instance; + + private HashMap storage; + + private StorageStub() { + storage = new HashMap<>(); + } + + public static StorageStub getInstance() { + if (instance == null) { + instance = new StorageStub(); + } + return instance; + } + + + @Override + public T read(Class clazz) { + return (T) this.copyObject(storage.get(clazz)); + } + + @Override + public void write(Object object) { + storage.put(object.getClass(), this.copyObject(object)); + } + + // @Override + // public Object read(Class clazz) { + // return this.copyObject(storage.get(clazz)); + // } + // + // @Override + // public void remove(Class clazz) { + // storage.remove(clazz); + // } + // + // @Override + // public void handleSourceChange(IEvent changeEvent) { + // + // } + + public void refreshInstantce() { + instance = new StorageStub(); + } + + /** + * + */ + private Object copyObject(Object objSource) { + Object objDest = null; + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(objSource); + oos.flush(); + oos.close(); + bos.close(); + byte[] byteData = bos.toByteArray(); + ByteArrayInputStream bais = new ByteArrayInputStream(byteData); + try { + objDest = new ObjectInputStream(bais).readObject(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return objDest; + + } +} diff --git a/src/test/java/com/t13g2/forum/storage/UnitOfWorkTest.java b/src/test/java/com/t13g2/forum/storage/UnitOfWorkTest.java new file mode 100644 index 000000000000..c959eae8319e --- /dev/null +++ b/src/test/java/com/t13g2/forum/storage/UnitOfWorkTest.java @@ -0,0 +1,122 @@ +package com.t13g2.forum.storage; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import com.t13g2.forum.model.IUnitOfWork; +import com.t13g2.forum.model.UnitOfWork; +import com.t13g2.forum.model.forum.Announcement; +import com.t13g2.forum.model.forum.User; +import com.t13g2.forum.storage.forum.EntityDoesNotExistException; + +/** + * Defines unit test for UnitOfWork + */ +public class UnitOfWorkTest { + + @Rule + public ExpectedException exceptionThrown = ExpectedException.none(); + + @Test + public void testAddUser() throws EntityDoesNotExistException { + + User user = getSampleUser(); + StorageStub storage = StorageStub.getInstance(); + storage.refreshInstantce(); + + IUnitOfWork unitOfWork = new UnitOfWork(storage); + + unitOfWork.getUserRepository().addUser(user); + unitOfWork.commit(); + + IUnitOfWork unitOfWorkCopy = new UnitOfWork(storage); + + User copy = unitOfWorkCopy.getUserRepository().getUser(user.getId()); + checkUserEqual(user, copy); + } + + @Test + public void testUpdateUser() throws EntityDoesNotExistException { + User user = getSampleUser(); + StorageStub storage = StorageStub.getInstance(); + storage.refreshInstantce(); + + IUnitOfWork unitOfWork = new UnitOfWork(storage); + + unitOfWork.getUserRepository().addUser(user); + unitOfWork.commit(); + + IUnitOfWork unitOfWork1 = new UnitOfWork(storage); + + User copy = unitOfWork1.getUserRepository().getUser(user.getId()); + copy.setPhone("22222222"); + unitOfWork1.getUserRepository().updateUser(copy); + + IUnitOfWork unitOfWork2 = new UnitOfWork(storage); + User updated = unitOfWork2.getUserRepository().getUser(user.getId()); + checkUserEqual(user, updated); + } + + @Test + public void testDeleteUser() throws EntityDoesNotExistException { + User user = getSampleUser(); + StorageStub storage = StorageStub.getInstance(); + storage.refreshInstantce(); + + IUnitOfWork unitOfWork = new UnitOfWork(storage); + + unitOfWork.getUserRepository().addUser(user); + unitOfWork.commit(); + + IUnitOfWork unitOfWork1 = new UnitOfWork(storage); + + User copy = unitOfWork1.getUserRepository().getUser(user.getId()); + unitOfWork1.getUserRepository().deleteUser(copy); + unitOfWork1.commit(); + + IUnitOfWork unitOfWork2 = new UnitOfWork(storage); + exceptionThrown.expect(EntityDoesNotExistException.class); + unitOfWork2.getUserRepository().getUser(user.getId()); + } + + @Test + public void testLatestAnnouncement() throws EntityDoesNotExistException { + Announcement announcement1 = new Announcement("Earlier announcement", "Content"); + Announcement announcement2 = new Announcement("Later announcement", "Content"); + + StorageStub storage = StorageStub.getInstance(); + storage.refreshInstantce(); + IUnitOfWork unitOfWork1 = new UnitOfWork(storage); + unitOfWork1.getAnnouncementRepository().addAnnouncement(announcement1); + unitOfWork1.getAnnouncementRepository().addAnnouncement(announcement2); + unitOfWork1.commit(); + + IUnitOfWork unitOfWork2 = new UnitOfWork(storage); + Announcement latest = unitOfWork2.getAnnouncementRepository().getLatestAnnouncement(); + Assert.assertEquals(latest.getTitle(), announcement2.getTitle()); + Assert.assertEquals(latest.getContent(), announcement2.getContent()); + + } + + + private User getSampleUser() { + return new User("username", "password", true, false, "Email@1.com", "12345678"); + } + + /** + * Checks if two user are the same + * + * @param user1 + * @param user2 + */ + private void checkUserEqual(User user1, User user2) { + Assert.assertEquals(user1.getUsername(), user2.getUsername()); + Assert.assertEquals(user1.getPassword(), user2.getPassword()); + Assert.assertEquals(user1.isAdmin(), user2.isAdmin()); + Assert.assertEquals(user1.isBlock(), user2.isBlock()); + Assert.assertEquals(user1.getEmail(), user2.getEmail()); + Assert.assertEquals(user1.getPhone(), user2.getPhone()); + } +} diff --git a/src/test/java/com/t13g2/forum/testutil/AddressBookBuilder.java b/src/test/java/com/t13g2/forum/testutil/AddressBookBuilder.java new file mode 100644 index 000000000000..95b7c22c975a --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/AddressBookBuilder.java @@ -0,0 +1,34 @@ +package com.t13g2.forum.testutil; + +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.person.Person; + +/** + * A utility class to help with building Addressbook objects. + * Example usage:
    + * {@code ForumBook ab = new AddressBookBuilder().withPerson("John", "Doe").build();} + */ +public class AddressBookBuilder { + + private ForumBook addressBook; + + public AddressBookBuilder() { + addressBook = new ForumBook(); + } + + public AddressBookBuilder(ForumBook addressBook) { + this.addressBook = addressBook; + } + + /** + * Adds a new {@code Person} to the {@code ForumBook} that we are building. + */ + public AddressBookBuilder withPerson(Person person) { + addressBook.addPerson(person); + return this; + } + + public ForumBook build() { + return addressBook; + } +} diff --git a/src/test/java/com/t13g2/forum/testutil/AnnouncementBuilder.java b/src/test/java/com/t13g2/forum/testutil/AnnouncementBuilder.java new file mode 100644 index 000000000000..ca39c3a6e164 --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/AnnouncementBuilder.java @@ -0,0 +1,49 @@ +package com.t13g2.forum.testutil; + +import com.t13g2.forum.model.forum.Announcement; + +/** + * A utility class to help with building Announcement objects. + */ +public class AnnouncementBuilder { + + public static final String DEFAULT_TITLE = "System Maintenance"; + public static final String DEFAULT_CONTENT = "Regular system maintenance on every Wednesday 4pm to 5pm."; + + private String title; + private String content; + + public AnnouncementBuilder() { + title = DEFAULT_TITLE; + content = DEFAULT_CONTENT; + } + + /** + * Initializes the AnnouncementBuilder with the data of {@code announcementToCopy}. + */ + public AnnouncementBuilder(Announcement announcementToCopy) { + title = announcementToCopy.getTitle(); + content = announcementToCopy.getContent(); + } + + /** + * Sets the {@code title} of the {@code Announcement} that we are building. + */ + public AnnouncementBuilder withTitle(String title) { + this.title = title; + return this; + } + + /** + * Sets the {@code content} of the {@code Announcement} that we are building. + */ + public AnnouncementBuilder withContent(String content) { + this.content = content; + return this; + } + + public Announcement build() { + return new Announcement(title, content); + } + +} diff --git a/src/test/java/seedu/address/testutil/Assert.java b/src/test/java/com/t13g2/forum/testutil/Assert.java similarity index 98% rename from src/test/java/seedu/address/testutil/Assert.java rename to src/test/java/com/t13g2/forum/testutil/Assert.java index c72a7622b080..8485c7d7dfb3 100644 --- a/src/test/java/seedu/address/testutil/Assert.java +++ b/src/test/java/com/t13g2/forum/testutil/Assert.java @@ -1,4 +1,4 @@ -package seedu.address.testutil; +package com.t13g2.forum.testutil; /** * A set of assertion methods useful for writing tests. diff --git a/src/test/java/com/t13g2/forum/testutil/CommentBuilder.java b/src/test/java/com/t13g2/forum/testutil/CommentBuilder.java new file mode 100644 index 000000000000..cbae043adb2d --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/CommentBuilder.java @@ -0,0 +1,51 @@ +package com.t13g2.forum.testutil; + +import com.t13g2.forum.model.forum.Comment; + +//@@author HansKoh +/** + * A utility class to help with building Comment objects. + */ +public class CommentBuilder { + + public static final String DEFAULT_COMMENT_CONTENT = "This is a new comment"; + + private int threadId; + private String commentContent; + + public CommentBuilder() { + this.commentContent = DEFAULT_COMMENT_CONTENT; + } + + /** + * Initializes the CommentBuilder with the data of {@code commentToCopy}. + */ + public CommentBuilder(Comment commentToCopy) { + this.threadId = commentToCopy.getThreadId(); + this.commentContent = commentToCopy.getContent(); + } + + /** + * Sets the {@code threadId} of the {@code Comment} that we are building. + */ + public CommentBuilder withThreadId(int threadId) { + this.threadId = threadId; + return this; + } + + /** + * Sets the {@code cContent} of the {@code Comment} that we are building. + */ + public CommentBuilder withContent(String cContent) { + this.commentContent = cContent; + return this; + } + + /** + * @return a comment object with default comment content + */ + public Comment build() { + this.commentContent = DEFAULT_COMMENT_CONTENT; + return new Comment(threadId, commentContent); + } +} diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/com/t13g2/forum/testutil/EditPersonDescriptorBuilder.java similarity index 86% rename from src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java rename to src/test/java/com/t13g2/forum/testutil/EditPersonDescriptorBuilder.java index 4584bd5044e1..96b01a38152a 100644 --- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java +++ b/src/test/java/com/t13g2/forum/testutil/EditPersonDescriptorBuilder.java @@ -1,16 +1,16 @@ -package seedu.address.testutil; +package com.t13g2.forum.testutil; import java.util.Set; import java.util.stream.Collectors; 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.tag.Tag; +import com.t13g2.forum.logic.commands.EditCommand.EditPersonDescriptor; +import com.t13g2.forum.model.person.Address; +import com.t13g2.forum.model.person.Email; +import com.t13g2.forum.model.person.Name; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.model.person.Phone; +import com.t13g2.forum.model.tag.Tag; /** * A utility class to help with building EditPersonDescriptor objects. diff --git a/src/test/java/seedu/address/testutil/EventsUtil.java b/src/test/java/com/t13g2/forum/testutil/EventsUtil.java similarity index 83% rename from src/test/java/seedu/address/testutil/EventsUtil.java rename to src/test/java/com/t13g2/forum/testutil/EventsUtil.java index 4ef8f28df156..d00aab0e6183 100644 --- a/src/test/java/seedu/address/testutil/EventsUtil.java +++ b/src/test/java/com/t13g2/forum/testutil/EventsUtil.java @@ -1,9 +1,11 @@ -package seedu.address.testutil; +package com.t13g2.forum.testutil; + +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.BaseEvent; import guitests.GuiRobot; + import javafx.application.Platform; -import seedu.address.commons.core.EventsCenter; -import seedu.address.commons.events.BaseEvent; /** * Helper methods related to events. diff --git a/src/test/java/com/t13g2/forum/testutil/ForumBookStorageBuilder.java b/src/test/java/com/t13g2/forum/testutil/ForumBookStorageBuilder.java new file mode 100644 index 000000000000..3b67f44fac31 --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/ForumBookStorageBuilder.java @@ -0,0 +1,19 @@ +//@@author Meowzz95 +package com.t13g2.forum.testutil; + +import com.t13g2.forum.storage.StorageStub; +import com.t13g2.forum.storage.forum.ForumBookStorage; + +/** + * + */ +public class ForumBookStorageBuilder { + + public ForumBookStorageBuilder() { + StorageStub.getInstance().refreshInstantce(); + } + + public ForumBookStorage build() { + return new ForumBookStorage(StorageStub.getInstance()); + } +} diff --git a/src/test/java/com/t13g2/forum/testutil/ForumThreadBuilder.java b/src/test/java/com/t13g2/forum/testutil/ForumThreadBuilder.java new file mode 100644 index 000000000000..2a0764675347 --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/ForumThreadBuilder.java @@ -0,0 +1,49 @@ +package com.t13g2.forum.testutil; + +import com.t13g2.forum.model.forum.ForumThread; + +//@@author HansKoh +/** + * A utility class to help with building ForumThread objects. + */ +public class ForumThreadBuilder { + + public static final String DEFAULT_MODULE_CODE = "CS2113"; + public static final String DEFAULT_THREAD_TITLE = "This is a new thread"; + + private int moduleId; + private String threadTitle; + + public ForumThreadBuilder() { + this.threadTitle = DEFAULT_THREAD_TITLE; + } + + /** + * Initializes the ForumThreadBuilder with the data of {@code forumThreadToCopy}. + */ + public ForumThreadBuilder(ForumThread forumThreadToCopy) { + this.moduleId = forumThreadToCopy.getModuleId(); + this.threadTitle = forumThreadToCopy.getTitle(); + } + + /** + * Sets the {@code mName} of the {@code Module} that we are building. + */ + public ForumThreadBuilder withModuleId(int moduleId) { + this.moduleId = moduleId; + + return this; + } + + /** + * Sets the {@code mTitle} of the {@code Module} that we are building. + */ + public ForumThreadBuilder withTitle(String tTitle) { + this.threadTitle = tTitle; + return this; + } + + public ForumThread build() { + return new ForumThread(moduleId, threadTitle); + } +} diff --git a/src/test/java/com/t13g2/forum/testutil/ModuleBuilder.java b/src/test/java/com/t13g2/forum/testutil/ModuleBuilder.java new file mode 100644 index 000000000000..34b0d30a5388 --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/ModuleBuilder.java @@ -0,0 +1,48 @@ +package com.t13g2.forum.testutil; + +import com.t13g2.forum.model.forum.Module; +//@@author xllx1 +/** + * A utility class to help with building Module objects. + */ +public class ModuleBuilder { + + public static final String DEFAULT_MODULE_CODE = "CS2113"; + public static final String DEFAULT_MODULE_TITLE = "Software Engineering and OOP"; + + private String moduleCode; + private String moduleTitle; + + public ModuleBuilder() { + this.moduleCode = DEFAULT_MODULE_CODE; + this.moduleTitle = DEFAULT_MODULE_TITLE; + } + + /** + * Initializes the ModuleBuilder with the data of {@code moduleToCopy}. + */ + public ModuleBuilder(Module moduleToCopy) { + this.moduleCode = moduleToCopy.getModuleCode(); + this.moduleTitle = moduleToCopy.getTitle(); + } + + /** + * Sets the {@code mName} of the {@code Module} that we are building. + */ + public ModuleBuilder withCode(String mCode) { + this.moduleCode = mCode; + return this; + } + + /** + * Sets the {@code mTitle} of the {@code Module} that we are building. + */ + public ModuleBuilder withTitle(String mTitle) { + this.moduleTitle = mTitle; + return this; + } + + public Module build() { + return new Module(moduleTitle, moduleCode); + } +} diff --git a/src/test/java/com/t13g2/forum/testutil/ModuleUtil.java b/src/test/java/com/t13g2/forum/testutil/ModuleUtil.java new file mode 100644 index 000000000000..b3593cc290e2 --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/ModuleUtil.java @@ -0,0 +1,31 @@ +package com.t13g2.forum.testutil; + +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_CODE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_MODULE_TITLE; + +import com.t13g2.forum.logic.commands.CreateModuleCommand; +import com.t13g2.forum.model.forum.Module; + +//@@author xllx1 +/** + * A utility class for Module. + */ +public class ModuleUtil { + + /** + * Returns an create command string for adding the {@code module}. + */ + public static String getCreateCommand(Module module) { + return CreateModuleCommand.COMMAND_WORD + " " + getModuleDetails(module); + } + + /** + * Returns the part of command string for the given {@code module}'s details. + */ + public static String getModuleDetails(Module module) { + StringBuilder sb = new StringBuilder(); + sb.append(PREFIX_MODULE_CODE + module.getModuleCode() + " "); + sb.append(PREFIX_MODULE_TITLE + module.getTitle() + " "); + return sb.toString(); + } +} diff --git a/src/test/java/seedu/address/testutil/PersonBuilder.java b/src/test/java/com/t13g2/forum/testutil/PersonBuilder.java similarity index 87% rename from src/test/java/seedu/address/testutil/PersonBuilder.java rename to src/test/java/com/t13g2/forum/testutil/PersonBuilder.java index 5eff412178bd..30886801005a 100644 --- a/src/test/java/seedu/address/testutil/PersonBuilder.java +++ b/src/test/java/com/t13g2/forum/testutil/PersonBuilder.java @@ -1,15 +1,15 @@ -package seedu.address.testutil; +package com.t13g2.forum.testutil; 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.tag.Tag; -import seedu.address.model.util.SampleDataUtil; +import com.t13g2.forum.model.person.Address; +import com.t13g2.forum.model.person.Email; +import com.t13g2.forum.model.person.Name; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.model.person.Phone; +import com.t13g2.forum.model.tag.Tag; +import com.t13g2.forum.model.util.SampleDataUtil; /** * A utility class to help with building Person objects. diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/com/t13g2/forum/testutil/PersonUtil.java similarity index 77% rename from src/test/java/seedu/address/testutil/PersonUtil.java rename to src/test/java/com/t13g2/forum/testutil/PersonUtil.java index 908499451834..8ff375a5f5d2 100644 --- a/src/test/java/seedu/address/testutil/PersonUtil.java +++ b/src/test/java/com/t13g2/forum/testutil/PersonUtil.java @@ -1,17 +1,17 @@ -package seedu.address.testutil; +package com.t13g2.forum.testutil; -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_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_EMAIL; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_NAME; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_PHONE; +import static com.t13g2.forum.logic.parser.CliSyntax.PREFIX_TAG; import java.util.Set; -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.model.person.Person; -import seedu.address.model.tag.Tag; +import com.t13g2.forum.logic.commands.AddCommand; +import com.t13g2.forum.logic.commands.EditCommand.EditPersonDescriptor; +import com.t13g2.forum.model.person.Person; +import com.t13g2.forum.model.tag.Tag; /** * A utility class for Person. diff --git a/src/test/java/seedu/address/testutil/SerializableTestClass.java b/src/test/java/com/t13g2/forum/testutil/SerializableTestClass.java similarity index 98% rename from src/test/java/seedu/address/testutil/SerializableTestClass.java rename to src/test/java/com/t13g2/forum/testutil/SerializableTestClass.java index f5a66340489f..dd646914db65 100644 --- a/src/test/java/seedu/address/testutil/SerializableTestClass.java +++ b/src/test/java/com/t13g2/forum/testutil/SerializableTestClass.java @@ -1,4 +1,4 @@ -package seedu.address.testutil; +package com.t13g2.forum.testutil; import java.time.LocalDateTime; import java.util.ArrayList; diff --git a/src/test/java/seedu/address/testutil/TestUtil.java b/src/test/java/com/t13g2/forum/testutil/TestUtil.java similarity index 90% rename from src/test/java/seedu/address/testutil/TestUtil.java rename to src/test/java/com/t13g2/forum/testutil/TestUtil.java index 896d103eb0b5..7cfeb09a1304 100644 --- a/src/test/java/seedu/address/testutil/TestUtil.java +++ b/src/test/java/com/t13g2/forum/testutil/TestUtil.java @@ -1,13 +1,13 @@ -package seedu.address.testutil; +package com.t13g2.forum.testutil; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import seedu.address.commons.core.index.Index; -import seedu.address.model.Model; -import seedu.address.model.person.Person; +import com.t13g2.forum.commons.core.index.Index; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.person.Person; /** * A utility class for test cases. diff --git a/src/test/java/seedu/address/testutil/TypicalIndexes.java b/src/test/java/com/t13g2/forum/testutil/TypicalIndexes.java similarity index 80% rename from src/test/java/seedu/address/testutil/TypicalIndexes.java rename to src/test/java/com/t13g2/forum/testutil/TypicalIndexes.java index 1e6139376570..a26c95869008 100644 --- a/src/test/java/seedu/address/testutil/TypicalIndexes.java +++ b/src/test/java/com/t13g2/forum/testutil/TypicalIndexes.java @@ -1,6 +1,6 @@ -package seedu.address.testutil; +package com.t13g2.forum.testutil; -import seedu.address.commons.core.index.Index; +import com.t13g2.forum.commons.core.index.Index; /** * A utility class containing a list of {@code Index} objects to be used in tests. diff --git a/src/test/java/com/t13g2/forum/testutil/TypicalModules.java b/src/test/java/com/t13g2/forum/testutil/TypicalModules.java new file mode 100644 index 000000000000..21c4704b2b30 --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/TypicalModules.java @@ -0,0 +1,30 @@ +package com.t13g2.forum.testutil; + +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_MODULE_CODE_CS1231; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_MODULE_CODE_MA1508E; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_MODULE_TITLE_CS1231; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_MODULE_TITLE_MA1508E; + +import com.t13g2.forum.model.forum.Module; +//@@author xllx1 +/** + * A utility class containing a list of {@code Module} objects to be used in tests. + */ +public class TypicalModules { + public static final Module CS2113 = new ModuleBuilder().withCode("CS2113") + .withTitle("Software Eng").build(); + public static final Module GET1020 = new ModuleBuilder().withCode("GET1020") + .withTitle("Darwin and Revolution").build(); + + // Manually added - Module's details found in {@code CommandTestUtil} + public static final Module MA1508E = new ModuleBuilder().withCode(VALID_MODULE_CODE_MA1508E) + .withTitle(VALID_MODULE_TITLE_MA1508E).build(); + public static final Module CS1231 = new ModuleBuilder().withCode(VALID_MODULE_CODE_CS1231) + .withTitle(VALID_MODULE_TITLE_CS1231).build(); + public static final Module CS1111 = new ModuleBuilder().withCode("CS1111").withTitle("Random CS module").build(); + + + + //prevent instantiation. + private TypicalModules() {} +} diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/com/t13g2/forum/testutil/TypicalPersons.java similarity index 74% rename from src/test/java/seedu/address/testutil/TypicalPersons.java rename to src/test/java/com/t13g2/forum/testutil/TypicalPersons.java index fec76fb71293..e5edbb789227 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/com/t13g2/forum/testutil/TypicalPersons.java @@ -1,22 +1,22 @@ -package seedu.address.testutil; +package com.t13g2.forum.testutil; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY; -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_PHONE_AMY; -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; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_NAME_AMY; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_PHONE_AMY; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_PHONE_BOB; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; +import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import seedu.address.model.AddressBook; -import seedu.address.model.person.Person; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.person.Person; /** * A utility class containing a list of {@code Person} objects to be used in tests. @@ -60,10 +60,10 @@ public class TypicalPersons { private TypicalPersons() {} // prevents instantiation /** - * Returns an {@code AddressBook} with all the typical persons. + * Returns an {@code ForumBook} with all the typical persons. */ - public static AddressBook getTypicalAddressBook() { - AddressBook ab = new AddressBook(); + public static ForumBook getTypicalAddressBook() { + ForumBook ab = new ForumBook(); for (Person person : getTypicalPersons()) { ab.addPerson(person); } diff --git a/src/test/java/com/t13g2/forum/testutil/TypicalUsers.java b/src/test/java/com/t13g2/forum/testutil/TypicalUsers.java new file mode 100644 index 000000000000..02452ae1f559 --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/TypicalUsers.java @@ -0,0 +1,23 @@ +package com.t13g2.forum.testutil; + +import com.t13g2.forum.model.forum.User; +//@@author xllx1 +/** + * A utility class containing a list of {@code User} objects to be used in tests. + */ +public class TypicalUsers { + public static final User JANEDOE = new UserBuilder().withName("janeDoe").withPassword("123").withIsAdmin(false) + .withIsBlock(false).withEmail("janeDoe@test.com").withPhone("87654321").build(); + public static final User JIM = new UserBuilder().withName("jim").withPassword("123").withIsAdmin(false) + .withIsBlock(false).withEmail("jim@test.com").withPhone("87654321").build(); + public static final User JONE = new UserBuilder().withName("jone").withPassword("123").withIsAdmin(false) + .withIsBlock(false).withEmail("jone@test.com").withPhone("87654321").build(); + public static final User JOSH = new UserBuilder().withName("josh").withPassword("123").withIsAdmin(false) + .withIsBlock(false).withEmail("josh@test.com").withPhone("87654321").build(); + public static final User JOSHUA = new UserBuilder().withName("joshua").withPassword("123").withIsAdmin(false) + .withIsBlock(false).withEmail("joshua@test.com").withPhone("87654321").build(); + + + //prevent instantiation. + private TypicalUsers() {} +} diff --git a/src/test/java/com/t13g2/forum/testutil/UserBuilder.java b/src/test/java/com/t13g2/forum/testutil/UserBuilder.java new file mode 100644 index 000000000000..1e503a677b14 --- /dev/null +++ b/src/test/java/com/t13g2/forum/testutil/UserBuilder.java @@ -0,0 +1,93 @@ +package com.t13g2.forum.testutil; + +import com.t13g2.forum.model.forum.User; +//@@author xllx1 +/** + * A utility class to help with building User objects. + */ +public class UserBuilder { + + public static final String DEFAULT_USER_NAME = "testAdmin"; + public static final String DEFAULT_USER_PASSWORD = "123"; + public static final boolean DEFAULT_USER_IS_ADMIN = true; + public static final boolean DEFAULT_USER_IS_BLOCK = false; + public static final String DEFAULT_USER_EMAIL = "teatAdmin@test.com"; + public static final String DEFAULT_USER_PHONE = "98765432"; + + private String username; + private String password; + private boolean isAdmin; + private boolean isBlock; + private String email; + private String phone; + + public UserBuilder() { + this.username = DEFAULT_USER_NAME; + this.password = DEFAULT_USER_PASSWORD; + this.isAdmin = DEFAULT_USER_IS_ADMIN; + this.isBlock = DEFAULT_USER_IS_BLOCK; + this.email = DEFAULT_USER_EMAIL; + this.phone = DEFAULT_USER_PHONE; + } + + /** + * Initializes the UserBuilder with the data of {@code userToCopy}. + */ + public UserBuilder(User userToCopy) { + this.username = userToCopy.getUsername(); + this.password = userToCopy.getPassword(); + this.isAdmin = userToCopy.isAdmin(); + this.isBlock = userToCopy.isBlock(); + this.email = userToCopy.getEmail(); + this.phone = userToCopy.getPhone(); + } + + /** + * Sets the {@code name} of the {@code User} that we are building. + */ + public UserBuilder withName(String name) { + this.username = name; + return this; + } + + /** + * Sets the {@code password} of the {@code User} that we are building. + */ + public UserBuilder withPassword(String password) { + this.password = password; + return this; + } + /** + * Sets the {@code isAdmin} of the {@code User} that we are building. + */ + public UserBuilder withIsAdmin(boolean isAdmin) { + this.isAdmin = isAdmin; + return this; + } + /** + * Sets the {@code isBlock} of the {@code User} that we are building. + */ + public UserBuilder withIsBlock(boolean isBlock) { + this.isBlock = isBlock; + return this; + } + /** + * Sets the {@code email} of the {@code User} that we are building. + */ + public UserBuilder withEmail(String email) { + this.email = email; + return this; + } + /** + * Sets the {@code phone} of the {@code User} that we are building. + */ + public UserBuilder withPhone(String phone) { + this.phone = phone; + return this; + } + + + public User build() { + return new User(username, password, isAdmin, isBlock, email, phone); + } +} diff --git a/src/test/java/seedu/address/ui/testutil/EventsCollectorRule.java b/src/test/java/com/t13g2/forum/ui/testutil/EventsCollectorRule.java similarity index 93% rename from src/test/java/seedu/address/ui/testutil/EventsCollectorRule.java rename to src/test/java/com/t13g2/forum/ui/testutil/EventsCollectorRule.java index 2985a5e60eb1..b63e927103af 100644 --- a/src/test/java/seedu/address/ui/testutil/EventsCollectorRule.java +++ b/src/test/java/com/t13g2/forum/ui/testutil/EventsCollectorRule.java @@ -1,4 +1,4 @@ -package seedu.address.ui.testutil; +package com.t13g2.forum.ui.testutil; import java.util.ArrayList; import java.util.List; @@ -8,9 +8,8 @@ import org.junit.runners.model.Statement; import com.google.common.eventbus.Subscribe; - -import seedu.address.commons.core.EventsCenter; -import seedu.address.commons.events.BaseEvent; +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.commons.events.BaseEvent; /** * Sets up an {@code EventsCollector} and tears it down after each test. diff --git a/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java b/src/test/java/com/t13g2/forum/ui/testutil/GuiTestAssert.java similarity index 97% rename from src/test/java/seedu/address/ui/testutil/GuiTestAssert.java rename to src/test/java/com/t13g2/forum/ui/testutil/GuiTestAssert.java index 6d896fc24e79..bc07ed079167 100644 --- a/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java +++ b/src/test/java/com/t13g2/forum/ui/testutil/GuiTestAssert.java @@ -1,14 +1,17 @@ -package seedu.address.ui.testutil; +package com.t13g2.forum.ui.testutil; import static org.junit.Assert.assertEquals; import java.util.List; import java.util.stream.Collectors; +import com.t13g2.forum.model.person.Person; + import guitests.guihandles.PersonCardHandle; import guitests.guihandles.PersonListPanelHandle; import guitests.guihandles.ResultDisplayHandle; -import seedu.address.model.person.Person; + + /** * A set of assertion methods useful for writing GUI tests. diff --git a/src/test/java/seedu/address/ui/testutil/StageRule.java b/src/test/java/com/t13g2/forum/ui/testutil/StageRule.java similarity index 95% rename from src/test/java/seedu/address/ui/testutil/StageRule.java rename to src/test/java/com/t13g2/forum/ui/testutil/StageRule.java index ea65a2bb8b95..6e7b5271cbd2 100644 --- a/src/test/java/seedu/address/ui/testutil/StageRule.java +++ b/src/test/java/com/t13g2/forum/ui/testutil/StageRule.java @@ -1,4 +1,4 @@ -package seedu.address.ui.testutil; +package com.t13g2.forum.ui.testutil; import org.junit.rules.TestRule; import org.junit.runner.Description; diff --git a/src/test/java/seedu/address/ui/testutil/UiPartRule.java b/src/test/java/com/t13g2/forum/ui/testutil/UiPartRule.java similarity index 91% rename from src/test/java/seedu/address/ui/testutil/UiPartRule.java rename to src/test/java/com/t13g2/forum/ui/testutil/UiPartRule.java index ec8206a546dd..b428612f31c2 100644 --- a/src/test/java/seedu/address/ui/testutil/UiPartRule.java +++ b/src/test/java/com/t13g2/forum/ui/testutil/UiPartRule.java @@ -1,12 +1,13 @@ -package seedu.address.ui.testutil; +package com.t13g2.forum.ui.testutil; import java.util.concurrent.TimeoutException; import org.testfx.api.FxToolkit; +import com.t13g2.forum.ui.UiPart; + import javafx.scene.Parent; import javafx.scene.Scene; -import seedu.address.ui.UiPart; /** * Provides an isolated stage to test an individual {@code UiPart}. diff --git a/src/test/java/guitests/GuiRobot.java b/src/test/java/guitests/GuiRobot.java index f4e0700b22f7..5d9d07b766c8 100644 --- a/src/test/java/guitests/GuiRobot.java +++ b/src/test/java/guitests/GuiRobot.java @@ -49,7 +49,7 @@ public boolean isHeadlessMode() { /** * Waits for {@code event} to be true by {@code DEFAULT_WAIT_FOR_EVENT_TIMEOUT_MILLISECONDS} milliseconds. * - * @throws EventTimeoutException if the time taken exceeds {@code DEFAULT_WAIT_FOR_EVENT_TIMEOUT_MILLISECONDS} + * throws EventTimeoutException if the time taken exceeds {@code DEFAULT_WAIT_FOR_EVENT_TIMEOUT_MILLISECONDS} * milliseconds. */ public void waitForEvent(BooleanSupplier event) { @@ -60,7 +60,7 @@ public void waitForEvent(BooleanSupplier event) { * Waits for {@code event} to be true. * * @param timeOut in milliseconds - * @throws EventTimeoutException if the time taken exceeds {@code timeOut}. + * throws EventTimeoutException if the time taken exceeds {@code timeOut}. */ public void waitForEvent(BooleanSupplier event, int timeOut) { int timePassed = 0; @@ -99,7 +99,7 @@ public int getNumberOfWindowsShown(String stageTitle) { * The order that the windows are searched are as follows (proximity): current target window, * children of the target window, rest of the windows. * - * @throws StageNotFoundException if the stage is not found. + * throws StageNotFoundException if the stage is not found. */ public Stage getStage(String stageTitle) { Optional targetStage = listTargetWindows().stream() diff --git a/src/test/java/guitests/guihandles/AlertDialogHandle.java b/src/test/java/guitests/guihandles/AlertDialogHandle.java index 92150be91837..a8f63be7fcfd 100644 --- a/src/test/java/guitests/guihandles/AlertDialogHandle.java +++ b/src/test/java/guitests/guihandles/AlertDialogHandle.java @@ -1,8 +1,9 @@ package guitests.guihandles; +import com.t13g2.forum.ui.UiManager; + import javafx.scene.control.DialogPane; import javafx.stage.Stage; -import seedu.address.ui.UiManager; /** * A handle for the {@code AlertDialog} of the UI. diff --git a/src/test/java/guitests/guihandles/CommandBoxHandle.java b/src/test/java/guitests/guihandles/CommandBoxHandle.java index aa59b1e470e2..9909be489d01 100644 --- a/src/test/java/guitests/guihandles/CommandBoxHandle.java +++ b/src/test/java/guitests/guihandles/CommandBoxHandle.java @@ -31,6 +31,7 @@ public void run(String command) { guiRobot.pauseForHuman(); guiRobot.type(KeyCode.ENTER); + guiRobot.type(KeyCode.ENTER); } /** diff --git a/src/test/java/guitests/guihandles/NodeHandle.java b/src/test/java/guitests/guihandles/NodeHandle.java index 628b6d584fef..b81ae962a296 100644 --- a/src/test/java/guitests/guihandles/NodeHandle.java +++ b/src/test/java/guitests/guihandles/NodeHandle.java @@ -28,7 +28,7 @@ protected T getRootNode() { * Retrieves the {@code query} node owned by the {@code rootNode}. * * @param query name of the CSS selector for the node to retrieve. - * @throws NodeNotFoundException if no such node exists. + * throws NodeNotFoundException if no such node exists. */ protected Q getChildNode(String query) { Optional node = guiRobot.from(rootNode).lookup(query).tryQuery(); diff --git a/src/test/java/guitests/guihandles/PersonCardHandle.java b/src/test/java/guitests/guihandles/PersonCardHandle.java index 1789735e49a8..22262d3c0e94 100644 --- a/src/test/java/guitests/guihandles/PersonCardHandle.java +++ b/src/test/java/guitests/guihandles/PersonCardHandle.java @@ -4,11 +4,11 @@ import java.util.stream.Collectors; import com.google.common.collect.ImmutableMultiset; +import com.t13g2.forum.model.person.Person; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.layout.Region; -import seedu.address.model.person.Person; /** * Provides a handle to a person card in the person list panel. diff --git a/src/test/java/guitests/guihandles/PersonListPanelHandle.java b/src/test/java/guitests/guihandles/PersonListPanelHandle.java index d11ed161ecbd..b3309355d214 100644 --- a/src/test/java/guitests/guihandles/PersonListPanelHandle.java +++ b/src/test/java/guitests/guihandles/PersonListPanelHandle.java @@ -4,9 +4,10 @@ import java.util.Optional; import java.util.Set; +import com.t13g2.forum.model.person.Person; + import javafx.scene.Node; import javafx.scene.control.ListView; -import seedu.address.model.person.Person; /** * Provides a handle for {@code PersonListPanel} containing the list of {@code PersonCard}. diff --git a/src/test/java/guitests/guihandles/StageHandle.java b/src/test/java/guitests/guihandles/StageHandle.java index af379def00ea..c14714788967 100644 --- a/src/test/java/guitests/guihandles/StageHandle.java +++ b/src/test/java/guitests/guihandles/StageHandle.java @@ -6,11 +6,13 @@ import java.util.Optional; import java.util.logging.Logger; +import com.t13g2.forum.commons.core.LogsCenter; + import guitests.GuiRobot; import guitests.guihandles.exceptions.NodeNotFoundException; + import javafx.scene.Node; import javafx.stage.Stage; -import seedu.address.commons.core.LogsCenter; /** * Provides access to a stage in a JavaFx application for GUI testing purposes. @@ -54,7 +56,7 @@ public boolean isFocused() { * Retrieves the {@code query} node owned by the {@code stage}. * * @param query name of the CSS selector for the node to retrieve. - * @throws NodeNotFoundException if no such node exists. + * throws NodeNotFoundException if no such node exists. */ protected T getChildNode(String query) { Optional node = guiRobot.from(stage.getScene().getRoot()).lookup(query).tryQuery(); diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java deleted file mode 100644 index 771480d0e9a6..000000000000 --- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package seedu.address.logic.commands; - -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.Before; -import org.junit.Test; - -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; -import seedu.address.testutil.PersonBuilder; - -/** - * Contains integration tests (interaction with the Model) for {@code AddCommand}. - */ -public class AddCommandIntegrationTest { - - private Model model; - private CommandHistory commandHistory = new CommandHistory(); - - @Before - public void setUp() { - model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - } - - @Test - public void execute_newPerson_success() { - Person validPerson = new PersonBuilder().build(); - - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); - expectedModel.addPerson(validPerson); - expectedModel.commitAddressBook(); - - assertCommandSuccess(new AddCommand(validPerson), model, commandHistory, - String.format(AddCommand.MESSAGE_SUCCESS, validPerson), expectedModel); - } - - @Test - public void execute_duplicatePerson_throwsCommandException() { - Person personInList = model.getAddressBook().getPersonList().get(0); - assertCommandFailure(new AddCommand(personInList), model, commandHistory, - AddCommand.MESSAGE_DUPLICATE_PERSON); - } - -} diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java deleted file mode 100644 index db2c7263d25d..000000000000 --- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package seedu.address.logic.commands; - -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.Test; - -import seedu.address.logic.CommandHistory; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; - -public class ClearCommandTest { - - private CommandHistory commandHistory = new CommandHistory(); - - @Test - public void execute_emptyAddressBook_success() { - Model model = new ModelManager(); - Model expectedModel = new ModelManager(); - expectedModel.commitAddressBook(); - - assertCommandSuccess(new ClearCommand(), model, commandHistory, ClearCommand.MESSAGE_SUCCESS, expectedModel); - } - - @Test - public void execute_nonEmptyAddressBook_success() { - Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - expectedModel.resetData(new AddressBook()); - expectedModel.commitAddressBook(); - - assertCommandSuccess(new ClearCommand(), model, commandHistory, ClearCommand.MESSAGE_SUCCESS, expectedModel); - } - -} diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java deleted file mode 100644 index f5c987bdceed..000000000000 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ /dev/null @@ -1,177 +0,0 @@ -package seedu.address.logic.commands; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -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.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.Test; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; - -/** - * Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for - * {@code DeleteCommand}. - */ -public class DeleteCommandTest { - - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private CommandHistory commandHistory = new CommandHistory(); - - @Test - public void execute_validIndexUnfilteredList_success() { - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); - - String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); - - ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); - expectedModel.deletePerson(personToDelete); - expectedModel.commitAddressBook(); - - assertCommandSuccess(deleteCommand, model, commandHistory, expectedMessage, expectedModel); - } - - @Test - public void execute_invalidIndexUnfilteredList_throwsCommandException() { - Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); - DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex); - - assertCommandFailure(deleteCommand, model, commandHistory, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - @Test - public void execute_validIndexFilteredList_success() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); - - String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); - - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); - expectedModel.deletePerson(personToDelete); - expectedModel.commitAddressBook(); - showNoPerson(expectedModel); - - assertCommandSuccess(deleteCommand, model, commandHistory, expectedMessage, expectedModel); - } - - @Test - 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 - assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); - - DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex); - - assertCommandFailure(deleteCommand, model, commandHistory, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - @Test - public void executeUndoRedo_validIndexUnfilteredList_success() throws Exception { - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); - expectedModel.deletePerson(personToDelete); - expectedModel.commitAddressBook(); - - // delete -> first person deleted - deleteCommand.execute(model, commandHistory); - - // undo -> reverts addressbook back to previous state and filtered person list to show all persons - expectedModel.undoAddressBook(); - assertCommandSuccess(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_SUCCESS, expectedModel); - - // redo -> same first person deleted again - expectedModel.redoAddressBook(); - assertCommandSuccess(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_SUCCESS, expectedModel); - } - - @Test - public void executeUndoRedo_invalidIndexUnfilteredList_failure() { - Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); - DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex); - - // execution failed -> address book state not added into model - assertCommandFailure(deleteCommand, model, commandHistory, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - - // single address book state in model -> undoCommand and redoCommand fail - assertCommandFailure(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_FAILURE); - assertCommandFailure(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_FAILURE); - } - - /** - * 1. Deletes a {@code Person} 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 - * 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. - */ - @Test - public void executeUndoRedo_validIndexFilteredList_samePersonDeleted() throws Exception { - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); - - showPersonAtIndex(model, INDEX_SECOND_PERSON); - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - expectedModel.deletePerson(personToDelete); - expectedModel.commitAddressBook(); - - // delete -> deletes second person in unfiltered person list / first person in filtered person list - deleteCommand.execute(model, commandHistory); - - // undo -> reverts addressbook back to previous state and filtered person list to show all persons - expectedModel.undoAddressBook(); - assertCommandSuccess(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_SUCCESS, expectedModel); - - assertNotEquals(personToDelete, model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased())); - // redo -> deletes same second person in unfiltered person list - expectedModel.redoAddressBook(); - assertCommandSuccess(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_SUCCESS, expectedModel); - } - - @Test - public void equals() { - DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON); - DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON); - - // same object -> returns true - assertTrue(deleteFirstCommand.equals(deleteFirstCommand)); - - // same values -> returns true - DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON); - assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy)); - - // different types -> returns false - assertFalse(deleteFirstCommand.equals(1)); - - // null -> returns false - assertFalse(deleteFirstCommand.equals(null)); - - // different person -> returns false - assertFalse(deleteFirstCommand.equals(deleteSecondCommand)); - } - - /** - * Updates {@code model}'s filtered list to show no one. - */ - private void showNoPerson(Model model) { - model.updateFilteredPersonList(p -> false); - - assertTrue(model.getFilteredPersonList().isEmpty()); - } -} diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java deleted file mode 100644 index d8aa24426698..000000000000 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ /dev/null @@ -1,248 +0,0 @@ -package seedu.address.logic.commands; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -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_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -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.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.Test; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.CommandHistory; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; -import seedu.address.testutil.EditPersonDescriptorBuilder; -import seedu.address.testutil.PersonBuilder; - -/** - * Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for EditCommand. - */ -public class EditCommandTest { - - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private CommandHistory commandHistory = new CommandHistory(); - - @Test - public void execute_allFieldsSpecifiedUnfilteredList_success() { - Person editedPerson = new PersonBuilder().build(); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor); - - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedPerson); - expectedModel.commitAddressBook(); - - assertCommandSuccess(editCommand, model, commandHistory, expectedMessage, expectedModel); - } - - @Test - public void execute_someFieldsSpecifiedUnfilteredList_success() { - Index indexLastPerson = Index.fromOneBased(model.getFilteredPersonList().size()); - Person lastPerson = model.getFilteredPersonList().get(indexLastPerson.getZeroBased()); - - PersonBuilder personInList = new PersonBuilder(lastPerson); - Person editedPerson = 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 = new EditCommand(indexLastPerson, descriptor); - - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.updatePerson(lastPerson, editedPerson); - expectedModel.commitAddressBook(); - - assertCommandSuccess(editCommand, model, commandHistory, expectedMessage, expectedModel); - } - - @Test - public void execute_noFieldSpecifiedUnfilteredList_success() { - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, new EditPersonDescriptor()); - Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.commitAddressBook(); - - assertCommandSuccess(editCommand, model, commandHistory, expectedMessage, expectedModel); - } - - @Test - public void execute_filteredList_success() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - - Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - Person editedPerson = new PersonBuilder(personInFilteredList).withName(VALID_NAME_BOB).build(); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, - new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build()); - - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedPerson); - expectedModel.commitAddressBook(); - - assertCommandSuccess(editCommand, model, commandHistory, expectedMessage, expectedModel); - } - - @Test - public void execute_duplicatePersonUnfilteredList_failure() { - Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstPerson).build(); - EditCommand editCommand = new EditCommand(INDEX_SECOND_PERSON, descriptor); - - assertCommandFailure(editCommand, model, commandHistory, EditCommand.MESSAGE_DUPLICATE_PERSON); - } - - @Test - 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()); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, - new EditPersonDescriptorBuilder(personInList).build()); - - assertCommandFailure(editCommand, model, commandHistory, EditCommand.MESSAGE_DUPLICATE_PERSON); - } - - @Test - public void execute_invalidPersonIndexUnfilteredList_failure() { - Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build(); - EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor); - - assertCommandFailure(editCommand, model, commandHistory, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - /** - * Edit filtered list where index is larger than size of filtered list, - * but smaller than size of address book - */ - @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 - assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); - - EditCommand editCommand = new EditCommand(outOfBoundIndex, - new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build()); - - assertCommandFailure(editCommand, model, commandHistory, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - @Test - public void executeUndoRedo_validIndexUnfilteredList_success() throws Exception { - Person editedPerson = new PersonBuilder().build(); - Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.updatePerson(personToEdit, editedPerson); - expectedModel.commitAddressBook(); - - // edit -> first person edited - editCommand.execute(model, commandHistory); - - // undo -> reverts addressbook back to previous state and filtered person list to show all persons - expectedModel.undoAddressBook(); - assertCommandSuccess(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_SUCCESS, expectedModel); - - // redo -> same first person edited again - expectedModel.redoAddressBook(); - assertCommandSuccess(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_SUCCESS, expectedModel); - } - - @Test - public void executeUndoRedo_invalidIndexUnfilteredList_failure() { - Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build(); - EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor); - - // execution failed -> address book state not added into model - assertCommandFailure(editCommand, model, commandHistory, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - - // single address book state in model -> undoCommand and redoCommand fail - assertCommandFailure(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_FAILURE); - assertCommandFailure(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_FAILURE); - } - - /** - * 1. Edits a {@code Person} 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 - * 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. - */ - @Test - public void executeUndoRedo_validIndexFilteredList_samePersonEdited() throws Exception { - Person editedPerson = new PersonBuilder().build(); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - - showPersonAtIndex(model, INDEX_SECOND_PERSON); - Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - expectedModel.updatePerson(personToEdit, editedPerson); - expectedModel.commitAddressBook(); - - // edit -> edits second person in unfiltered person list / first person in filtered person list - editCommand.execute(model, commandHistory); - - // undo -> reverts addressbook back to previous state and filtered person list to show all persons - expectedModel.undoAddressBook(); - assertCommandSuccess(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_SUCCESS, expectedModel); - - assertNotEquals(model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()), personToEdit); - // redo -> edits same second person in unfiltered person list - expectedModel.redoAddressBook(); - assertCommandSuccess(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_SUCCESS, expectedModel); - } - - @Test - public void equals() { - final EditCommand standardCommand = new EditCommand(INDEX_FIRST_PERSON, DESC_AMY); - - // same values -> returns true - EditPersonDescriptor copyDescriptor = new EditPersonDescriptor(DESC_AMY); - EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_PERSON, copyDescriptor); - assertTrue(standardCommand.equals(commandWithSameValues)); - - // same object -> returns true - assertTrue(standardCommand.equals(standardCommand)); - - // null -> returns false - assertFalse(standardCommand.equals(null)); - - // different types -> returns false - assertFalse(standardCommand.equals(new ClearCommand())); - - // different index -> returns false - assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_PERSON, DESC_AMY))); - - // different descriptor -> returns false - assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_PERSON, DESC_BOB))); - } - -} diff --git a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java deleted file mode 100644 index bfa7549c690f..000000000000 --- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package seedu.address.logic.commands; - -import static org.junit.Assert.assertFalse; -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_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_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; - -import org.junit.Test; - -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.testutil.EditPersonDescriptorBuilder; - -public class EditPersonDescriptorTest { - - @Test - public void equals() { - // same values -> returns true - EditPersonDescriptor descriptorWithSameValues = new EditPersonDescriptor(DESC_AMY); - assertTrue(DESC_AMY.equals(descriptorWithSameValues)); - - // same object -> returns true - assertTrue(DESC_AMY.equals(DESC_AMY)); - - // null -> returns false - assertFalse(DESC_AMY.equals(null)); - - // different types -> returns false - assertFalse(DESC_AMY.equals(5)); - - // different values -> returns false - assertFalse(DESC_AMY.equals(DESC_BOB)); - - // different name -> returns false - EditPersonDescriptor editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withName(VALID_NAME_BOB).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - - // different phone -> returns false - editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withPhone(VALID_PHONE_BOB).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - - // different email -> returns false - editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withEmail(VALID_EMAIL_BOB).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - - // different address -> returns false - editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withAddress(VALID_ADDRESS_BOB).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - - // different tags -> returns false - editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withTags(VALID_TAG_HUSBAND).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - } -} diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java deleted file mode 100644 index a3e4c78f9380..000000000000 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package seedu.address.logic.commands; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static seedu.address.commons.core.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -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 java.util.Arrays; -import java.util.Collections; - -import org.junit.Test; - -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.NameContainsKeywordsPredicate; - -/** - * Contains integration tests (interaction with the Model) for {@code FindCommand}. - */ -public class FindCommandTest { - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private CommandHistory commandHistory = new CommandHistory(); - - @Test - public void equals() { - NameContainsKeywordsPredicate firstPredicate = - new NameContainsKeywordsPredicate(Collections.singletonList("first")); - NameContainsKeywordsPredicate secondPredicate = - new NameContainsKeywordsPredicate(Collections.singletonList("second")); - - FindCommand findFirstCommand = new FindCommand(firstPredicate); - FindCommand findSecondCommand = new FindCommand(secondPredicate); - - // same object -> returns true - assertTrue(findFirstCommand.equals(findFirstCommand)); - - // same values -> returns true - FindCommand findFirstCommandCopy = new FindCommand(firstPredicate); - assertTrue(findFirstCommand.equals(findFirstCommandCopy)); - - // different types -> returns false - assertFalse(findFirstCommand.equals(1)); - - // null -> returns false - assertFalse(findFirstCommand.equals(null)); - - // different person -> returns false - assertFalse(findFirstCommand.equals(findSecondCommand)); - } - - @Test - public void execute_zeroKeywords_noPersonFound() { - String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0); - NameContainsKeywordsPredicate predicate = preparePredicate(" "); - FindCommand command = new FindCommand(predicate); - expectedModel.updateFilteredPersonList(predicate); - assertCommandSuccess(command, model, commandHistory, expectedMessage, expectedModel); - assertEquals(Collections.emptyList(), model.getFilteredPersonList()); - } - - @Test - public void execute_multipleKeywords_multiplePersonsFound() { - String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3); - NameContainsKeywordsPredicate predicate = preparePredicate("Kurz Elle Kunz"); - FindCommand command = new FindCommand(predicate); - expectedModel.updateFilteredPersonList(predicate); - assertCommandSuccess(command, model, commandHistory, expectedMessage, expectedModel); - assertEquals(Arrays.asList(CARL, ELLE, FIONA), model.getFilteredPersonList()); - } - - /** - * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}. - */ - private NameContainsKeywordsPredicate preparePredicate(String userInput) { - return new NameContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+"))); - } -} diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java deleted file mode 100644 index e5235fe4b266..000000000000 --- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package seedu.address.logic.commands; - -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 org.junit.Before; -import org.junit.Test; - -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; - -/** - * Contains integration tests (interaction with the Model) and unit tests for ListCommand. - */ -public class ListCommandTest { - - private Model model; - private Model expectedModel; - private CommandHistory commandHistory = new CommandHistory(); - - @Before - public void setUp() { - model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); - } - - @Test - public void execute_listIsNotFiltered_showsSameList() { - assertCommandSuccess(new ListCommand(), model, commandHistory, ListCommand.MESSAGE_SUCCESS, expectedModel); - } - - @Test - public void execute_listIsFiltered_showsEverything() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - assertCommandSuccess(new ListCommand(), model, commandHistory, ListCommand.MESSAGE_SUCCESS, expectedModel); - } -} diff --git a/src/test/java/seedu/address/logic/commands/RedoCommandTest.java b/src/test/java/seedu/address/logic/commands/RedoCommandTest.java deleted file mode 100644 index c8aaf714b890..000000000000 --- a/src/test/java/seedu/address/logic/commands/RedoCommandTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package seedu.address.logic.commands; - -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.CommandTestUtil.deleteFirstPerson; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.Before; -import org.junit.Test; - -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; - -public class RedoCommandTest { - - private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private final Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private final CommandHistory commandHistory = new CommandHistory(); - - @Before - public void setUp() { - // set up of both models' undo/redo history - deleteFirstPerson(model); - deleteFirstPerson(model); - model.undoAddressBook(); - model.undoAddressBook(); - - deleteFirstPerson(expectedModel); - deleteFirstPerson(expectedModel); - expectedModel.undoAddressBook(); - expectedModel.undoAddressBook(); - } - - @Test - public void execute() { - // multiple redoable states in model - expectedModel.redoAddressBook(); - assertCommandSuccess(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_SUCCESS, expectedModel); - - // single redoable state in model - expectedModel.redoAddressBook(); - assertCommandSuccess(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_SUCCESS, expectedModel); - - // no redoable state in model - assertCommandFailure(new RedoCommand(), model, commandHistory, RedoCommand.MESSAGE_FAILURE); - } -} diff --git a/src/test/java/seedu/address/logic/commands/SelectCommandTest.java b/src/test/java/seedu/address/logic/commands/SelectCommandTest.java deleted file mode 100644 index d345189362da..000000000000 --- a/src/test/java/seedu/address/logic/commands/SelectCommandTest.java +++ /dev/null @@ -1,118 +0,0 @@ -package seedu.address.logic.commands; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -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.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.Rule; -import org.junit.Test; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.commons.events.ui.JumpToListRequestEvent; -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.ui.testutil.EventsCollectorRule; - -/** - * Contains integration tests (interaction with the Model) for {@code SelectCommand}. - */ -public class SelectCommandTest { - @Rule - public final EventsCollectorRule eventsCollectorRule = new EventsCollectorRule(); - - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private CommandHistory commandHistory = new CommandHistory(); - - @Test - public void execute_validIndexUnfilteredList_success() { - Index lastPersonIndex = Index.fromOneBased(model.getFilteredPersonList().size()); - - assertExecutionSuccess(INDEX_FIRST_PERSON); - assertExecutionSuccess(INDEX_THIRD_PERSON); - assertExecutionSuccess(lastPersonIndex); - } - - @Test - public void execute_invalidIndexUnfilteredList_failure() { - Index outOfBoundsIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); - - assertExecutionFailure(outOfBoundsIndex, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - @Test - public void execute_validIndexFilteredList_success() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - showPersonAtIndex(expectedModel, INDEX_FIRST_PERSON); - - assertExecutionSuccess(INDEX_FIRST_PERSON); - } - - @Test - public void execute_invalidIndexFilteredList_failure() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - showPersonAtIndex(expectedModel, INDEX_FIRST_PERSON); - - Index outOfBoundsIndex = INDEX_SECOND_PERSON; - // ensures that outOfBoundIndex is still in bounds of address book list - assertTrue(outOfBoundsIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); - - assertExecutionFailure(outOfBoundsIndex, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - @Test - public void equals() { - SelectCommand selectFirstCommand = new SelectCommand(INDEX_FIRST_PERSON); - SelectCommand selectSecondCommand = new SelectCommand(INDEX_SECOND_PERSON); - - // same object -> returns true - assertTrue(selectFirstCommand.equals(selectFirstCommand)); - - // same values -> returns true - SelectCommand selectFirstCommandCopy = new SelectCommand(INDEX_FIRST_PERSON); - assertTrue(selectFirstCommand.equals(selectFirstCommandCopy)); - - // different types -> returns false - assertFalse(selectFirstCommand.equals(1)); - - // null -> returns false - assertFalse(selectFirstCommand.equals(null)); - - // different person -> returns false - assertFalse(selectFirstCommand.equals(selectSecondCommand)); - } - - /** - * Executes a {@code SelectCommand} with the given {@code index}, and checks that {@code JumpToListRequestEvent} - * is raised with the correct index. - */ - private void assertExecutionSuccess(Index index) { - SelectCommand selectCommand = new SelectCommand(index); - String expectedMessage = String.format(SelectCommand.MESSAGE_SELECT_PERSON_SUCCESS, index.getOneBased()); - - assertCommandSuccess(selectCommand, model, commandHistory, expectedMessage, expectedModel); - - JumpToListRequestEvent lastEvent = (JumpToListRequestEvent) eventsCollectorRule.eventsCollector.getMostRecent(); - assertEquals(index, Index.fromZeroBased(lastEvent.targetIndex)); - } - - /** - * Executes a {@code SelectCommand} with the given {@code index}, and checks that a {@code CommandException} - * is thrown with the {@code expectedMessage}. - */ - private void assertExecutionFailure(Index index, String expectedMessage) { - SelectCommand selectCommand = new SelectCommand(index); - assertCommandFailure(selectCommand, model, commandHistory, expectedMessage); - assertTrue(eventsCollectorRule.eventsCollector.isEmpty()); - } -} diff --git a/src/test/java/seedu/address/logic/commands/UndoCommandTest.java b/src/test/java/seedu/address/logic/commands/UndoCommandTest.java deleted file mode 100644 index 0a706b8eb823..000000000000 --- a/src/test/java/seedu/address/logic/commands/UndoCommandTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package seedu.address.logic.commands; - -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.CommandTestUtil.deleteFirstPerson; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.Before; -import org.junit.Test; - -import seedu.address.logic.CommandHistory; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; - -public class UndoCommandTest { - - private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private final Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private final CommandHistory commandHistory = new CommandHistory(); - - @Before - public void setUp() { - // set up of models' undo/redo history - deleteFirstPerson(model); - deleteFirstPerson(model); - - deleteFirstPerson(expectedModel); - deleteFirstPerson(expectedModel); - } - - @Test - public void execute() { - // multiple undoable states in model - expectedModel.undoAddressBook(); - assertCommandSuccess(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_SUCCESS, expectedModel); - - // single undoable state in model - expectedModel.undoAddressBook(); - assertCommandSuccess(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_SUCCESS, expectedModel); - - // no undoable states in model - assertCommandFailure(new UndoCommand(), model, commandHistory, UndoCommand.MESSAGE_FAILURE); - } -} diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java deleted file mode 100644 index c770e86482e6..000000000000 --- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java +++ /dev/null @@ -1,141 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; -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_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.PHONE_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_NON_EMPTY; -import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE; -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_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -import static seedu.address.testutil.TypicalPersons.AMY; -import static seedu.address.testutil.TypicalPersons.BOB; - -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.tag.Tag; -import seedu.address.testutil.PersonBuilder; - -public class AddCommandParserTest { - private AddCommandParser parser = new AddCommandParser(); - - @Test - public void parse_allFieldsPresent_success() { - Person expectedPerson = new PersonBuilder(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)); - - // 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)); - - // 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)); - - // 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)); - - // 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)); - - // multiple tags - all accepted - Person expectedPersonMultipleTags = new PersonBuilder(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)); - } - - @Test - public void parse_optionalFieldsMissing_success() { - // zero tags - Person expectedPerson = new PersonBuilder(AMY).withTags().build(); - assertParseSuccess(parser, NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY, - new AddCommand(expectedPerson)); - } - - @Test - 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, - expectedMessage); - - // missing phone prefix - assertParseFailure(parser, NAME_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, - expectedMessage); - - // missing address prefix - assertParseFailure(parser, NAME_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, - 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); - - // invalid phone - assertParseFailure(parser, NAME_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 - + 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 - + 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 - + 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); - - // non-empty preamble - assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_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/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java deleted file mode 100644 index a8c8cbf21f4e..000000000000 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ /dev/null @@ -1,143 +0,0 @@ -package seedu.address.logic.parser; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.ClearCommand; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.HelpCommand; -import seedu.address.logic.commands.HistoryCommand; -import seedu.address.logic.commands.ListCommand; -import seedu.address.logic.commands.RedoCommand; -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.testutil.EditPersonDescriptorBuilder; -import seedu.address.testutil.PersonBuilder; -import seedu.address.testutil.PersonUtil; - -public class AddressBookParserTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private final AddressBookParser parser = new AddressBookParser(); - - @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); - } - - @Test - public void parseCommand_clear() throws Exception { - assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD) instanceof ClearCommand); - assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD + " 3") instanceof ClearCommand); - } - - @Test - public void parseCommand_delete() throws Exception { - DeleteCommand command = (DeleteCommand) parser.parseCommand( - DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()); - assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command); - } - - @Test - public void parseCommand_edit() throws Exception { - Person person = new PersonBuilder().build(); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build(); - EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " " - + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor)); - assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command); - } - - @Test - public void parseCommand_exit() throws Exception { - assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD) instanceof ExitCommand); - assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD + " 3") instanceof ExitCommand); - } - - @Test - 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); - } - - @Test - public void parseCommand_help() throws Exception { - assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD) instanceof HelpCommand); - assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD + " 3") instanceof HelpCommand); - } - - @Test - public void parseCommand_history() throws Exception { - assertTrue(parser.parseCommand(HistoryCommand.COMMAND_WORD) instanceof HistoryCommand); - assertTrue(parser.parseCommand(HistoryCommand.COMMAND_WORD + " 3") instanceof HistoryCommand); - - try { - parser.parseCommand("histories"); - throw new AssertionError("The expected ParseException was not thrown."); - } catch (ParseException pe) { - assertEquals(MESSAGE_UNKNOWN_COMMAND, pe.getMessage()); - } - } - - @Test - public void parseCommand_list() throws Exception { - assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand); - assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand); - } - - @Test - public void parseCommand_select() throws Exception { - SelectCommand command = (SelectCommand) parser.parseCommand( - SelectCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()); - assertEquals(new SelectCommand(INDEX_FIRST_PERSON), command); - } - - @Test - public void parseCommand_redoCommandWord_returnsRedoCommand() throws Exception { - assertTrue(parser.parseCommand(RedoCommand.COMMAND_WORD) instanceof RedoCommand); - assertTrue(parser.parseCommand("redo 1") instanceof RedoCommand); - } - - @Test - public void parseCommand_undoCommandWord_returnsUndoCommand() throws Exception { - assertTrue(parser.parseCommand(UndoCommand.COMMAND_WORD) instanceof UndoCommand); - assertTrue(parser.parseCommand("undo 3") instanceof UndoCommand); - } - - @Test - public void parseCommand_unrecognisedInput_throwsParseException() throws Exception { - thrown.expect(ParseException.class); - thrown.expectMessage(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); - parser.parseCommand(""); - } - - @Test - public void parseCommand_unknownCommand_throwsParseException() throws Exception { - thrown.expect(ParseException.class); - thrown.expectMessage(MESSAGE_UNKNOWN_COMMAND); - parser.parseCommand("unknownCommand"); - } -} diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java deleted file mode 100644 index 24c138b41a7f..000000000000 --- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java +++ /dev/null @@ -1,211 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; -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_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.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_AMY; -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_PHONE_AMY; -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; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -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 org.junit.Test; - -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.tag.Tag; -import seedu.address.testutil.EditPersonDescriptorBuilder; - -public class EditCommandParserTest { - - private static final String TAG_EMPTY = " " + PREFIX_TAG; - - private static final String MESSAGE_INVALID_FORMAT = - String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE); - - private EditCommandParser parser = new EditCommandParser(); - - @Test - public void parse_missingParts_failure() { - // no index specified - assertParseFailure(parser, VALID_NAME_AMY, MESSAGE_INVALID_FORMAT); - - // no field specified - assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED); - - // no index and no field specified - assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT); - } - - @Test - public void parse_invalidPreamble_failure() { - // negative index - assertParseFailure(parser, "-5" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT); - - // zero index - assertParseFailure(parser, "0" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT); - - // invalid arguments being parsed as preamble - assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT); - - // invalid prefix being parsed as preamble - assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT); - } - - @Test - public void parse_invalidValue_failure() { - assertParseFailure(parser, "1" + INVALID_NAME_DESC, Name.MESSAGE_NAME_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 - assertParseFailure(parser, "1" + INVALID_TAG_DESC, Tag.MESSAGE_TAG_CONSTRAINTS); // invalid tag - - // invalid phone followed by valid email - assertParseFailure(parser, "1" + INVALID_PHONE_DESC + EMAIL_DESC_AMY, Phone.MESSAGE_PHONE_CONSTRAINTS); - - // valid phone followed by invalid phone. The test case for invalid phone followed by valid phone - // 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, - // 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); - 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); - } - - @Test - public void parse_allFieldsSpecified_success() { - Index targetIndex = INDEX_SECOND_PERSON; - String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + TAG_DESC_HUSBAND - + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + NAME_DESC_AMY + TAG_DESC_FRIEND; - - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_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); - - assertParseSuccess(parser, userInput, expectedCommand); - } - - @Test - public void parse_someFieldsSpecified_success() { - Index targetIndex = INDEX_FIRST_PERSON; - String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + EMAIL_DESC_AMY; - - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB) - .withEmail(VALID_EMAIL_AMY).build(); - EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); - - assertParseSuccess(parser, userInput, expectedCommand); - } - - @Test - public void parse_oneFieldSpecified_success() { - // name - Index targetIndex = INDEX_THIRD_PERSON; - String userInput = targetIndex.getOneBased() + NAME_DESC_AMY; - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY).build(); - EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - - // phone - userInput = targetIndex.getOneBased() + PHONE_DESC_AMY; - descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_AMY).build(); - expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - - // email - userInput = targetIndex.getOneBased() + EMAIL_DESC_AMY; - descriptor = new EditPersonDescriptorBuilder().withEmail(VALID_EMAIL_AMY).build(); - expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - - // address - userInput = targetIndex.getOneBased() + ADDRESS_DESC_AMY; - descriptor = new EditPersonDescriptorBuilder().withAddress(VALID_ADDRESS_AMY).build(); - expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - - // tags - userInput = targetIndex.getOneBased() + TAG_DESC_FRIEND; - descriptor = new EditPersonDescriptorBuilder().withTags(VALID_TAG_FRIEND).build(); - expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - } - - @Test - public void parse_multipleRepeatedFields_acceptsLast() { - Index targetIndex = INDEX_FIRST_PERSON; - String userInput = targetIndex.getOneBased() + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY - + TAG_DESC_FRIEND + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY + TAG_DESC_FRIEND - + PHONE_DESC_BOB + ADDRESS_DESC_BOB + EMAIL_DESC_BOB + TAG_DESC_HUSBAND; - - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB) - .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND) - .build(); - EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); - - assertParseSuccess(parser, userInput, expectedCommand); - } - - @Test - public void parse_invalidValueFollowedByValidValue_success() { - // no other valid values specified - Index targetIndex = INDEX_FIRST_PERSON; - String userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + PHONE_DESC_BOB; - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB).build(); - EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - - // other valid values specified - userInput = targetIndex.getOneBased() + EMAIL_DESC_BOB + INVALID_PHONE_DESC + ADDRESS_DESC_BOB - + PHONE_DESC_BOB; - descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB) - .withAddress(VALID_ADDRESS_BOB).build(); - expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - } - - @Test - public void parse_resetTags_success() { - Index targetIndex = INDEX_THIRD_PERSON; - String userInput = targetIndex.getOneBased() + TAG_EMPTY; - - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withTags().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 deleted file mode 100644 index e65143d3b7b0..000000000000 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; - -import java.util.Arrays; - -import org.junit.Test; - -import seedu.address.logic.commands.FindCommand; -import seedu.address.model.person.NameContainsKeywordsPredicate; - -public class FindCommandParserTest { - - private FindCommandParser parser = new FindCommandParser(); - - @Test - public void parse_emptyArg_throwsParseException() { - assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); - } - - @Test - public void parse_validArgs_returnsFindCommand() { - // no leading and trailing whitespaces - FindCommand expectedFindCommand = - new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"))); - assertParseSuccess(parser, "Alice Bob", expectedFindCommand); - - // multiple whitespaces between keywords - assertParseSuccess(parser, " \n Alice \n \t Bob \t", expectedFindCommand); - } - -} diff --git a/src/test/java/seedu/address/model/person/PersonTest.java b/src/test/java/seedu/address/model/person/PersonTest.java deleted file mode 100644 index ac75b257fa39..000000000000 --- a/src/test/java/seedu/address/model/person/PersonTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package seedu.address.model.person; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -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_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.BOB; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import seedu.address.testutil.PersonBuilder; - -public class PersonTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void asObservableList_modifyList_throwsUnsupportedOperationException() { - Person person = new PersonBuilder().build(); - thrown.expect(UnsupportedOperationException.class); - person.getTags().remove(0); - } - - @Test - public void isSamePerson() { - // same object -> returns true - assertTrue(ALICE.isSamePerson(ALICE)); - - // null -> returns false - assertFalse(ALICE.isSamePerson(null)); - - // different phone and email -> returns false - Person editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).build(); - assertFalse(ALICE.isSamePerson(editedAlice)); - - // different name -> returns false - editedAlice = new PersonBuilder(ALICE).withName(VALID_NAME_BOB).build(); - assertFalse(ALICE.isSamePerson(editedAlice)); - - // same name, same phone, different attributes -> returns true - editedAlice = new PersonBuilder(ALICE).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB) - .withTags(VALID_TAG_HUSBAND).build(); - assertTrue(ALICE.isSamePerson(editedAlice)); - - // same name, same email, different attributes -> returns true - editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).withAddress(VALID_ADDRESS_BOB) - .withTags(VALID_TAG_HUSBAND).build(); - assertTrue(ALICE.isSamePerson(editedAlice)); - - // same name, same phone, same email, different attributes -> returns true - editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); - assertTrue(ALICE.isSamePerson(editedAlice)); - } - - @Test - public void equals() { - // same values -> returns true - Person aliceCopy = new PersonBuilder(ALICE).build(); - assertTrue(ALICE.equals(aliceCopy)); - - // same object -> returns true - assertTrue(ALICE.equals(ALICE)); - - // null -> returns false - assertFalse(ALICE.equals(null)); - - // different type -> returns false - assertFalse(ALICE.equals(5)); - - // different person -> returns false - assertFalse(ALICE.equals(BOB)); - - // different name -> returns false - Person editedAlice = new PersonBuilder(ALICE).withName(VALID_NAME_BOB).build(); - assertFalse(ALICE.equals(editedAlice)); - - // different phone -> returns false - editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).build(); - assertFalse(ALICE.equals(editedAlice)); - - // different email -> returns false - editedAlice = new PersonBuilder(ALICE).withEmail(VALID_EMAIL_BOB).build(); - assertFalse(ALICE.equals(editedAlice)); - - // different address -> returns false - editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).build(); - assertFalse(ALICE.equals(editedAlice)); - - // different tags -> returns false - editedAlice = new PersonBuilder(ALICE).withTags(VALID_TAG_HUSBAND).build(); - assertFalse(ALICE.equals(editedAlice)); - } -} diff --git a/src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java b/src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java deleted file mode 100644 index c3c91a5c27a7..000000000000 --- a/src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java +++ /dev/null @@ -1,110 +0,0 @@ -package seedu.address.storage; - -import static org.junit.Assert.assertEquals; -import static seedu.address.storage.XmlAdaptedPerson.MISSING_FIELD_MESSAGE_FORMAT; -import static seedu.address.testutil.TypicalPersons.BENSON; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -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.testutil.Assert; - -public class XmlAdaptedPersonTest { - private static final String INVALID_NAME = "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_PHONE = BENSON.getPhone().toString(); - private static final String VALID_EMAIL = BENSON.getEmail().toString(); - private static final String VALID_ADDRESS = BENSON.getAddress().toString(); - private static final List VALID_TAGS = BENSON.getTags().stream() - .map(XmlAdaptedTag::new) - .collect(Collectors.toList()); - - @Test - public void toModelType_validPersonDetails_returnsPerson() throws Exception { - XmlAdaptedPerson person = new XmlAdaptedPerson(BENSON); - assertEquals(BENSON, person.toModelType()); - } - - @Test - public void toModelType_invalidName_throwsIllegalValueException() { - XmlAdaptedPerson person = - new XmlAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = Name.MESSAGE_NAME_CONSTRAINTS; - Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_nullName_throwsIllegalValueException() { - XmlAdaptedPerson person = new XmlAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()); - Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_invalidPhone_throwsIllegalValueException() { - XmlAdaptedPerson person = - new XmlAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = Phone.MESSAGE_PHONE_CONSTRAINTS; - Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_nullPhone_throwsIllegalValueException() { - XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()); - Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_invalidEmail_throwsIllegalValueException() { - XmlAdaptedPerson person = - new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = Email.MESSAGE_EMAIL_CONSTRAINTS; - Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_nullEmail_throwsIllegalValueException() { - XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()); - Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_invalidAddress_throwsIllegalValueException() { - XmlAdaptedPerson person = - new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, VALID_TAGS); - String expectedMessage = Address.MESSAGE_ADDRESS_CONSTRAINTS; - Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_nullAddress_throwsIllegalValueException() { - XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS); - String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()); - Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_invalidTags_throwsIllegalValueException() { - List invalidTags = new ArrayList<>(VALID_TAGS); - invalidTags.add(new XmlAdaptedTag(INVALID_TAG)); - XmlAdaptedPerson person = - new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags); - Assert.assertThrows(IllegalValueException.class, person::toModelType); - } - -} diff --git a/src/test/java/seedu/address/storage/XmlAddressBookStorageTest.java b/src/test/java/seedu/address/storage/XmlAddressBookStorageTest.java deleted file mode 100644 index 484bd43cc0fd..000000000000 --- a/src/test/java/seedu/address/storage/XmlAddressBookStorageTest.java +++ /dev/null @@ -1,127 +0,0 @@ -package seedu.address.storage; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -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 java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; - -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; - -public class XmlAddressBookStorageTest { - private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "XmlAddressBookStorageTest"); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Rule - public TemporaryFolder testFolder = new TemporaryFolder(); - - @Test - public void readAddressBook_nullFilePath_throwsNullPointerException() throws Exception { - thrown.expect(NullPointerException.class); - readAddressBook(null); - } - - private java.util.Optional readAddressBook(String filePath) throws Exception { - return new XmlAddressBookStorage(Paths.get(filePath)).readAddressBook(addToTestDataPathIfNotNull(filePath)); - } - - private Path addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) { - return prefsFileInTestDataFolder != null - ? TEST_DATA_FOLDER.resolve(prefsFileInTestDataFolder) - : null; - } - - @Test - public void read_missingFile_emptyResult() throws Exception { - assertFalse(readAddressBook("NonExistentFile.xml").isPresent()); - } - - @Test - public void read_notXmlFormat_exceptionThrown() throws Exception { - - thrown.expect(DataConversionException.class); - readAddressBook("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 - */ - } - - @Test - public void readAddressBook_invalidPersonAddressBook_throwDataConversionException() throws Exception { - thrown.expect(DataConversionException.class); - readAddressBook("invalidPersonAddressBook.xml"); - } - - @Test - public void readAddressBook_invalidAndValidPersonAddressBook_throwDataConversionException() throws Exception { - thrown.expect(DataConversionException.class); - readAddressBook("invalidAndValidPersonAddressBook.xml"); - } - - @Test - public void readAndSaveAddressBook_allInOrder_success() throws Exception { - Path filePath = testFolder.getRoot().toPath().resolve("TempAddressBook.xml"); - AddressBook original = getTypicalAddressBook(); - XmlAddressBookStorage xmlAddressBookStorage = new XmlAddressBookStorage(filePath); - - //Save in new file and read back - xmlAddressBookStorage.saveAddressBook(original, filePath); - ReadOnlyAddressBook readBack = xmlAddressBookStorage.readAddressBook(filePath).get(); - assertEquals(original, new AddressBook(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)); - - //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)); - - } - - @Test - public void saveAddressBook_nullAddressBook_throwsNullPointerException() { - thrown.expect(NullPointerException.class); - saveAddressBook(null, "SomeFile.xml"); - } - - /** - * Saves {@code addressBook} at the specified {@code filePath}. - */ - private void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) { - try { - new XmlAddressBookStorage(Paths.get(filePath)) - .saveAddressBook(addressBook, 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() { - thrown.expect(NullPointerException.class); - saveAddressBook(new AddressBook(), null); - } - - -} diff --git a/src/test/java/seedu/address/storage/XmlSerializableAddressBookTest.java b/src/test/java/seedu/address/storage/XmlSerializableAddressBookTest.java deleted file mode 100644 index 55a4f10957b3..000000000000 --- a/src/test/java/seedu/address/storage/XmlSerializableAddressBookTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package seedu.address.storage; - -import static org.junit.Assert.assertEquals; - -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.commons.util.XmlUtil; -import seedu.address.model.AddressBook; -import seedu.address.testutil.TypicalPersons; - -public class XmlSerializableAddressBookTest { - - private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "XmlSerializableAddressBookTest"); - private static final Path TYPICAL_PERSONS_FILE = TEST_DATA_FOLDER.resolve("typicalPersonsAddressBook.xml"); - private static final Path INVALID_PERSON_FILE = TEST_DATA_FOLDER.resolve("invalidPersonAddressBook.xml"); - private static final Path DUPLICATE_PERSON_FILE = TEST_DATA_FOLDER.resolve("duplicatePersonAddressBook.xml"); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @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); - } - - @Test - public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception { - XmlSerializableAddressBook dataFromFile = XmlUtil.getDataFromFile(INVALID_PERSON_FILE, - XmlSerializableAddressBook.class); - thrown.expect(IllegalValueException.class); - dataFromFile.toModelType(); - } - - @Test - public void toModelType_duplicatePersons_throwsIllegalValueException() throws Exception { - XmlSerializableAddressBook dataFromFile = XmlUtil.getDataFromFile(DUPLICATE_PERSON_FILE, - XmlSerializableAddressBook.class); - thrown.expect(IllegalValueException.class); - thrown.expectMessage(XmlSerializableAddressBook.MESSAGE_DUPLICATE_PERSON); - 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 d53799fd1102..000000000000 --- a/src/test/java/seedu/address/testutil/AddressBookBuilder.java +++ /dev/null @@ -1,34 +0,0 @@ -package seedu.address.testutil; - -import seedu.address.model.AddressBook; -import seedu.address.model.person.Person; - -/** - * A utility class to help with building Addressbook objects. - * Example usage:
    - * {@code AddressBook ab = new AddressBookBuilder().withPerson("John", "Doe").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) { - addressBook.addPerson(person); - return this; - } - - public AddressBook build() { - return addressBook; - } -} diff --git a/src/test/java/seedu/address/ui/BrowserPanelTest.java b/src/test/java/seedu/address/ui/BrowserPanelTest.java deleted file mode 100644 index 5fe6d4f8767f..000000000000 --- a/src/test/java/seedu/address/ui/BrowserPanelTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package seedu.address.ui; - -import static guitests.guihandles.WebViewUtil.waitUntilBrowserLoaded; -import static org.junit.Assert.assertEquals; -import static seedu.address.testutil.EventsUtil.postNow; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.ui.BrowserPanel.DEFAULT_PAGE; -import static seedu.address.ui.UiPart.FXML_FILE_FOLDER; - -import java.net.URL; - -import org.junit.Before; -import org.junit.Test; - -import guitests.guihandles.BrowserPanelHandle; -import seedu.address.MainApp; -import seedu.address.commons.events.ui.PersonPanelSelectionChangedEvent; - -public class BrowserPanelTest extends GuiUnitTest { - private PersonPanelSelectionChangedEvent selectionChangedEventStub; - - private BrowserPanel browserPanel; - private BrowserPanelHandle browserPanelHandle; - - @Before - public void setUp() { - selectionChangedEventStub = new PersonPanelSelectionChangedEvent(ALICE); - - guiRobot.interact(() -> browserPanel = new BrowserPanel()); - uiPartRule.setUiPart(browserPanel); - - browserPanelHandle = new BrowserPanelHandle(browserPanel.getRoot()); - } - - @Test - public void display() throws Exception { - // default web page - URL expectedDefaultPageUrl = MainApp.class.getResource(FXML_FILE_FOLDER + DEFAULT_PAGE); - assertEquals(expectedDefaultPageUrl, browserPanelHandle.getLoadedUrl()); - - // associated web page of a person - postNow(selectionChangedEventStub); - URL expectedPersonUrl = new URL(BrowserPanel.SEARCH_PAGE_URL + ALICE.getName().fullName.replaceAll(" ", "%20")); - - waitUntilBrowserLoaded(browserPanelHandle); - assertEquals(expectedPersonUrl, browserPanelHandle.getLoadedUrl()); - } -} diff --git a/src/test/java/seedu/address/ui/CommandBoxTest.java b/src/test/java/seedu/address/ui/CommandBoxTest.java deleted file mode 100644 index f72304570a7a..000000000000 --- a/src/test/java/seedu/address/ui/CommandBoxTest.java +++ /dev/null @@ -1,157 +0,0 @@ -package seedu.address.ui; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; - -import org.junit.Before; -import org.junit.Test; - -import guitests.guihandles.CommandBoxHandle; -import javafx.scene.input.KeyCode; -import seedu.address.logic.Logic; -import seedu.address.logic.LogicManager; -import seedu.address.logic.commands.ListCommand; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; - -public class CommandBoxTest extends GuiUnitTest { - - private static final String COMMAND_THAT_SUCCEEDS = ListCommand.COMMAND_WORD; - private static final String COMMAND_THAT_FAILS = "invalid command"; - - private ArrayList defaultStyleOfCommandBox; - private ArrayList errorStyleOfCommandBox; - - private CommandBoxHandle commandBoxHandle; - - @Before - public void setUp() { - Model model = new ModelManager(); - Logic logic = new LogicManager(model); - - CommandBox commandBox = new CommandBox(logic); - commandBoxHandle = new CommandBoxHandle(getChildNode(commandBox.getRoot(), - CommandBoxHandle.COMMAND_INPUT_FIELD_ID)); - uiPartRule.setUiPart(commandBox); - - defaultStyleOfCommandBox = new ArrayList<>(commandBoxHandle.getStyleClass()); - - errorStyleOfCommandBox = new ArrayList<>(defaultStyleOfCommandBox); - errorStyleOfCommandBox.add(CommandBox.ERROR_STYLE_CLASS); - } - - @Test - public void commandBox_startingWithSuccessfulCommand() { - assertBehaviorForSuccessfulCommand(); - assertBehaviorForFailedCommand(); - } - - @Test - public void commandBox_startingWithFailedCommand() { - assertBehaviorForFailedCommand(); - assertBehaviorForSuccessfulCommand(); - - // verify that style is changed correctly even after multiple consecutive failed commands - assertBehaviorForSuccessfulCommand(); - assertBehaviorForFailedCommand(); - assertBehaviorForFailedCommand(); - } - - @Test - public void commandBox_handleKeyPress() { - commandBoxHandle.run(COMMAND_THAT_FAILS); - assertEquals(errorStyleOfCommandBox, commandBoxHandle.getStyleClass()); - guiRobot.push(KeyCode.ESCAPE); - assertEquals(errorStyleOfCommandBox, commandBoxHandle.getStyleClass()); - - guiRobot.push(KeyCode.A); - assertEquals(defaultStyleOfCommandBox, commandBoxHandle.getStyleClass()); - } - - @Test - public void handleKeyPress_startingWithUp() { - // empty history - assertInputHistory(KeyCode.UP, ""); - assertInputHistory(KeyCode.DOWN, ""); - - // one command - commandBoxHandle.run(COMMAND_THAT_SUCCEEDS); - assertInputHistory(KeyCode.UP, COMMAND_THAT_SUCCEEDS); - assertInputHistory(KeyCode.DOWN, ""); - - // two commands (latest command is failure) - commandBoxHandle.run(COMMAND_THAT_FAILS); - assertInputHistory(KeyCode.UP, COMMAND_THAT_SUCCEEDS); - assertInputHistory(KeyCode.UP, COMMAND_THAT_SUCCEEDS); - assertInputHistory(KeyCode.DOWN, COMMAND_THAT_FAILS); - assertInputHistory(KeyCode.DOWN, ""); - assertInputHistory(KeyCode.DOWN, ""); - assertInputHistory(KeyCode.UP, COMMAND_THAT_FAILS); - - // insert command in the middle of retrieving previous commands - guiRobot.push(KeyCode.UP); - String thirdCommand = "list"; - commandBoxHandle.run(thirdCommand); - assertInputHistory(KeyCode.UP, thirdCommand); - assertInputHistory(KeyCode.UP, COMMAND_THAT_FAILS); - assertInputHistory(KeyCode.UP, COMMAND_THAT_SUCCEEDS); - assertInputHistory(KeyCode.DOWN, COMMAND_THAT_FAILS); - assertInputHistory(KeyCode.DOWN, thirdCommand); - assertInputHistory(KeyCode.DOWN, ""); - } - - @Test - public void handleKeyPress_startingWithDown() { - // empty history - assertInputHistory(KeyCode.DOWN, ""); - assertInputHistory(KeyCode.UP, ""); - - // one command - commandBoxHandle.run(COMMAND_THAT_SUCCEEDS); - assertInputHistory(KeyCode.DOWN, ""); - assertInputHistory(KeyCode.UP, COMMAND_THAT_SUCCEEDS); - - // two commands - commandBoxHandle.run(COMMAND_THAT_FAILS); - assertInputHistory(KeyCode.DOWN, ""); - assertInputHistory(KeyCode.UP, COMMAND_THAT_FAILS); - - // insert command in the middle of retrieving previous commands - guiRobot.push(KeyCode.UP); - String thirdCommand = "list"; - commandBoxHandle.run(thirdCommand); - assertInputHistory(KeyCode.DOWN, ""); - assertInputHistory(KeyCode.UP, thirdCommand); - } - - /** - * Runs a command that fails, then verifies that
    - * - the text remains
    - * - the command box's style is the same as {@code errorStyleOfCommandBox}. - */ - private void assertBehaviorForFailedCommand() { - commandBoxHandle.run(COMMAND_THAT_FAILS); - assertEquals(COMMAND_THAT_FAILS, commandBoxHandle.getInput()); - assertEquals(errorStyleOfCommandBox, commandBoxHandle.getStyleClass()); - } - - /** - * Runs a command that succeeds, then verifies that
    - * - the text is cleared
    - * - the command box's style is the same as {@code defaultStyleOfCommandBox}. - */ - private void assertBehaviorForSuccessfulCommand() { - commandBoxHandle.run(COMMAND_THAT_SUCCEEDS); - assertEquals("", commandBoxHandle.getInput()); - assertEquals(defaultStyleOfCommandBox, commandBoxHandle.getStyleClass()); - } - - /** - * Pushes {@code keycode} and checks that the input in the {@code commandBox} equals to {@code expectedCommand}. - */ - private void assertInputHistory(KeyCode keycode, String expectedCommand) { - guiRobot.push(keycode); - assertEquals(expectedCommand, commandBoxHandle.getInput()); - } -} diff --git a/src/test/java/seedu/address/ui/GuiUnitTest.java b/src/test/java/seedu/address/ui/GuiUnitTest.java deleted file mode 100644 index f1ff0656725a..000000000000 --- a/src/test/java/seedu/address/ui/GuiUnitTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package seedu.address.ui; - -import java.util.Optional; - -import org.junit.After; -import org.junit.Rule; - -import guitests.GuiRobot; -import guitests.guihandles.exceptions.NodeNotFoundException; -import javafx.scene.Node; -import seedu.address.commons.core.EventsCenter; -import seedu.address.ui.testutil.UiPartRule; - -/** - * A GUI unit test class for AddressBook. - */ -public abstract class GuiUnitTest { - @Rule - public final UiPartRule uiPartRule = new UiPartRule(); - - protected final GuiRobot guiRobot = new GuiRobot(); - - @After - public void tearDown() { - EventsCenter.clearSubscribers(); - } - - /** - * Retrieves the {@code query} node owned by the {@code rootNode}. - * - * @param query name of the CSS selector of the node to retrieve. - * @throws NodeNotFoundException if no such node exists. - */ - protected T getChildNode(Node rootNode, String query) { - Optional node = guiRobot.from(rootNode).lookup(query).tryQuery(); - return node.orElseThrow(NodeNotFoundException::new); - } -} diff --git a/src/test/java/seedu/address/ui/HelpWindowTest.java b/src/test/java/seedu/address/ui/HelpWindowTest.java deleted file mode 100644 index 20d721cd0e45..000000000000 --- a/src/test/java/seedu/address/ui/HelpWindowTest.java +++ /dev/null @@ -1,69 +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 org.junit.Assume.assumeFalse; -import static seedu.address.ui.HelpWindow.USERGUIDE_FILE_PATH; - -import java.net.URL; - -import org.junit.Before; -import org.junit.Test; -import org.testfx.api.FxToolkit; - -import guitests.guihandles.HelpWindowHandle; -import javafx.stage.Stage; - -public class HelpWindowTest extends GuiUnitTest { - - private HelpWindow helpWindow; - private HelpWindowHandle helpWindowHandle; - - @Before - public void setUp() throws Exception { - guiRobot.interact(() -> helpWindow = new HelpWindow()); - FxToolkit.registerStage(helpWindow::getRoot); - helpWindowHandle = new HelpWindowHandle(helpWindow.getRoot()); - } - - @Test - public void display() throws Exception { - FxToolkit.showStage(); - URL expectedHelpPage = HelpWindow.class.getResource(USERGUIDE_FILE_PATH); - assertEquals(expectedHelpPage, helpWindowHandle.getLoadedUrl()); - } - - @Test - public void isShowing_helpWindowIsShowing_returnsTrue() { - guiRobot.interact(helpWindow::show); - assertTrue(helpWindow.isShowing()); - } - - @Test - public void isShowing_helpWindowIsHiding_returnsFalse() { - assertFalse(helpWindow.isShowing()); - } - - @Test - public void focus_helpWindowNotFocused_focused() throws Exception { - // TODO: This test skip can be removed once this bug is fixed: - // https://github.com/javafxports/openjdk-jfx/issues/50 - // - // When there are two stages (stage1 and stage2) shown, - // stage1 is in focus and stage2.requestFocus() is called, - // we expect that stage1.isFocused() will return false while - // stage2.isFocused() returns true. However, as reported in the bug report, - // both stage1.isFocused() and stage2.isFocused() returns true, - // which fails the test. - assumeFalse("Test skipped in headless mode: Window focus behavior is buggy.", guiRobot.isHeadlessMode()); - guiRobot.interact(helpWindow::show); - - // Focus on another stage to remove focus from the helpWindow - FxToolkit.setupStage(Stage::requestFocus); - assertFalse(helpWindow.getRoot().isFocused()); - - guiRobot.interact(helpWindow::focus); - assertTrue(helpWindow.getRoot().isFocused()); - } -} diff --git a/src/test/java/seedu/address/ui/MainWindowCloseTest.java b/src/test/java/seedu/address/ui/MainWindowCloseTest.java deleted file mode 100644 index 6321f255b048..000000000000 --- a/src/test/java/seedu/address/ui/MainWindowCloseTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package seedu.address.ui; - -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.testfx.api.FxToolkit; - -import guitests.guihandles.StageHandle; -import javafx.stage.Stage; -import javafx.stage.WindowEvent; -import seedu.address.commons.core.Config; -import seedu.address.commons.events.ui.ExitAppRequestEvent; -import seedu.address.logic.LogicManager; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.ui.testutil.EventsCollectorRule; - -/** - * Contains tests for closing of the {@code MainWindow}. - */ -public class MainWindowCloseTest extends GuiUnitTest { - @Rule - public final EventsCollectorRule eventsCollectorRule = new EventsCollectorRule(); - - private MainWindow mainWindow; - private EmptyMainWindowHandle mainWindowHandle; - private Stage stage; - - @Before - public void setUp() throws Exception { - FxToolkit.setupStage(stage -> { - this.stage = stage; - mainWindow = new MainWindow(stage, new Config(), new UserPrefs(), new LogicManager(new ModelManager())); - mainWindowHandle = new EmptyMainWindowHandle(stage); - - stage.setScene(mainWindow.getRoot().getScene()); - mainWindowHandle.focus(); - }); - FxToolkit.showStage(); - } - - @Test - public void close_menuBarExitButton_exitAppRequestEventPosted() { - mainWindowHandle.clickOnMenuExitButton(); - assertTrue(eventsCollectorRule.eventsCollector.getMostRecent() instanceof ExitAppRequestEvent); - assertTrue(eventsCollectorRule.eventsCollector.getSize() == 1); - } - - @Test - public void close_externalRequest_exitAppRequestEventPosted() { - mainWindowHandle.closeMainWindowExternally(); - assertTrue(eventsCollectorRule.eventsCollector.getMostRecent() instanceof ExitAppRequestEvent); - assertTrue(eventsCollectorRule.eventsCollector.getSize() == 1); - } - - /** - * A handle for an empty {@code MainWindow}. The components in {@code MainWindow} are not initialized. - */ - private class EmptyMainWindowHandle extends StageHandle { - - private EmptyMainWindowHandle(Stage stage) { - super(stage); - } - - /** - * Closes the {@code MainWindow} by clicking on the menu bar's exit button. - */ - private void clickOnMenuExitButton() { - guiRobot.clickOn("File"); - guiRobot.clickOn("Exit"); - } - - /** - * Closes the {@code MainWindow} through an external request {@code MainWindow} (e.g pressing the 'X' button on - * the {@code MainWindow} or closing the app through the taskbar). - */ - private void closeMainWindowExternally() { - guiRobot.interact(() -> stage.fireEvent(new WindowEvent(stage, WindowEvent.WINDOW_CLOSE_REQUEST))); - } - } -} 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/PersonListPanelTest.java b/src/test/java/seedu/address/ui/PersonListPanelTest.java deleted file mode 100644 index 24c015565eb3..000000000000 --- a/src/test/java/seedu/address/ui/PersonListPanelTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package seedu.address.ui; - -import static java.time.Duration.ofMillis; -import static org.junit.Assert.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; -import static seedu.address.testutil.EventsUtil.postNow; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalPersons; -import static seedu.address.ui.testutil.GuiTestAssert.assertCardDisplaysPerson; -import static seedu.address.ui.testutil.GuiTestAssert.assertCardEquals; - -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.Test; - -import guitests.guihandles.PersonCardHandle; -import guitests.guihandles.PersonListPanelHandle; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import seedu.address.commons.events.ui.JumpToListRequestEvent; -import seedu.address.commons.util.FileUtil; -import seedu.address.commons.util.XmlUtil; -import seedu.address.model.person.Person; -import seedu.address.storage.XmlSerializableAddressBook; - -public class PersonListPanelTest extends GuiUnitTest { - private static final ObservableList TYPICAL_PERSONS = - FXCollections.observableList(getTypicalPersons()); - - private static final JumpToListRequestEvent JUMP_TO_SECOND_EVENT = new JumpToListRequestEvent(INDEX_SECOND_PERSON); - - private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "sandbox"); - - private static final long CARD_CREATION_AND_DELETION_TIMEOUT = 2500; - - private PersonListPanelHandle personListPanelHandle; - - @Test - public void display() { - initUi(TYPICAL_PERSONS); - - for (int i = 0; i < TYPICAL_PERSONS.size(); i++) { - personListPanelHandle.navigateToCard(TYPICAL_PERSONS.get(i)); - Person expectedPerson = TYPICAL_PERSONS.get(i); - PersonCardHandle actualCard = personListPanelHandle.getPersonCardHandle(i); - - assertCardDisplaysPerson(expectedPerson, actualCard); - assertEquals(Integer.toString(i + 1) + ". ", actualCard.getId()); - } - } - - @Test - public void handleJumpToListRequestEvent() { - initUi(TYPICAL_PERSONS); - postNow(JUMP_TO_SECOND_EVENT); - guiRobot.pauseForHuman(); - - PersonCardHandle expectedPerson = personListPanelHandle.getPersonCardHandle(INDEX_SECOND_PERSON.getZeroBased()); - PersonCardHandle selectedPerson = personListPanelHandle.getHandleToSelectedCard(); - assertCardEquals(expectedPerson, selectedPerson); - } - - /** - * Verifies that creating and deleting large number of persons in {@code PersonListPanel} requires lesser than - * {@code CARD_CREATION_AND_DELETION_TIMEOUT} milliseconds to execute. - */ - @Test - public void performanceTest() throws Exception { - ObservableList backingList = createBackingList(10000); - - assertTimeoutPreemptively(ofMillis(CARD_CREATION_AND_DELETION_TIMEOUT), () -> { - initUi(backingList); - guiRobot.interact(backingList::clear); - }, "Creation and deletion of person cards exceeded time limit"); - } - - /** - * Returns a list of persons containing {@code personCount} persons that is used to populate the - * {@code PersonListPanel}. - */ - private ObservableList createBackingList(int personCount) throws Exception { - Path xmlFile = createXmlFileWithPersons(personCount); - XmlSerializableAddressBook xmlAddressBook = - XmlUtil.getDataFromFile(xmlFile, XmlSerializableAddressBook.class); - return FXCollections.observableArrayList(xmlAddressBook.toModelType().getPersonList()); - } - - /** - * Returns a .xml file containing {@code personCount} persons. This file will be deleted when the JVM terminates. - */ - private Path createXmlFileWithPersons(int personCount) throws Exception { - StringBuilder builder = new StringBuilder(); - builder.append("\n"); - builder.append("\n"); - for (int i = 0; i < personCount; i++) { - builder.append("\n"); - builder.append("").append(i).append("a\n"); - builder.append("000\n"); - builder.append("a@aa\n"); - builder.append("
    a
    \n"); - builder.append("
    \n"); - } - builder.append("
    \n"); - - Path manyPersonsFile = Paths.get(TEST_DATA_FOLDER + "manyPersons.xml"); - FileUtil.createFile(manyPersonsFile); - FileUtil.writeToFile(manyPersonsFile, builder.toString()); - manyPersonsFile.toFile().deleteOnExit(); - return manyPersonsFile; - } - - /** - * Initializes {@code personListPanelHandle} with a {@code PersonListPanel} backed by {@code backingList}. - * Also shows the {@code Stage} that displays only {@code PersonListPanel}. - */ - private void initUi(ObservableList backingList) { - PersonListPanel personListPanel = new PersonListPanel(backingList); - uiPartRule.setUiPart(personListPanel); - - personListPanelHandle = new PersonListPanelHandle(getChildNode(personListPanel.getRoot(), - PersonListPanelHandle.PERSON_LIST_VIEW_ID)); - } -} diff --git a/src/test/java/seedu/address/ui/ResultDisplayTest.java b/src/test/java/seedu/address/ui/ResultDisplayTest.java deleted file mode 100644 index acea62615ff4..000000000000 --- a/src/test/java/seedu/address/ui/ResultDisplayTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package seedu.address.ui; - -import static org.junit.Assert.assertEquals; -import static seedu.address.testutil.EventsUtil.postNow; - -import org.junit.Before; -import org.junit.Test; - -import guitests.guihandles.ResultDisplayHandle; -import seedu.address.commons.events.ui.NewResultAvailableEvent; - -public class ResultDisplayTest extends GuiUnitTest { - - private static final NewResultAvailableEvent NEW_RESULT_EVENT_STUB = new NewResultAvailableEvent("Stub"); - - private ResultDisplayHandle resultDisplayHandle; - - @Before - public void setUp() { - ResultDisplay resultDisplay = new ResultDisplay(); - uiPartRule.setUiPart(resultDisplay); - - resultDisplayHandle = new ResultDisplayHandle(getChildNode(resultDisplay.getRoot(), - ResultDisplayHandle.RESULT_DISPLAY_ID)); - } - - @Test - public void display() { - // default result text - guiRobot.pauseForHuman(); - assertEquals("", resultDisplayHandle.getText()); - - // new result received - postNow(NEW_RESULT_EVENT_STUB); - guiRobot.pauseForHuman(); - assertEquals(NEW_RESULT_EVENT_STUB.message, resultDisplayHandle.getText()); - } -} diff --git a/src/test/java/seedu/address/ui/StatusBarFooterTest.java b/src/test/java/seedu/address/ui/StatusBarFooterTest.java deleted file mode 100644 index c7d21684a472..000000000000 --- a/src/test/java/seedu/address/ui/StatusBarFooterTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package seedu.address.ui; - -import static org.junit.Assert.assertEquals; -import static seedu.address.testutil.EventsUtil.postNow; -import static seedu.address.ui.StatusBarFooter.SYNC_STATUS_INITIAL; -import static seedu.address.ui.StatusBarFooter.SYNC_STATUS_UPDATED; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.util.Date; - -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import guitests.guihandles.StatusBarFooterHandle; -import seedu.address.commons.events.model.AddressBookChangedEvent; -import seedu.address.model.AddressBook; - -public class StatusBarFooterTest extends GuiUnitTest { - - private static final Path STUB_SAVE_LOCATION = Paths.get("Stub"); - private static final Path RELATIVE_PATH = Paths.get("."); - - private static final AddressBookChangedEvent EVENT_STUB = new AddressBookChangedEvent(new AddressBook()); - - private static final Clock originalClock = StatusBarFooter.getClock(); - private static final Clock injectedClock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); - - private StatusBarFooterHandle statusBarFooterHandle; - - @BeforeClass - public static void setUpBeforeClass() { - // inject fixed clock - StatusBarFooter.setClock(injectedClock); - } - - @AfterClass - public static void tearDownAfterClass() { - // restore original clock - StatusBarFooter.setClock(originalClock); - } - - @Before - public void setUp() { - StatusBarFooter statusBarFooter = new StatusBarFooter(STUB_SAVE_LOCATION); - uiPartRule.setUiPart(statusBarFooter); - - statusBarFooterHandle = new StatusBarFooterHandle(statusBarFooter.getRoot()); - } - - @Test - public void display() { - // initial state - assertStatusBarContent(RELATIVE_PATH.resolve(STUB_SAVE_LOCATION).toString(), SYNC_STATUS_INITIAL); - - // after address book is updated - postNow(EVENT_STUB); - assertStatusBarContent(RELATIVE_PATH.resolve(STUB_SAVE_LOCATION).toString(), - String.format(SYNC_STATUS_UPDATED, new Date(injectedClock.millis()).toString())); - } - - /** - * Asserts that the save location matches that of {@code expectedSaveLocation}, and the - * sync status matches that of {@code expectedSyncStatus}. - */ - private void assertStatusBarContent(String expectedSaveLocation, String expectedSyncStatus) { - assertEquals(expectedSaveLocation, statusBarFooterHandle.getSaveLocation()); - assertEquals(expectedSyncStatus, statusBarFooterHandle.getSyncStatus()); - guiRobot.pauseForHuman(); - } - -} diff --git a/src/test/java/seedu/address/ui/TestFxmlObject.java b/src/test/java/seedu/address/ui/TestFxmlObject.java deleted file mode 100644 index 5ecd82656f25..000000000000 --- a/src/test/java/seedu/address/ui/TestFxmlObject.java +++ /dev/null @@ -1,35 +0,0 @@ -package seedu.address.ui; - -import javafx.beans.DefaultProperty; - -/** - * A test object which can be constructed via an FXML file. - * Unlike other JavaFX classes, this class can be constructed without the JavaFX toolkit being initialized. - */ -@DefaultProperty("text") -public class TestFxmlObject { - - private String text; - - public TestFxmlObject() {} - - public TestFxmlObject(String text) { - setText(text); - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof TestFxmlObject // instanceof handles nulls - && text.equals(((TestFxmlObject) other).getText())); - } - -} diff --git a/src/test/java/seedu/address/ui/UiPartTest.java b/src/test/java/seedu/address/ui/UiPartTest.java deleted file mode 100644 index 00bffd0d5608..000000000000 --- a/src/test/java/seedu/address/ui/UiPartTest.java +++ /dev/null @@ -1,118 +0,0 @@ -package seedu.address.ui; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.net.URL; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; - -import javafx.fxml.FXML; -import seedu.address.MainApp; -import seedu.address.testutil.Assert; - -public class UiPartTest { - - private static final String MISSING_FILE_PATH = "UiPartTest/missingFile.fxml"; - private static final String INVALID_FILE_PATH = "UiPartTest/invalidFile.fxml"; - private static final String VALID_FILE_PATH = "UiPartTest/validFile.fxml"; - private static final String VALID_FILE_WITH_FX_ROOT_PATH = "UiPartTest/validFileWithFxRoot.fxml"; - private static final TestFxmlObject VALID_FILE_ROOT = new TestFxmlObject("Hello World!"); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Rule - public TemporaryFolder testFolder = new TemporaryFolder(); - - @Test - public void constructor_nullFileUrl_throwsNullPointerException() { - Assert.assertThrows(NullPointerException.class, () -> new TestUiPart((URL) null)); - Assert.assertThrows(NullPointerException.class, () -> new TestUiPart((URL) null, new Object())); - } - - @Test - public void constructor_missingFileUrl_throwsAssertionError() throws Exception { - URL missingFileUrl = new URL(testFolder.getRoot().toURI().toURL(), MISSING_FILE_PATH); - Assert.assertThrows(AssertionError.class, () -> new TestUiPart(missingFileUrl)); - Assert.assertThrows(AssertionError.class, () -> new TestUiPart(missingFileUrl, new Object())); - } - - @Test - public void constructor_invalidFileUrl_throwsAssertionError() { - URL invalidFileUrl = getTestFileUrl(INVALID_FILE_PATH); - Assert.assertThrows(AssertionError.class, () -> new TestUiPart(invalidFileUrl)); - Assert.assertThrows(AssertionError.class, () -> new TestUiPart(invalidFileUrl, new Object())); - } - - @Test - public void constructor_validFileUrl_loadsFile() { - URL validFileUrl = getTestFileUrl(VALID_FILE_PATH); - assertEquals(VALID_FILE_ROOT, new TestUiPart(validFileUrl).getRoot()); - } - - @Test - public void constructor_validFileWithFxRootUrl_loadsFile() { - URL validFileUrl = getTestFileUrl(VALID_FILE_WITH_FX_ROOT_PATH); - TestFxmlObject root = new TestFxmlObject(); - assertEquals(VALID_FILE_ROOT, new TestUiPart(validFileUrl, root).getRoot()); - } - - @Test - public void constructor_nullFileName_throwsNullPointerException() { - Assert.assertThrows(NullPointerException.class, () -> new TestUiPart((String) null)); - Assert.assertThrows(NullPointerException.class, () -> new TestUiPart((String) null, new Object())); - } - - @Test - public void constructor_missingFileName_throwsNullPointerException() { - Assert.assertThrows(NullPointerException.class, () -> new TestUiPart(MISSING_FILE_PATH)); - Assert.assertThrows(NullPointerException.class, () -> new TestUiPart(MISSING_FILE_PATH, new Object())); - } - - @Test - public void constructor_invalidFileName_throwsAssertionError() { - Assert.assertThrows(AssertionError.class, () -> new TestUiPart(INVALID_FILE_PATH)); - Assert.assertThrows(AssertionError.class, () -> new TestUiPart(INVALID_FILE_PATH, new Object())); - } - - private URL getTestFileUrl(String testFilePath) { - String testFilePathInView = "/view/" + testFilePath; - URL testFileUrl = MainApp.class.getResource(testFilePathInView); - assertNotNull(testFilePathInView + " does not exist.", testFileUrl); - return testFileUrl; - } - - /** - * UiPart used for testing. - * It should only be used with invalid FXML files or the valid file located at {@link VALID_FILE_PATH}. - */ - private static class TestUiPart extends UiPart { - - @FXML - private TestFxmlObject validFileRoot; // Check that @FXML annotations work - - TestUiPart(URL fxmlFileUrl, T root) { - super(fxmlFileUrl, root); - } - - TestUiPart(String fxmlFileName, T root) { - super(fxmlFileName, root); - } - - TestUiPart(URL fxmlFileUrl) { - super(fxmlFileUrl); - assertEquals(VALID_FILE_ROOT, validFileRoot); - } - - TestUiPart(String fxmlFileName) { - super(fxmlFileName); - assertEquals(VALID_FILE_ROOT, validFileRoot); - } - - } - -} diff --git a/src/test/java/systemtests/AddCommandSystemTest.java b/src/test/java/systemtests/AddCommandSystemTest.java deleted file mode 100644 index c656bca6f0fd..000000000000 --- a/src/test/java/systemtests/AddCommandSystemTest.java +++ /dev/null @@ -1,248 +0,0 @@ -package systemtests; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; -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_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.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_PHONE_BOB; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.AMY; -import static seedu.address.testutil.TypicalPersons.BOB; -import static seedu.address.testutil.TypicalPersons.CARL; -import static seedu.address.testutil.TypicalPersons.HOON; -import static seedu.address.testutil.TypicalPersons.IDA; -import static seedu.address.testutil.TypicalPersons.KEYWORD_MATCHING_MEIER; - -import org.junit.Test; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.AddCommand; -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.tag.Tag; -import seedu.address.testutil.PersonBuilder; -import seedu.address.testutil.PersonUtil; - -public class AddCommandSystemTest extends AddressBookSystemTest { - - @Test - public void add() { - Model model = getModel(); - - /* ------------------------ 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 - * -> added - */ - Person 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); - - /* Case: undo adding Amy to the list -> Amy deleted */ - command = UndoCommand.COMMAND_WORD; - String expectedResultMessage = UndoCommand.MESSAGE_SUCCESS; - assertCommandSuccess(command, model, expectedResultMessage); - - /* Case: redo adding Amy to the list -> Amy added again */ - command = RedoCommand.COMMAND_WORD; - model.addPerson(toAdd); - 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 */ - toAdd = new PersonBuilder(AMY).withName(VALID_NAME_BOB).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 and email - * -> added - */ - toAdd = new PersonBuilder(AMY).withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).build(); - command = PersonUtil.getAddCommand(toAdd); - assertCommandSuccess(command, toAdd); - - /* Case: add to empty address book -> added */ - deleteAllPersons(); - assertCommandSuccess(ALICE); - - /* Case: add a person 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 */ - assertCommandSuccess(HOON); - - /* -------------------------- Perform add operation on the shown filtered list ------------------------------ */ - - /* Case: filters the person list before adding -> added */ - showPersonsWithName(KEYWORD_MATCHING_MEIER); - assertCommandSuccess(IDA); - - /* ------------------------ Perform add operation while a person card is selected --------------------------- */ - - /* Case: selects first card in the person list, add a person -> added, card selection remains unchanged */ - selectPerson(Index.fromOneBased(1)); - assertCommandSuccess(CARL); - - /* ----------------------------------- Perform invalid add operations --------------------------------------- */ - - /* Case: add a duplicate person -> rejected */ - command = PersonUtil.getAddCommand(HOON); - assertCommandFailure(command, AddCommand.MESSAGE_DUPLICATE_PERSON); - - /* Case: add a duplicate person except with different phone -> rejected */ - toAdd = new PersonBuilder(HOON).withPhone(VALID_PHONE_BOB).build(); - command = PersonUtil.getAddCommand(toAdd); - assertCommandFailure(command, AddCommand.MESSAGE_DUPLICATE_PERSON); - - /* Case: add a duplicate person except with different email -> rejected */ - toAdd = new PersonBuilder(HOON).withEmail(VALID_EMAIL_BOB).build(); - command = PersonUtil.getAddCommand(toAdd); - assertCommandFailure(command, AddCommand.MESSAGE_DUPLICATE_PERSON); - - /* Case: add a duplicate person except with different address -> rejected */ - toAdd = new PersonBuilder(HOON).withAddress(VALID_ADDRESS_BOB).build(); - command = PersonUtil.getAddCommand(toAdd); - assertCommandFailure(command, AddCommand.MESSAGE_DUPLICATE_PERSON); - - /* Case: add a duplicate person except with different tags -> rejected */ - command = PersonUtil.getAddCommand(HOON) + " " + PREFIX_TAG.getPrefix() + "friends"; - assertCommandFailure(command, AddCommand.MESSAGE_DUPLICATE_PERSON); - - /* Case: missing name -> rejected */ - command = AddCommand.COMMAND_WORD + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY; - 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; - 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; - 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; - assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); - - /* Case: invalid keyword -> rejected */ - command = "adds " + PersonUtil.getPersonDetails(toAdd); - 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); - - /* Case: invalid phone -> rejected */ - command = AddCommand.COMMAND_WORD + NAME_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; - 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; - 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 - + INVALID_TAG_DESC; - assertCommandFailure(command, Tag.MESSAGE_TAG_CONSTRAINTS); - } - - /** - * Executes the {@code AddCommand} that adds {@code toAdd} to the model and asserts that the,
    - * 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 {@code AddCommand} with the details of - * {@code toAdd}.
    - * 4. {@code Storage} and {@code PersonListPanel} equal to the corresponding components in - * the current model added with {@code toAdd}.
    - * 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) - */ - private void assertCommandSuccess(Person toAdd) { - assertCommandSuccess(PersonUtil.getAddCommand(toAdd), toAdd); - } - - /** - * Performs the same verification as {@code assertCommandSuccess(Person)}. Executes {@code command} - * instead. - * @see AddCommandSystemTest#assertCommandSuccess(Person) - */ - private void assertCommandSuccess(String command, Person toAdd) { - Model expectedModel = getModel(); - expectedModel.addPerson(toAdd); - String expectedResultMessage = String.format(AddCommand.MESSAGE_SUCCESS, toAdd); - - assertCommandSuccess(command, expectedModel, expectedResultMessage); - } - - /** - * Performs the same verification as {@code assertCommandSuccess(String, Person)} except asserts that - * the,
    - * 1. Result display box displays {@code expectedResultMessage}.
    - * 2. {@code Storage} and {@code PersonListPanel} equal to the corresponding components in - * {@code expectedModel}.
    - * @see AddCommandSystemTest#assertCommandSuccess(String, Person) - */ - private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage) { - executeCommand(command); - assertApplicationDisplaysExpected("", expectedResultMessage, expectedModel); - assertSelectedCardUnchanged(); - assertCommandBoxShowsDefaultStyle(); - assertStatusBarUnchangedExceptSyncStatus(); - } - - /** - * Executes {@code command} and asserts that the,
    - * 1. Command box displays {@code command}.
    - * 2. Command box has the error style class.
    - * 3. Result display box displays {@code expectedResultMessage}.
    - * 4. {@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) - */ - private void assertCommandFailure(String command, String expectedResultMessage) { - Model expectedModel = getModel(); - - executeCommand(command); - assertApplicationDisplaysExpected(command, expectedResultMessage, expectedModel); - assertSelectedCardUnchanged(); - assertCommandBoxShowsErrorStyle(); - assertStatusBarUnchanged(); - } -} diff --git a/src/test/java/systemtests/ClearCommandSystemTest.java b/src/test/java/systemtests/ClearCommandSystemTest.java deleted file mode 100644 index 805a59784e29..000000000000 --- a/src/test/java/systemtests/ClearCommandSystemTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package systemtests; - -import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; -import static seedu.address.testutil.TypicalPersons.KEYWORD_MATCHING_MEIER; - -import org.junit.Test; - -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.ClearCommand; -import seedu.address.logic.commands.RedoCommand; -import seedu.address.logic.commands.UndoCommand; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; - -public class ClearCommandSystemTest extends AddressBookSystemTest { - - @Test - public void clear() { - final Model defaultModel = getModel(); - - /* Case: clear non-empty address book, 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 */ - String command = UndoCommand.COMMAND_WORD; - String expectedResultMessage = UndoCommand.MESSAGE_SUCCESS; - assertCommandSuccess(command, expectedResultMessage, defaultModel); - assertSelectedCardUnchanged(); - - /* Case: redo clearing address book -> 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 - 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 - showPersonsWithName(KEYWORD_MATCHING_MEIER); - assertCommandSuccess(ClearCommand.COMMAND_WORD); - assertSelectedCardUnchanged(); - - /* Case: clear empty address book -> cleared */ - assertCommandSuccess(ClearCommand.COMMAND_WORD); - assertSelectedCardUnchanged(); - - /* Case: mixed case command word -> rejected */ - assertCommandFailure("ClEaR", MESSAGE_UNKNOWN_COMMAND); - } - - /** - * 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)}.
    - * 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) - */ - private void assertCommandSuccess(String command) { - assertCommandSuccess(command, ClearCommand.MESSAGE_SUCCESS, new ModelManager()); - } - - /** - * Performs the same verification as {@code assertCommandSuccess(String)} except that the result box displays - * {@code expectedResultMessage} and the model related components equal to {@code expectedModel}. - * @see ClearCommandSystemTest#assertCommandSuccess(String) - */ - private void assertCommandSuccess(String command, String expectedResultMessage, Model expectedModel) { - executeCommand(command); - assertApplicationDisplaysExpected("", expectedResultMessage, expectedModel); - assertCommandBoxShowsDefaultStyle(); - assertStatusBarUnchangedExceptSyncStatus(); - } - - /** - * 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)}.
    - * 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) - */ - private void assertCommandFailure(String command, String expectedResultMessage) { - Model expectedModel = getModel(); - - executeCommand(command); - assertApplicationDisplaysExpected(command, expectedResultMessage, expectedModel); - assertSelectedCardUnchanged(); - assertCommandBoxShowsErrorStyle(); - assertStatusBarUnchanged(); - } -} diff --git a/src/test/java/systemtests/ClockRule.java b/src/test/java/systemtests/ClockRule.java index 6beace668e61..147538549685 100644 --- a/src/test/java/systemtests/ClockRule.java +++ b/src/test/java/systemtests/ClockRule.java @@ -8,7 +8,7 @@ import org.junit.runner.Description; import org.junit.runners.model.Statement; -import seedu.address.ui.StatusBarFooter; +import com.t13g2.forum.ui.StatusBarFooter; /** * This rule makes the time stamp in the status bar predictable during a test. diff --git a/src/test/java/systemtests/CreateModuleCommandSystemTest.java b/src/test/java/systemtests/CreateModuleCommandSystemTest.java new file mode 100644 index 000000000000..7c64673722e1 --- /dev/null +++ b/src/test/java/systemtests/CreateModuleCommandSystemTest.java @@ -0,0 +1,157 @@ +// package systemtests; +// +// import static com.t13g2.forum.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +// import static com.t13g2.forum.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; +// import static com.t13g2.forum.logic.commands.CommandTestUtil.INVALID_MODULE_CODE_DESC; +// import static com.t13g2.forum.logic.commands.CommandTestUtil.INVALID_MODULE_TITLE_DESC; +// import static com.t13g2.forum.logic.commands.CommandTestUtil.MODULE_CODE_DESC_CS1231; +// import static com.t13g2.forum.logic.commands.CommandTestUtil.MODULE_CODE_DESC_GET1020; +// import static com.t13g2.forum.logic.commands.CommandTestUtil.MODULE_CODE_DESC_MA1508E; +// import static com.t13g2.forum.logic.commands.CommandTestUtil.MODULE_TITLE_DESC_CS1231; +// import static com.t13g2.forum.logic.commands.CommandTestUtil.MODULE_TITLE_DESC_MA1508E; +// import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_MODULE_CODE_GET1020; +// import static com.t13g2.forum.logic.commands.CommandTestUtil.VALID_MODULE_TITLE_MA1508E; +// import static com.t13g2.forum.testutil.TypicalModules.CS1231; +// import static com.t13g2.forum.testutil.TypicalModules.MA1508E; +// +// import org.junit.Test; +// +// import com.t13g2.forum.logic.commands.CreateModuleCommand; +// import com.t13g2.forum.model.Context; +// import com.t13g2.forum.model.Model; +// import com.t13g2.forum.model.forum.Module; +// import com.t13g2.forum.model.forum.User; +// import com.t13g2.forum.testutil.ModuleBuilder; +// import com.t13g2.forum.testutil.ModuleUtil; +// import com.t13g2.forum.testutil.UserBuilder; +// +// //@@author xllx1 +// public class CreateModuleCommandSystemTest extends ForumBookSystemTest { +// +// @Test +// public void add() { +// //set the current logged in user as an admin. +// User validAdmin = new UserBuilder().build(); +// Context.getInstance().setCurrentUser(validAdmin); +// +// /* Case: add a new module to forum book, command with leading spaces and trailing spaces +// * -> added +// */ +// Module toAdd = MA1508E; +// String command = " " + CreateModuleCommand.COMMAND_WORD + " " + MODULE_CODE_DESC_MA1508E + " " +// + MODULE_TITLE_DESC_MA1508E + " "; +// assertCommandSuccess(command, toAdd); +// +// /* Case: add a module with all fields same as another module in the forum book except code -> added */ +// toAdd = new ModuleBuilder(MA1508E).withCode(VALID_MODULE_CODE_GET1020).build(); +// command = CreateModuleCommand.COMMAND_WORD + MODULE_CODE_DESC_GET1020 + MODULE_TITLE_DESC_MA1508E; +// assertCommandSuccess(command, toAdd); +// +// /* Case: add a module with parameters in random order -> added */ +// toAdd = CS1231; +// command = CreateModuleCommand.COMMAND_WORD + MODULE_TITLE_DESC_CS1231 + MODULE_CODE_DESC_CS1231; +// assertCommandSuccess(command, toAdd); +// +// /* ------------------------------- Perform invalid add operations ----------------------------------- */ +// +// /* Case: add a duplicate module -> rejected */ +// command = ModuleUtil.getCreateCommand(CS1231); +// assertCommandFailure(command, String.format(CreateModuleCommand.MESSAGE_DUPLICATE_MODULE, +// CS1231.getModuleCode())); +// +// /* Case: add a duplicate module except with different title -> rejected */ +// toAdd = new ModuleBuilder(CS1231).withTitle(VALID_MODULE_TITLE_MA1508E).build(); +// command = ModuleUtil.getCreateCommand(toAdd); +// assertCommandFailure(command, String.format(CreateModuleCommand.MESSAGE_DUPLICATE_MODULE, +// CS1231.getModuleCode())); +// +// /* Case: missing code -> rejected */ +// command = CreateModuleCommand.COMMAND_WORD + MODULE_TITLE_DESC_MA1508E; +// assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, +// CreateModuleCommand.MESSAGE_USAGE)); +// +// /* Case: missing title -> rejected */ +// command = CreateModuleCommand.COMMAND_WORD + MODULE_CODE_DESC_MA1508E; +// assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, +// CreateModuleCommand.MESSAGE_USAGE)); +// +// /* Case: invalid keyword -> rejected */ +// command = "creates " + ModuleUtil.getModuleDetails(toAdd); +// assertCommandFailure(command, MESSAGE_UNKNOWN_COMMAND); +// +// /* Case: invalid cpde -> rejected */ +// command = CreateModuleCommand.COMMAND_WORD + INVALID_MODULE_CODE_DESC + MODULE_TITLE_DESC_MA1508E; +// assertCommandFailure(command, Module.MESSAGE_MODULE_CODE_CONSTRAINTS); +// +// /* Case: invalid title -> rejected */ +// command = CreateModuleCommand.COMMAND_WORD + MODULE_CODE_DESC_MA1508E + INVALID_MODULE_TITLE_DESC; +// assertCommandFailure(command, Module.MESSAGE_MODULE_TITLE_CONSTRAINTS); +// } +// +// /** +// * Executes the {@code CreateModuleCommand} that adds {@code toAdd} to the model and asserts that the,
    +// * 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 +// * {@code CreateModuleCommand} with the details of +// * {@code toAdd}.
    +// * 4. {@code Storage} and {@code PersonListPanel} equal to the corresponding components in +// * the current model added with {@code toAdd}.
    +// * 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 ForumBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) +// */ +// private void assertCommandSuccess(Module toAdd) { +// assertCommandSuccess(ModuleUtil.getCreateCommand(toAdd), toAdd); +// } +// +// /** +// * Performs the same verification as {@code assertCommandSuccess(Person)}. Executes {@code command} +// * instead. +// * @see CreateModuleCommandSystemTest#assertCommandSuccess(Module) +// */ +// private void assertCommandSuccess(String command, Module toAdd) { +// Model expectedModel = getModel(); +// String expectedResultMessage = String.format(CreateModuleCommand.MESSAGE_SUCCESS, toAdd.getModuleCode()); +// +// assertCommandSuccess(command, expectedModel, expectedResultMessage); +// } +// +// /** +// * Performs the same verification as {@code assertCommandSuccess(String, Person)} except asserts that +// * the,
    +// * 1. Result display box displays {@code expectedResultMessage}.
    +// * 2. {@code Storage} and {@code PersonListPanel} equal to the corresponding components in +// * {@code expectedModel}.
    +// * @see CreateModuleCommandSystemTest#assertCommandSuccess(String, Module) +// */ +// private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage) { +// executeCommand(command); +// assertApplicationDisplaysExpected(command, expectedResultMessage, expectedModel); +// assertSelectedCardUnchanged(); +// assertCommandBoxShowsDefaultStyle(); +// } +// +// /** +// * Executes {@code command} and asserts that the,
    +// * 1. Command box displays {@code command}.
    +// * 2. Command box has the error style class.
    +// * 3. Result display box displays {@code expectedResultMessage}.
    +// * 4. {@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 ForumBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) +// */ +// private void assertCommandFailure(String command, String expectedResultMessage) { +// Model expectedModel = getModel(); +// +// executeCommand(command); +// assertApplicationDisplaysExpected(command, expectedResultMessage, expectedModel); +// assertSelectedCardUnchanged(); +// assertCommandBoxShowsErrorStyle(); +// assertStatusBarUnchanged(); +// } +// } diff --git a/src/test/java/systemtests/DeleteCommandSystemTest.java b/src/test/java/systemtests/DeleteCommandSystemTest.java deleted file mode 100644 index 29fbb5fc3930..000000000000 --- a/src/test/java/systemtests/DeleteCommandSystemTest.java +++ /dev/null @@ -1,193 +0,0 @@ -package systemtests; - -import static org.junit.Assert.assertTrue; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; -import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; -import static seedu.address.logic.commands.DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS; -import static seedu.address.testutil.TestUtil.getLastIndex; -import static seedu.address.testutil.TestUtil.getMidIndex; -import static seedu.address.testutil.TestUtil.getPerson; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalPersons.KEYWORD_MATCHING_MEIER; - -import org.junit.Test; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.RedoCommand; -import seedu.address.logic.commands.UndoCommand; -import seedu.address.model.Model; -import seedu.address.model.person.Person; - -public class DeleteCommandSystemTest extends AddressBookSystemTest { - - private static final String MESSAGE_INVALID_DELETE_COMMAND_FORMAT = - String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE); - - @Test - 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 */ - 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); - assertCommandSuccess(command, expectedModel, expectedResultMessage); - - /* Case: delete the last person 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 */ - 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 */ - command = RedoCommand.COMMAND_WORD; - removePerson(modelBeforeDeletingLast, lastPersonIndex); - expectedResultMessage = RedoCommand.MESSAGE_SUCCESS; - assertCommandSuccess(command, modelBeforeDeletingLast, expectedResultMessage); - - /* Case: delete the middle person 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 */ - 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 - * -> rejected - */ - showPersonsWithName(KEYWORD_MATCHING_MEIER); - int invalidIndex = getModel().getAddressBook().getPersonList().size(); - command = DeleteCommand.COMMAND_WORD + " " + invalidIndex; - assertCommandFailure(command, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - - /* --------------------- Performing delete operation while a person card is selected ------------------------ */ - - /* Case: delete the selected person -> person list panel selects the person before the deleted person */ - 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); - assertCommandSuccess(command, expectedModel, expectedResultMessage, expectedIndex); - - /* --------------------------------- Performing invalid delete operation ------------------------------------ */ - - /* Case: invalid index (0) -> rejected */ - command = DeleteCommand.COMMAND_WORD + " 0"; - assertCommandFailure(command, MESSAGE_INVALID_DELETE_COMMAND_FORMAT); - - /* Case: invalid index (-1) -> rejected */ - command = DeleteCommand.COMMAND_WORD + " -1"; - assertCommandFailure(command, MESSAGE_INVALID_DELETE_COMMAND_FORMAT); - - /* Case: invalid index (size + 1) -> rejected */ - Index outOfBoundsIndex = Index.fromOneBased( - getModel().getAddressBook().getPersonList().size() + 1); - command = DeleteCommand.COMMAND_WORD + " " + outOfBoundsIndex.getOneBased(); - assertCommandFailure(command, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - - /* Case: invalid arguments (alphabets) -> rejected */ - assertCommandFailure(DeleteCommand.COMMAND_WORD + " abc", MESSAGE_INVALID_DELETE_COMMAND_FORMAT); - - /* Case: invalid arguments (extra argument) -> rejected */ - assertCommandFailure(DeleteCommand.COMMAND_WORD + " 1 abc", MESSAGE_INVALID_DELETE_COMMAND_FORMAT); - - /* Case: mixed case command word -> rejected */ - assertCommandFailure("DelETE 1", MESSAGE_UNKNOWN_COMMAND); - } - - /** - * Removes the {@code Person} at the specified {@code index} in {@code model}'s address book. - * @return the removed person - */ - private Person removePerson(Model model, Index index) { - Person targetPerson = getPerson(model, index); - model.deletePerson(targetPerson); - return targetPerson; - } - - /** - * Deletes the person 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); - - assertCommandSuccess( - DeleteCommand.COMMAND_WORD + " " + toDelete.getOneBased(), expectedModel, expectedResultMessage); - } - - /** - * Executes {@code command} and in addition,
    - * 1. Asserts that the command box displays an empty string.
    - * 2. Asserts that the result display box displays {@code expectedResultMessage}.
    - * 3. Asserts that the browser url and selected card remains unchanged.
    - * 4. Asserts that the status bar's sync status changes.
    - * 5. Asserts that the command box has the default style class.
    - * Verifications 1 and 2 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}. - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) - */ - private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage) { - assertCommandSuccess(command, expectedModel, expectedResultMessage, null); - } - - /** - * 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) - */ - private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage, - Index expectedSelectedCardIndex) { - executeCommand(command); - assertApplicationDisplaysExpected("", expectedResultMessage, expectedModel); - - if (expectedSelectedCardIndex != null) { - assertSelectedCardChanged(expectedSelectedCardIndex); - } else { - assertSelectedCardUnchanged(); - } - - assertCommandBoxShowsDefaultStyle(); - assertStatusBarUnchangedExceptSyncStatus(); - } - - /** - * Executes {@code command} and in addition,
    - * 1. Asserts that the command box displays {@code command}.
    - * 2. Asserts that result display box displays {@code expectedResultMessage}.
    - * 3. Asserts that the browser url, selected card and status bar remain unchanged.
    - * 4. Asserts that the command box has the error style.
    - * Verifications 1 and 2 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
    - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) - */ - private void assertCommandFailure(String command, String expectedResultMessage) { - Model expectedModel = getModel(); - - executeCommand(command); - assertApplicationDisplaysExpected(command, expectedResultMessage, expectedModel); - assertSelectedCardUnchanged(); - assertCommandBoxShowsErrorStyle(); - assertStatusBarUnchanged(); - } -} diff --git a/src/test/java/systemtests/EditCommandSystemTest.java b/src/test/java/systemtests/EditCommandSystemTest.java deleted file mode 100644 index 9e9e4572ddb2..000000000000 --- a/src/test/java/systemtests/EditCommandSystemTest.java +++ /dev/null @@ -1,299 +0,0 @@ -package systemtests; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; -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_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.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_EMAIL_AMY; -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_PHONE_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.AMY; -import static seedu.address.testutil.TypicalPersons.BOB; -import static seedu.address.testutil.TypicalPersons.KEYWORD_MATCHING_MEIER; - -import org.junit.Test; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.EditCommand; -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.tag.Tag; -import seedu.address.testutil.PersonBuilder; -import seedu.address.testutil.PersonUtil; - -public class EditCommandSystemTest extends AddressBookSystemTest { - - @Test - public void edit() { - Model model = getModel(); - - /* ----------------- Performing edit operation while an unfiltered list is being shown ---------------------- */ - - /* Case: edit all fields, command with leading spaces, trailing spaces and multiple spaces between each field - * -> edited - */ - 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(BOB).withTags(VALID_TAG_HUSBAND).build(); - assertCommandSuccess(command, index, editedPerson); - - /* Case: undo editing the last person in the list -> last person 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 */ - command = RedoCommand.COMMAND_WORD; - expectedResultMessage = RedoCommand.MESSAGE_SUCCESS; - model.updatePerson( - getModel().getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()), editedPerson); - assertCommandSuccess(command, model, expectedResultMessage); - - /* Case: edit a person 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); - - /* Case: edit a person with new values same as another person's values but with different name -> edited */ - assertTrue(getModel().getAddressBook().getPersonList().contains(BOB)); - index = INDEX_SECOND_PERSON; - assertNotEquals(getModel().getFilteredPersonList().get(index.getZeroBased()), BOB); - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_BOB - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND; - editedPerson = new PersonBuilder(BOB).withName(VALID_NAME_AMY).build(); - assertCommandSuccess(command, index, editedPerson); - - /* Case: edit a person with new values same as another person's values but with different phone and email - * -> edited - */ - index = INDEX_SECOND_PERSON; - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_AMY + EMAIL_DESC_AMY - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND; - editedPerson = new PersonBuilder(BOB).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).build(); - assertCommandSuccess(command, index, editedPerson); - - /* Case: clear tags -> cleared */ - index = INDEX_FIRST_PERSON; - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + " " + PREFIX_TAG.getPrefix(); - Person personToEdit = getModel().getFilteredPersonList().get(index.getZeroBased()); - editedPerson = new PersonBuilder(personToEdit).withTags().build(); - assertCommandSuccess(command, index, editedPerson); - - /* ------------------ 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 */ - 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); - - /* Case: filtered person list, edit index within bounds of address book but out of bounds of person list - * -> rejected - */ - showPersonsWithName(KEYWORD_MATCHING_MEIER); - int invalidIndex = getModel().getAddressBook().getPersonList().size(); - assertCommandFailure(EditCommand.COMMAND_WORD + " " + invalidIndex + NAME_DESC_BOB, - Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - - /* --------------------- Performing edit operation while a person card is selected -------------------------- */ - - /* Case: selects first card in the person list, edit a person -> edited, card selection remains unchanged but - * browser url changes - */ - showAllPersons(); - index = INDEX_FIRST_PERSON; - selectPerson(index); - 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 - assertCommandSuccess(command, index, AMY, index); - - /* --------------------------------- Performing invalid edit operation -------------------------------------- */ - - /* Case: invalid index (0) -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + " 0" + NAME_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, - String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); - - /* Case: invalid index (size + 1) -> rejected */ - invalidIndex = getModel().getFilteredPersonList().size() + 1; - assertCommandFailure(EditCommand.COMMAND_WORD + " " + invalidIndex + NAME_DESC_BOB, - Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - - /* Case: missing index -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + NAME_DESC_BOB, - String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); - - /* Case: missing all fields -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased(), - EditCommand.MESSAGE_NOT_EDITED); - - /* Case: invalid name -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased() + INVALID_NAME_DESC, - Name.MESSAGE_NAME_CONSTRAINTS); - - /* Case: invalid phone -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased() + INVALID_PHONE_DESC, - Phone.MESSAGE_PHONE_CONSTRAINTS); - - /* Case: invalid email -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased() + INVALID_EMAIL_DESC, - Email.MESSAGE_EMAIL_CONSTRAINTS); - - /* Case: invalid address -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased() + INVALID_ADDRESS_DESC, - Address.MESSAGE_ADDRESS_CONSTRAINTS); - - /* Case: invalid tag -> rejected */ - 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 */ - executeCommand(PersonUtil.getAddCommand(BOB)); - assertTrue(getModel().getAddressBook().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 - + 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 */ - 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); - - /* Case: edit a person with new values same as another person's values but with different address -> rejected */ - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB - + ADDRESS_DESC_AMY + 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 phone -> rejected */ - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_AMY + EMAIL_DESC_BOB - + 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 email -> rejected */ - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND; - assertCommandFailure(command, EditCommand.MESSAGE_DUPLICATE_PERSON); - } - - /** - * Performs the same verification as {@code assertCommandSuccess(String, Index, Person, 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) - */ - private void assertCommandSuccess(String command, Index toEdit, Person editedPerson) { - assertCommandSuccess(command, toEdit, editedPerson, 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}.
    - * @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, - Index expectedSelectedCardIndex) { - Model expectedModel = getModel(); - expectedModel.updatePerson(expectedModel.getFilteredPersonList().get(toEdit.getZeroBased()), editedPerson); - expectedModel.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - - assertCommandSuccess(command, expectedModel, - String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson), expectedSelectedCardIndex); - } - - /** - * Performs the same verification as {@code assertCommandSuccess(String, Model, String, Index)} except that the - * browser url and selected card remain unchanged. - * @see EditCommandSystemTest#assertCommandSuccess(String, Model, String, Index) - */ - private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage) { - assertCommandSuccess(command, expectedModel, expectedResultMessage, null); - } - - /** - * Executes {@code command} and in addition,
    - * 1. Asserts that the command box displays an empty string.
    - * 2. Asserts that the result display box displays {@code expectedResultMessage}.
    - * 3. Asserts that the browser url and selected card update accordingly depending on the card at - * {@code expectedSelectedCardIndex}.
    - * 4. Asserts that the status bar's sync status changes.
    - * 5. Asserts that the command box has the default style class.
    - * Verifications 1 and 2 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
    - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) - * @see AddressBookSystemTest#assertSelectedCardChanged(Index) - */ - private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage, - Index expectedSelectedCardIndex) { - executeCommand(command); - expectedModel.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - assertApplicationDisplaysExpected("", expectedResultMessage, expectedModel); - assertCommandBoxShowsDefaultStyle(); - if (expectedSelectedCardIndex != null) { - assertSelectedCardChanged(expectedSelectedCardIndex); - } else { - assertSelectedCardUnchanged(); - } - assertStatusBarUnchangedExceptSyncStatus(); - } - - /** - * Executes {@code command} and in addition,
    - * 1. Asserts that the command box displays {@code command}.
    - * 2. Asserts that result display box displays {@code expectedResultMessage}.
    - * 3. Asserts that the browser url, selected card and status bar remain unchanged.
    - * 4. Asserts that the command box has the error style.
    - * Verifications 1 and 2 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
    - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) - */ - private void assertCommandFailure(String command, String expectedResultMessage) { - Model expectedModel = getModel(); - - executeCommand(command); - assertApplicationDisplaysExpected(command, expectedResultMessage, expectedModel); - assertSelectedCardUnchanged(); - assertCommandBoxShowsErrorStyle(); - assertStatusBarUnchanged(); - } -} diff --git a/src/test/java/systemtests/ErrorDialogGuiTest.java b/src/test/java/systemtests/ErrorDialogGuiTest.java deleted file mode 100644 index f8ec17fdb2a7..000000000000 --- a/src/test/java/systemtests/ErrorDialogGuiTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package systemtests; - -import static org.junit.Assert.assertEquals; -import static seedu.address.testutil.EventsUtil.postLater; -import static seedu.address.ui.UiManager.FILE_OPS_ERROR_DIALOG_CONTENT_MESSAGE; -import static seedu.address.ui.UiManager.FILE_OPS_ERROR_DIALOG_HEADER_MESSAGE; -import static seedu.address.ui.UiManager.FILE_OPS_ERROR_DIALOG_STAGE_TITLE; - -import java.io.IOException; - -import org.junit.Test; - -import guitests.GuiRobot; -import guitests.guihandles.AlertDialogHandle; -import seedu.address.commons.events.storage.DataSavingExceptionEvent; - -public class ErrorDialogGuiTest extends AddressBookSystemTest { - - private static final IOException IO_EXCEPTION_STUB = new IOException("Stub"); - private final GuiRobot guiRobot = new GuiRobot(); - - @Test - public void showErrorDialogs() { - postLater(new DataSavingExceptionEvent(IO_EXCEPTION_STUB)); - - guiRobot.waitForEvent(() -> guiRobot.isWindowShown(FILE_OPS_ERROR_DIALOG_STAGE_TITLE)); - - AlertDialogHandle alertDialog = new AlertDialogHandle(guiRobot.getStage(FILE_OPS_ERROR_DIALOG_STAGE_TITLE)); - assertEquals(FILE_OPS_ERROR_DIALOG_HEADER_MESSAGE, alertDialog.getHeaderText()); - assertEquals(FILE_OPS_ERROR_DIALOG_CONTENT_MESSAGE + ":\n" + IO_EXCEPTION_STUB.toString(), - alertDialog.getContentText()); - } - -} diff --git a/src/test/java/systemtests/FindCommandSystemTest.java b/src/test/java/systemtests/FindCommandSystemTest.java deleted file mode 100644 index 0bde83c0444b..000000000000 --- a/src/test/java/systemtests/FindCommandSystemTest.java +++ /dev/null @@ -1,195 +0,0 @@ -package systemtests; - -import static org.junit.Assert.assertFalse; -import static seedu.address.commons.core.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW; -import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; -import static seedu.address.testutil.TypicalPersons.BENSON; -import static seedu.address.testutil.TypicalPersons.CARL; -import static seedu.address.testutil.TypicalPersons.DANIEL; -import static seedu.address.testutil.TypicalPersons.KEYWORD_MATCHING_MEIER; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.RedoCommand; -import seedu.address.logic.commands.UndoCommand; -import seedu.address.model.Model; -import seedu.address.model.tag.Tag; - -public class FindCommandSystemTest extends AddressBookSystemTest { - - @Test - public void find() { - /* Case: find multiple persons in address book, command with leading spaces and trailing spaces - * -> 2 persons found - */ - String command = " " + FindCommand.COMMAND_WORD + " " + KEYWORD_MATCHING_MEIER + " "; - Model expectedModel = getModel(); - ModelHelper.setFilteredList(expectedModel, BENSON, DANIEL); // first names of Benson and Daniel are "Meier" - assertCommandSuccess(command, expectedModel); - assertSelectedCardUnchanged(); - - /* Case: repeat previous find command where person 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 */ - 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 */ - 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 */ - 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 */ - 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 - * -> 2 persons found - */ - command = FindCommand.COMMAND_WORD + " Daniel Benson NonMatchingKeyWord"; - assertCommandSuccess(command, expectedModel); - assertSelectedCardUnchanged(); - - /* Case: undo previous find command -> rejected */ - command = UndoCommand.COMMAND_WORD; - String expectedResultMessage = UndoCommand.MESSAGE_FAILURE; - assertCommandFailure(command, expectedResultMessage); - - /* Case: redo previous find command -> rejected */ - command = RedoCommand.COMMAND_WORD; - expectedResultMessage = RedoCommand.MESSAGE_FAILURE; - assertCommandFailure(command, expectedResultMessage); - - /* 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)); - command = FindCommand.COMMAND_WORD + " " + KEYWORD_MATCHING_MEIER; - expectedModel = getModel(); - ModelHelper.setFilteredList(expectedModel, DANIEL); - assertCommandSuccess(command, expectedModel); - assertSelectedCardUnchanged(); - - /* Case: find person in address book, keyword is same as name but of different case -> 1 person found */ - command = FindCommand.COMMAND_WORD + " MeIeR"; - assertCommandSuccess(command, expectedModel); - assertSelectedCardUnchanged(); - - /* Case: find person in address book, 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 */ - command = FindCommand.COMMAND_WORD + " Meiers"; - ModelHelper.setFilteredList(expectedModel); - assertCommandSuccess(command, expectedModel); - assertSelectedCardUnchanged(); - - /* Case: find person not in address book -> 0 persons found */ - command = FindCommand.COMMAND_WORD + " Mark"; - assertCommandSuccess(command, expectedModel); - assertSelectedCardUnchanged(); - - /* Case: find phone number of person in address book -> 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 */ - command = FindCommand.COMMAND_WORD + " " + DANIEL.getAddress().value; - assertCommandSuccess(command, expectedModel); - assertSelectedCardUnchanged(); - - /* Case: find email of person in address book -> 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 */ - 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 */ - showAllPersons(); - selectPerson(Index.fromOneBased(1)); - assertFalse(getPersonListPanel().getHandleToSelectedCard().getName().equals(DANIEL.getName().fullName)); - command = FindCommand.COMMAND_WORD + " Daniel"; - ModelHelper.setFilteredList(expectedModel, DANIEL); - assertCommandSuccess(command, expectedModel); - assertSelectedCardDeselected(); - - /* Case: find person in empty address book -> 0 persons found */ - deleteAllPersons(); - command = FindCommand.COMMAND_WORD + " " + KEYWORD_MATCHING_MEIER; - expectedModel = getModel(); - ModelHelper.setFilteredList(expectedModel, DANIEL); - assertCommandSuccess(command, expectedModel); - assertSelectedCardUnchanged(); - - /* Case: mixed case command word -> rejected */ - command = "FiNd Meier"; - assertCommandFailure(command, MESSAGE_UNKNOWN_COMMAND); - } - - /** - * Executes {@code command} and verifies that the command box displays an empty string, the result display - * 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)}.
    - * 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) - */ - private void assertCommandSuccess(String command, Model expectedModel) { - String expectedResultMessage = String.format( - MESSAGE_PERSONS_LISTED_OVERVIEW, expectedModel.getFilteredPersonList().size()); - - executeCommand(command); - assertApplicationDisplaysExpected("", expectedResultMessage, expectedModel); - assertCommandBoxShowsDefaultStyle(); - assertStatusBarUnchanged(); - } - - /** - * 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)}.
    - * 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) - */ - private void assertCommandFailure(String command, String expectedResultMessage) { - Model expectedModel = getModel(); - - executeCommand(command); - assertApplicationDisplaysExpected(command, expectedResultMessage, expectedModel); - assertSelectedCardUnchanged(); - assertCommandBoxShowsErrorStyle(); - assertStatusBarUnchanged(); - } -} diff --git a/src/test/java/systemtests/AddressBookSystemTest.java b/src/test/java/systemtests/ForumBookSystemTest.java similarity index 62% rename from src/test/java/systemtests/AddressBookSystemTest.java rename to src/test/java/systemtests/ForumBookSystemTest.java index bf1743e3d16e..a01124b8a284 100644 --- a/src/test/java/systemtests/AddressBookSystemTest.java +++ b/src/test/java/systemtests/ForumBookSystemTest.java @@ -1,17 +1,13 @@ package systemtests; +import static com.t13g2.forum.ui.BrowserPanel.DEFAULT_PAGE; +import static com.t13g2.forum.ui.StatusBarFooter.SYNC_STATUS_INITIAL; +import static com.t13g2.forum.ui.StatusBarFooter.SYNC_STATUS_UPDATED; +import static com.t13g2.forum.ui.UiPart.FXML_FILE_FOLDER; import static guitests.guihandles.WebViewUtil.waitUntilBrowserLoaded; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static seedu.address.ui.BrowserPanel.DEFAULT_PAGE; -import static seedu.address.ui.StatusBarFooter.SYNC_STATUS_INITIAL; -import static seedu.address.ui.StatusBarFooter.SYNC_STATUS_UPDATED; -import static seedu.address.ui.UiPart.FXML_FILE_FOLDER; -import static seedu.address.ui.testutil.GuiTestAssert.assertListMatching; - -import java.net.MalformedURLException; -import java.net.URL; + import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; @@ -23,6 +19,14 @@ import org.junit.BeforeClass; import org.junit.ClassRule; +import com.t13g2.forum.MainApp; +import com.t13g2.forum.TestApp; +import com.t13g2.forum.commons.core.EventsCenter; +import com.t13g2.forum.model.ForumBook; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.testutil.TypicalPersons; +import com.t13g2.forum.ui.CommandBox; + import guitests.guihandles.BrowserPanelHandle; import guitests.guihandles.CommandBoxHandle; import guitests.guihandles.MainMenuHandle; @@ -30,31 +34,18 @@ import guitests.guihandles.PersonListPanelHandle; import guitests.guihandles.ResultDisplayHandle; import guitests.guihandles.StatusBarFooterHandle; -import seedu.address.MainApp; -import seedu.address.TestApp; -import seedu.address.commons.core.EventsCenter; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.ClearCommand; -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.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 * for test verification. */ -public abstract class AddressBookSystemTest { +public abstract class ForumBookSystemTest { @ClassRule public static ClockRule clockRule = new ClockRule(); private static final List COMMAND_BOX_DEFAULT_STYLE = Arrays.asList("text-input", "text-field"); private static final List COMMAND_BOX_ERROR_STYLE = - Arrays.asList("text-input", "text-field", CommandBox.ERROR_STYLE_CLASS); + Arrays.asList("text-input", "text-field", CommandBox.ERROR_STYLE_CLASS); private MainWindowHandle mainWindowHandle; private TestApp testApp; @@ -84,7 +75,7 @@ public void tearDown() { /** * Returns the data to be loaded into the file in {@link #getDataFileLocation()}. */ - protected AddressBook getInitialData() { + protected ForumBook getInitialData() { return TypicalPersons.getTypicalAddressBook(); } @@ -138,49 +129,15 @@ protected void executeCommand(String command) { waitUntilBrowserLoaded(getBrowserPanel()); } - /** - * Displays all persons in the address book. - */ - protected void showAllPersons() { - executeCommand(ListCommand.COMMAND_WORD); - assertEquals(getModel().getAddressBook().getPersonList().size(), getModel().getFilteredPersonList().size()); - } - - /** - * Displays all persons with any parts of their names matching {@code keyword} (case-insensitive). - */ - protected void showPersonsWithName(String keyword) { - executeCommand(FindCommand.COMMAND_WORD + " " + keyword); - assertTrue(getModel().getFilteredPersonList().size() < getModel().getAddressBook().getPersonList().size()); - } - - /** - * Selects the person at {@code index} of the displayed list. - */ - protected void selectPerson(Index index) { - executeCommand(SelectCommand.COMMAND_WORD + " " + index.getOneBased()); - assertEquals(index.getZeroBased(), getPersonListPanel().getSelectedCardIndex()); - } - - /** - * Deletes all persons in the address book. - */ - protected void deleteAllPersons() { - executeCommand(ClearCommand.COMMAND_WORD); - assertEquals(0, getModel().getAddressBook().getPersonList().size()); - } - /** * Asserts that the {@code CommandBox} displays {@code expectedCommandInput}, the {@code ResultDisplay} displays * {@code expectedResultMessage}, the storage contains the same person objects as {@code expectedModel} * and the person list panel displays the persons in the model correctly. */ protected void assertApplicationDisplaysExpected(String expectedCommandInput, String expectedResultMessage, - Model expectedModel) { + Model expectedModel) { assertEquals(expectedCommandInput, getCommandBox().getInput()); assertEquals(expectedResultMessage, getResultDisplay().getText()); - assertEquals(new AddressBook(expectedModel.getAddressBook()), testApp.readStorageAddressBook()); - assertListMatching(getPersonListPanel(), expectedModel.getFilteredPersonList()); } /** @@ -195,36 +152,6 @@ private void rememberStates() { getPersonListPanel().rememberSelectedPersonCard(); } - /** - * Asserts that the previously selected card is now deselected and the browser's url remains displaying the details - * of the previously selected person. - * @see BrowserPanelHandle#isUrlChanged() - */ - protected void assertSelectedCardDeselected() { - assertFalse(getBrowserPanel().isUrlChanged()); - assertFalse(getPersonListPanel().isAnyCardSelected()); - } - - /** - * Asserts that the browser's url is changed to display the details of the person in the person list panel at - * {@code expectedSelectedCardIndex}, and only the card at {@code expectedSelectedCardIndex} is selected. - * @see BrowserPanelHandle#isUrlChanged() - * @see PersonListPanelHandle#isSelectedPersonCardChanged() - */ - protected void assertSelectedCardChanged(Index expectedSelectedCardIndex) { - getPersonListPanel().navigateToCard(getPersonListPanel().getSelectedCardIndex()); - String selectedCardName = getPersonListPanel().getHandleToSelectedCard().getName(); - URL expectedUrl; - try { - expectedUrl = new URL(BrowserPanel.SEARCH_PAGE_URL + selectedCardName.replaceAll(" ", "%20")); - } catch (MalformedURLException mue) { - throw new AssertionError("URL expected to be valid.", mue); - } - assertEquals(expectedUrl, getBrowserPanel().getLoadedUrl()); - - assertEquals(expectedSelectedCardIndex.getZeroBased(), getPersonListPanel().getSelectedCardIndex()); - } - /** * Asserts that the browser's url and the selected card in the person list panel remain unchanged. * @see BrowserPanelHandle#isUrlChanged() @@ -276,10 +203,9 @@ protected void assertStatusBarUnchangedExceptSyncStatus() { private void assertApplicationStartingStateIsCorrect() { assertEquals("", getCommandBox().getInput()); assertEquals("", getResultDisplay().getText()); - assertListMatching(getPersonListPanel(), getModel().getFilteredPersonList()); assertEquals(MainApp.class.getResource(FXML_FILE_FOLDER + DEFAULT_PAGE), getBrowserPanel().getLoadedUrl()); assertEquals(Paths.get(".").resolve(testApp.getStorageSaveLocation()).toString(), - getStatusBarFooter().getSaveLocation()); + getStatusBarFooter().getSaveLocation()); assertEquals(SYNC_STATUS_INITIAL, getStatusBarFooter().getSyncStatus()); } diff --git a/src/test/java/systemtests/HelpCommandSystemTest.java b/src/test/java/systemtests/HelpCommandSystemTest.java deleted file mode 100644 index 3fa0cc98236e..000000000000 --- a/src/test/java/systemtests/HelpCommandSystemTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package systemtests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.ui.testutil.GuiTestAssert.assertListMatching; - -import org.junit.Test; - -import guitests.GuiRobot; -import guitests.guihandles.HelpWindowHandle; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.HelpCommand; -import seedu.address.logic.commands.SelectCommand; -import seedu.address.ui.BrowserPanel; -import seedu.address.ui.StatusBarFooter; - -/** - * A system test class for the help window, which contains interaction with other UI components. - */ -public class HelpCommandSystemTest extends AddressBookSystemTest { - 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 " - + "tests on headless mode. See UsingGradle.adoc on how to do so."; - - private final GuiRobot guiRobot = new GuiRobot(); - - @Test - public void openHelpWindow() { - //use accelerator - getCommandBox().click(); - getMainMenu().openHelpWindowUsingAccelerator(); - assertHelpWindowOpen(); - - getResultDisplay().click(); - getMainMenu().openHelpWindowUsingAccelerator(); - assertHelpWindowOpen(); - - getPersonListPanel().click(); - getMainMenu().openHelpWindowUsingAccelerator(); - assertHelpWindowOpen(); - - getBrowserPanel().click(); - getMainMenu().openHelpWindowUsingAccelerator(); - assertHelpWindowNotOpen(); - - //use menu button - getMainMenu().openHelpWindowUsingMenu(); - assertHelpWindowOpen(); - - //use command box - executeCommand(HelpCommand.COMMAND_WORD); - assertHelpWindowOpen(); - - // open help window and give it focus - executeCommand(HelpCommand.COMMAND_WORD); - getMainWindowHandle().focus(); - - // assert that while the help window is open the UI updates correctly for a command execution - executeCommand(SelectCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()); - assertEquals("", getCommandBox().getInput()); - assertCommandBoxShowsDefaultStyle(); - assertNotEquals(HelpCommand.SHOWING_HELP_MESSAGE, getResultDisplay().getText()); - assertNotEquals(BrowserPanel.DEFAULT_PAGE, getBrowserPanel().getLoadedUrl()); - assertListMatching(getPersonListPanel(), getModel().getFilteredPersonList()); - - // assert that the status bar too is updated correctly while the help window is open - // note: the select command tested above does not update the status bar - executeCommand(DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()); - assertNotEquals(StatusBarFooter.SYNC_STATUS_INITIAL, getStatusBarFooter().getSyncStatus()); - } - - @Test - public void help_multipleCommands_onlyOneHelpWindowOpen() { - getMainMenu().openHelpWindowUsingMenu(); - - getMainWindowHandle().focus(); - getMainMenu().openHelpWindowUsingAccelerator(); - - getMainWindowHandle().focus(); - executeCommand(HelpCommand.COMMAND_WORD); - - assertEquals(1, guiRobot.getNumberOfWindowsShown(HelpWindowHandle.HELP_WINDOW_TITLE)); - } - - /** - * Asserts that the help window is open, and closes it after checking. - */ - private void assertHelpWindowOpen() { - assertTrue(ERROR_MESSAGE, HelpWindowHandle.isWindowPresent()); - guiRobot.pauseForHuman(); - - new HelpWindowHandle(guiRobot.getStage(HelpWindowHandle.HELP_WINDOW_TITLE)).close(); - getMainWindowHandle().focus(); - } - - /** - * Asserts that the help window isn't open. - */ - private void assertHelpWindowNotOpen() { - assertFalse(ERROR_MESSAGE, HelpWindowHandle.isWindowPresent()); - } - -} diff --git a/src/test/java/systemtests/ModelHelper.java b/src/test/java/systemtests/ModelHelper.java index b7950598d36b..f5852de9949b 100644 --- a/src/test/java/systemtests/ModelHelper.java +++ b/src/test/java/systemtests/ModelHelper.java @@ -5,8 +5,8 @@ import java.util.Optional; import java.util.function.Predicate; -import seedu.address.model.Model; -import seedu.address.model.person.Person; +import com.t13g2.forum.model.Model; +import com.t13g2.forum.model.person.Person; /** * Contains helper methods to set up {@code Model} for testing. diff --git a/src/test/java/systemtests/SampleDataTest.java b/src/test/java/systemtests/SampleDataTest.java deleted file mode 100644 index 6a1cfac1ea75..000000000000 --- a/src/test/java/systemtests/SampleDataTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package systemtests; - -import static seedu.address.ui.testutil.GuiTestAssert.assertListMatching; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; - -import org.junit.Test; - -import seedu.address.model.AddressBook; -import seedu.address.model.person.Person; -import seedu.address.model.util.SampleDataUtil; -import seedu.address.testutil.TestUtil; - -public class SampleDataTest extends AddressBookSystemTest { - /** - * Returns null to force test app to load data of the file in {@code getDataFileLocation()}. - */ - @Override - protected AddressBook getInitialData() { - return null; - } - - /** - * Returns a non-existent file location to force test app to load sample data. - */ - @Override - protected Path getDataFileLocation() { - Path filePath = TestUtil.getFilePathInSandboxFolder("SomeFileThatDoesNotExist1234567890.xml"); - deleteFileIfExists(filePath); - return filePath; - } - - /** - * Deletes the file at {@code filePath} if it exists. - */ - private void deleteFileIfExists(Path filePath) { - try { - Files.deleteIfExists(filePath); - } catch (IOException ioe) { - throw new AssertionError(ioe); - } - } - - @Test - public void addressBook_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 deleted file mode 100644 index 68d024c22e64..000000000000 --- a/src/test/java/systemtests/SelectCommandSystemTest.java +++ /dev/null @@ -1,154 +0,0 @@ -package systemtests; - -import static org.junit.Assert.assertTrue; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; -import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; -import static seedu.address.logic.commands.SelectCommand.MESSAGE_SELECT_PERSON_SUCCESS; -import static seedu.address.testutil.TestUtil.getLastIndex; -import static seedu.address.testutil.TestUtil.getMidIndex; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalPersons.KEYWORD_MATCHING_MEIER; - -import org.junit.Test; - -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.RedoCommand; -import seedu.address.logic.commands.SelectCommand; -import seedu.address.logic.commands.UndoCommand; -import seedu.address.model.Model; - -public class SelectCommandSystemTest extends AddressBookSystemTest { - @Test - 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 - * -> 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 */ - Index personCount = getLastIndex(getModel()); - command = SelectCommand.COMMAND_WORD + " " + personCount.getOneBased(); - assertCommandSuccess(command, personCount); - - /* Case: undo previous selection -> rejected */ - command = UndoCommand.COMMAND_WORD; - String expectedResultMessage = UndoCommand.MESSAGE_FAILURE; - assertCommandFailure(command, expectedResultMessage); - - /* Case: redo selecting last card in the list -> rejected */ - command = RedoCommand.COMMAND_WORD; - expectedResultMessage = RedoCommand.MESSAGE_FAILURE; - assertCommandFailure(command, expectedResultMessage); - - /* Case: select the middle card in the person list -> selected */ - Index middleIndex = getMidIndex(getModel()); - command = SelectCommand.COMMAND_WORD + " " + middleIndex.getOneBased(); - assertCommandSuccess(command, middleIndex); - - /* Case: select the current selected card -> selected */ - assertCommandSuccess(command, middleIndex); - - /* ------------------------ 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 - * -> rejected - */ - showPersonsWithName(KEYWORD_MATCHING_MEIER); - int invalidIndex = getModel().getAddressBook().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 */ - Index validIndex = Index.fromOneBased(1); - assertTrue(validIndex.getZeroBased() < getModel().getFilteredPersonList().size()); - command = SelectCommand.COMMAND_WORD + " " + validIndex.getOneBased(); - assertCommandSuccess(command, validIndex); - - /* ----------------------------------- Perform invalid select operations ------------------------------------ */ - - /* Case: invalid index (0) -> rejected */ - assertCommandFailure(SelectCommand.COMMAND_WORD + " " + 0, - String.format(MESSAGE_INVALID_COMMAND_FORMAT, SelectCommand.MESSAGE_USAGE)); - - /* Case: invalid index (-1) -> rejected */ - assertCommandFailure(SelectCommand.COMMAND_WORD + " " + -1, - String.format(MESSAGE_INVALID_COMMAND_FORMAT, SelectCommand.MESSAGE_USAGE)); - - /* Case: invalid index (size + 1) -> rejected */ - invalidIndex = getModel().getFilteredPersonList().size() + 1; - assertCommandFailure(SelectCommand.COMMAND_WORD + " " + invalidIndex, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - - /* Case: invalid arguments (alphabets) -> rejected */ - assertCommandFailure(SelectCommand.COMMAND_WORD + " abc", - String.format(MESSAGE_INVALID_COMMAND_FORMAT, SelectCommand.MESSAGE_USAGE)); - - /* Case: invalid arguments (extra argument) -> rejected */ - assertCommandFailure(SelectCommand.COMMAND_WORD + " 1 abc", - String.format(MESSAGE_INVALID_COMMAND_FORMAT, SelectCommand.MESSAGE_USAGE)); - - /* Case: mixed case command word -> rejected */ - assertCommandFailure("SeLeCt 1", MESSAGE_UNKNOWN_COMMAND); - - /* Case: select from empty address book -> rejected */ - deleteAllPersons(); - assertCommandFailure(SelectCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased(), - MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - /** - * Executes {@code command} and asserts that the,
    - * 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.
    - * 4. {@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.
    - * Verifications 1, 3 and 4 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
    - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) - * @see AddressBookSystemTest#assertSelectedCardChanged(Index) - */ - private void assertCommandSuccess(String command, Index expectedSelectedCardIndex) { - Model expectedModel = getModel(); - String expectedResultMessage = String.format( - MESSAGE_SELECT_PERSON_SUCCESS, expectedSelectedCardIndex.getOneBased()); - int preExecutionSelectedCardIndex = getPersonListPanel().getSelectedCardIndex(); - - executeCommand(command); - assertApplicationDisplaysExpected("", expectedResultMessage, expectedModel); - - if (preExecutionSelectedCardIndex == expectedSelectedCardIndex.getZeroBased()) { - assertSelectedCardUnchanged(); - } else { - assertSelectedCardChanged(expectedSelectedCardIndex); - } - - assertCommandBoxShowsDefaultStyle(); - assertStatusBarUnchanged(); - } - - /** - * Executes {@code command} and asserts that the,
    - * 1. Command box displays {@code command}.
    - * 2. Command box has the error style class.
    - * 3. Result display box displays {@code expectedResultMessage}.
    - * 4. {@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) - */ - private void assertCommandFailure(String command, String expectedResultMessage) { - Model expectedModel = getModel(); - - executeCommand(command); - assertApplicationDisplaysExpected(command, expectedResultMessage, expectedModel); - assertSelectedCardUnchanged(); - assertCommandBoxShowsErrorStyle(); - assertStatusBarUnchanged(); - } -} diff --git a/src/test/java/systemtests/SystemTestSetupHelper.java b/src/test/java/systemtests/SystemTestSetupHelper.java index 82811ba874f0..8c75bfa2cab8 100644 --- a/src/test/java/systemtests/SystemTestSetupHelper.java +++ b/src/test/java/systemtests/SystemTestSetupHelper.java @@ -6,10 +6,11 @@ import org.testfx.api.FxToolkit; +import com.t13g2.forum.TestApp; +import com.t13g2.forum.model.ReadOnlyForumBook; + import guitests.guihandles.MainWindowHandle; import javafx.stage.Stage; -import seedu.address.TestApp; -import seedu.address.model.ReadOnlyAddressBook; /** * Contains helper methods that system tests require. @@ -21,7 +22,7 @@ public class SystemTestSetupHelper { /** * Sets up a new {@code TestApp} and returns it. */ - public TestApp setupApplication(Supplier addressBook, Path saveFileLocation) { + public TestApp setupApplication(Supplier addressBook, Path saveFileLocation) { try { FxToolkit.registerStage(Stage::new); FxToolkit.setupApplication(() -> testApp = new TestApp(addressBook, saveFileLocation)); diff --git a/src/test/resources/view/UiPartTest/validFile.fxml b/src/test/resources/view/UiPartTest/validFile.fxml index bab836af0db6..8ef376da4fa1 100644 --- a/src/test/resources/view/UiPartTest/validFile.fxml +++ b/src/test/resources/view/UiPartTest/validFile.fxml @@ -1,4 +1,4 @@ - + Hello World! diff --git a/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml b/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml index 151e09ce926f..ddfa848ed108 100644 --- a/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml +++ b/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml @@ -1,6 +1,6 @@ - + Hello World!