newConfig = jsonConfigStorage.readConfig(CONFIG_JSON);
+ String newFilePath = newConfig.get().getTaskManagerFilePath();
+ logger.info("New path: " + newFilePath);
+
+ assert(newFilePath.equals(DEFAULT_SAVE_LOCATION));
+ }
+
+```
diff --git a/config/findbugs/excludeFilter.xml b/config/findbugs/excludeFilter.xml
index 03c15ae4cc81..8955c4af62b0 100644
--- a/config/findbugs/excludeFilter.xml
+++ b/config/findbugs/excludeFilter.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/copyright.txt b/copyright.txt
index 93aa2a39ce25..fb67df74cf3a 100644
--- a/copyright.txt
+++ b/copyright.txt
@@ -1,7 +1,7 @@
Some code adapted from http://code.makery.ch/library/javafx-8-tutorial/ by Marco Jakob
Copyright by Susumu Yoshida - http://www.mcdodesign.com/
-- address_book_32.png
+- task_manager_32.png
- AddressApp.ico
Copyright by Jan Jan Kovařík - http://glyphicons.com/
diff --git a/docs/AboutUs.md b/docs/AboutUs.md
index 33df65bea583..e4d972b147c0 100644
--- a/docs/AboutUs.md
+++ b/docs/AboutUs.md
@@ -4,49 +4,104 @@ We are a team based in the [School of Computing, National University of Singapor
## Project Team
-#### [Damith C. Rajapakse](http://www.comp.nus.edu.sg/~damithch)
-
-**Role**: Project Advisor
+#### [Marcus Ng Wen Jian](https://github.com/marcusngwj)
+
+**Role**: Team Leader
+**Responsibilities**: Code Quality Control, Logic
+**Features implemented**:
+* Add Command
+* TaskDate
+* TaskTime
+* Priority Colour
------
+As a Team Leader, I will
+* Be responsible for the overall project coordination
+* Be the main point of contact for the group
+* Liaise with Professor and Tutorial Assistants
+* Ensure that each member of the team performs his/her roles dutifully
+* Be responsible in creating a comfortable workflow structure for the team
+
-#### [Joshua Lee](http://github.com/lejolly)
-
-Role: Developer
-Responsibilities: UI
+As a Code Quality Surveyor, I will
+* Look after the code quality
+* Ensure that the team adhere to the Java coding standards
+* Ensure that code follows software design principles
-----
-#### [Leow Yijin](http://github.com/yijinl)
-
-Role: Developer
-Responsibilities: Data
+#### [Jazlyn Ang Chue Ching](https://github.com/turtle96)
+
+**Role**: Developer
+**Responsibilities**: UI, Testing and Integrating of codes
+**Features implemented**:
+* Save Location
+* Undo Command
+* Find Tag
+* UI
+
+As a Code Integrator, I will
+* Make sure code works well when integrating a new feature to system (by liaising with those in-charge of Documentation, Code Quality and Testing)
+* Make sure any new code follows software design principles for easier maintenance
+* Look after the Github repository
+* Ensure that branches and PRs are well-labeled and specific for easier tracking
+
+
+As a Testing Leader, I will
+* Ensure tests cover all the bases required for regression testing (e.g. error handling, nullpointers etc)
+* Ensure testing is done regularly and on schedule
-----
-#### [Martin Choo](http://github.com/m133225)
-
-Role: Developer
-Responsibilities: Dev Ops
+#### [Madasamy Ravi Nadar Mamtha](https://github.com/Mamtha3005)
+
+**Role**: Developer
+**Responsibilities**: Data, Documentation, Scheduling and Tracking of deadlines
+**Features implemented**:
+* Edit Command
+* List Command
+
+As a Documentation Leader, I will
+* Be well-organised
+* Be responsible for the quality of documents submitted by the team.
+* Ensure that documents follow the format provided, if applicable.
+* Ensure that sentences in the document are grammatically correct, points are clear, concise, well-analysed and explained in a way everyone can understand
+
+
+As a Scheduling Deputy Leader, I will
+* Provide realistic deadlines for my team mates so that they can finish their part with good quality
+* Remind them when deadlines are nearing, giving them enough time to prepare
+* Remind them on a regular basis, giving them suggested timeline so that they can gauge their working pace and better manage their time
-----
-#### [Thien Nguyen](https://github.com/ndt93)
- Role: Developer
- Responsibilities: Threading
-
- -----
+#### [Zuo ZhuoLin](https://github.com/ZuoZhuolin)
+
+**Role**: Developer
+**Responsibilities**: Development and Operations, Testing, Scheduling and Tracking of deadlines
+**Features implemented**:
+* Done Command
+* List Command
+
+As a Scheduling Leader, I will
+* Set realistic deadline for different milestones of the project
+* Remind team mates when deadlines are nearing
+
-#### [You Liang](http://github.com/yl-coder)
-
- Role: Developer
- Responsibilities: UI
-
- -----
+As Testing Deputy Leader, I will
+* Double check tests cover all the bases required for regression testing
+* Ensures the testing of project is done properly and on time
+
+-----
# Contributors
We welcome contributions. See [Contact Us](ContactUs.md) page for more info.
+* [Damith C. Rajapakse](http://www.comp.nus.edu.sg/~damithch/)
+* [Joshua Lee](https://github.com/lejolly)
+* [Leow Yijin](https://github.com/yijinl)
+* [Martin Choo](https://github.com/m133225)
+* [Thien Nguyen](https://github.com/ndt93)
+* [You Liang](https://github.com/yl-coder)
* [Akshay Narayan](https://github.com/se-edu/addressbook-level4/pulls?q=is%3Apr+author%3Aokkhoy)
* [Sam Yong](https://github.com/se-edu/addressbook-level4/pulls?q=is%3Apr+author%3Amauris)
\ No newline at end of file
diff --git a/docs/ContactUs.md b/docs/ContactUs.md
index 866d0de3fddc..d50841f6a789 100644
--- a/docs/ContactUs.md
+++ b/docs/ContactUs.md
@@ -1,8 +1,8 @@
# Contact Us
-* **Bug reports, Suggestions** : Post in our [issue tracker](https://github.com/se-edu/addressbook-level4/issues)
+* **Bug reports, Suggestions** : Post in our [issue tracker](https://github.com/CS2103AUG2016-W15-C3/main/issues)
if you noticed bugs or have suggestions on how to improve.
* **Contributing** : We welcome pull requests. Follow the process described [here](https://github.com/oss-generic/process)
-* **Email us** : You can also reach us at `damith [at] comp.nus.edu.sg`
\ No newline at end of file
+* **Email us** : You can also reach us at `autumncs2103t [at] gmail.com`
\ No newline at end of file
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 690b6d386627..8343a8e2f5dd 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -1,5 +1,6 @@
# Developer Guide
+* [Introduction](#introduction)
* [Setting Up](#setting-up)
* [Design](#design)
* [Implementation](#implementation)
@@ -11,8 +12,13 @@
* [Appendix D: Glossary](#appendix-d--glossary)
* [Appendix E : Product Survey](#appendix-e-product-survey)
+##Introduction
-## Setting up
+Taskell is a simple software for users to keep track of their daily tasks and manage their busy schedule. Keyboard lovers will be able to experience the full benefit of Taskell as it implements a command-line interface.
+
+This developer guide will help you understand the design and implementation of Taskell. It helps you understand how Taskell works and how you can contribute for further development. This guide follows a top-down approach by giving an overview of the essential components first, followed by thorough explanation subsequently.
+
+## Setting Up
#### Prerequisites
@@ -22,22 +28,21 @@
This app will not work with earlier versions of Java 8.
2. **Eclipse** IDE
-3. **e(fx)clipse** plugin for Eclipse (Do the steps 2 onwards given in
+3. **E(fx)clipse** plugin for Eclipse (Do the steps 2 onwards given in
[this page](http://www.eclipse.org/efxclipse/install.html#for-the-ambitious))
4. **Buildship Gradle Integration** plugin from the Eclipse Marketplace
-#### Importing the project into Eclipse
+#### Importing The Project Into Eclipse
-0. Fork this repo, and clone the fork to your computer
-1. Open Eclipse (Note: Ensure you have installed the **e(fx)clipse** and **buildship** plugins as given
- in the prerequisites above)
+0. Fork this repository, and clone the fork to your computer
+1. Open Eclipse (Note: Ensure you have installed the **e(fx)clipse** and **buildship** plugins as given in the prerequisites above)
2. Click `File` > `Import`
3. Click `Gradle` > `Gradle Project` > `Next` > `Next`
4. Click `Browse`, then locate the project's directory
5. Click `Finish`
- > * If you are asked whether to 'keep' or 'overwrite' config files, choose to 'keep'.
+ > * If you are asked whether to 'keep' or 'overwrite' configuration files, choose to 'keep'.
> * Depending on your connection speed and server load, it can even take up to 30 minutes for the set up to finish
(This is because Gradle downloads library files from servers during the project set up process)
> * If Eclipse auto-changed any settings files during the import process, you can discard those changes.
@@ -58,45 +63,64 @@
### Architecture
-
-The **_Architecture Diagram_** given above explains the high-level design of the App.
-Given below is a quick overview of each component.
+
+
+
+Diagram 1: Architecture Diagram
+
+
+The Architecture Diagram given above explains the high-level design of the Application.
+Given below is a quick overview of each component.
-`Main` has only one class called [`MainApp`](../src/main/java/seedu/address/MainApp.java). It is responsible for,
-* At app launch: Initializes the components in the correct sequence, and connect them up with each other.
-* At shut down: Shuts down the components and invoke cleanup method where necessary.
+`Main` has only one class called [`MainApp`](../src/main/java/seedu/taskell/MainApp.java). It is responsible for,
+* At application 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.
[**`Commons`**](#common-classes) represents a collection of classes used by multiple other components.
Two of those classes play important roles at the architecture level.
-* `EventsCentre` : This class (written using [Google's Event Bus library](https://github.com/google/guava/wiki/EventBusExplained))
- is used by components to communicate with other components using events (i.e. a form of _Event Driven_ design)
-* `LogsCenter` : Used by many classes to write log messages to the App's log file.
+* `EventsCentre` : Used by components to communicate with other components using events (i.e. a form of _Event Driven_ design)(written using [Google's Event Bus library](https://github.com/google/guava/wiki/EventBusExplained))
-The rest of the App consists four components.
-* [**`UI`**](#ui-component) : The UI of tha App.
-* [**`Logic`**](#logic-component) : The command executor.
-* [**`Model`**](#model-component) : Holds the data of the App in-memory.
-* [**`Storage`**](#storage-component) : Reads data from, and writes data to, the hard disk.
+* `LogsCenter` : Used by many classes to write log messages to the Application's log file.
+
+The rest of the Application consists four components.
+* [**`UI`**](#ui-component) : UI of the Application.
+* [**`Logic`**](#logic-component) : Command executor.
+* [**`Model`**](#model-component) : Data Holder of the Application in-memory.
+* [**`Storage`**](#storage-component) : Data read from, and written to the hard disk.
Each of the four components
* Defines its _API_ in an `interface` with the same name as the Component.
* Exposes its functionality using a `{Component Name}Manager` class.
-For example, the `Logic` component (see the class diagram given below) defines it's API in the `Logic.java`
-interface and exposes its functionality using the `LogicManager.java` class.
+
-The _Sequence Diagram_ below shows how the components interact for the scenario where the user issues the
-command `delete 3`.
+Diagram 2: Logic Class Diagram
+
+
+The `Logic` component above defines it's API in the `Logic.java`
+interface and exposes its functionality using the `LogicManager.java` class.
-
+
+
->Note how the `Model` simply raises a `AddressBookChangedEvent` when the Address Book data are changed,
+Diagram 3: Sequence Diagram for Delete Task
+
+
+The Sequence Diagram above shows how the components interact for the scenario where the user issues the
+command `delete 1`.
+
+>Note how the `Model` simply raises a `TaskManagerChangedEvent` when the Task Manager data is 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.
-
+
+
+
+Diagram 4: Sequence Diagram for Delete Task Event Handling
+
+
+The diagram above shows how the `EventsCenter` reacts to that event, which eventually results in the updates
+being saved to the hard disk. The status bar of the UI is updated to reflect the 'Last Updated' time.
> Note how the event is propagated through the `EventsCenter` to the `Storage` and `UI` without `Model` having
to be coupled to either of them. This is an example of how this Event Driven approach helps us reduce direct
@@ -104,67 +128,93 @@ being saved to the hard disk and the status bar of the UI being updated to refle
The sections below give more details of each component.
-### UI component
+### UI Component
+
-**API** : [`Ui.java`](../src/main/java/seedu/address/ui/Ui.java)
+Diagram 5: UI Class Diagram
+
-The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`,
+The diagram above gives an overview of how the `UI`component is implemented.
+
+**API** : [`Ui.java`](../src/main/java/seedu/taskell/ui/Ui.java)
+
+The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `TaskListPanel`,
`StatusBarFooter`, `BrowserPanel` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class
and they can be loaded using the `UiPartLoader`.
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 [`MainWindow`](../src/main/java/seedu/address/ui/MainWindow.java) is specified in
+ For example, the layout of the [`MainWindow`](../src/main/java/seedu/taskell/ui/MainWindow.java) is specified in
[`MainWindow.fxml`](../src/main/resources/view/MainWindow.fxml)
The `UI` component,
* Executes user commands using the `Logic` component.
-* Binds itself to some data in the `Model` so that the UI can auto-update when data in the `Model` change.
-* Responds to events raised from various parts of the App and updates the UI accordingly.
+* Binds itself to some data in the `Model` so that the UI can auto-update when data in the `Model` changes.
+* Responds to events raised from various parts of the Application and updates the UI accordingly.
-### Logic component
+### Logic Component
+
-**API** : [`Logic.java`](../src/main/java/seedu/address/logic/Logic.java)
+Diagram 6: Logic Class Diagram
+
-1. `Logic` uses the `Parser` class to parse the user command.
-2. This results in a `Command` object which is executed by the `LogicManager`.
-3. The command execution can affect the `Model` (e.g. adding a person) and/or raise events.
-4. The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`.
+The diagram above gives an overview of how the `Logic`component is implemented.
+
**API** : [`Logic.java`](../src/main/java/seedu/taskell/logic/Logic.java)
-Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("delete 1")`
- API call.
-
+The `Logic` component,
+* Uses the `Parser` class to parse the user command, resulting in a `Command` object which is executed by the `LogicManager`.
+* Affects the `Model` (e.g. adding a task) and/or raise events.
+* Executes the necessary command and the result is encapsulated as a `CommandResult` to be passed back to the `UI`.
-### Model component
+
+
+
+Diagram 7: Add Task Sequence Diagram For Logic
+
+
+The diagram above shows the Sequence Diagram for interactions within the `Logic` component for the `execute("delete 1")`
+ API call.
+
+### Model Component
+
-**API** : [`Model.java`](../src/main/java/seedu/address/model/Model.java)
+Diagram 7: Model Class Diagram
+
-The `Model`,
+The diagram above gives an overview of how the `Model` component is implemented.
+
**API** : [`Model.java`](../src/main/java/seedu/taskell/model/Model.java)
+
+The `Model` component,
* stores a `UserPref` object that represents the user's preferences.
-* stores the Address Book data.
-* exposes a `UnmodifiableObservableList` that can be 'observed' e.g. the UI can be bound to this list
+* stores the Task Manager data.
+* exposes a `UnmodifiableObservableList` 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.
-### Storage component
+### Storage Component
+
-**API** : [`Storage.java`](../src/main/java/seedu/address/storage/Storage.java)
+Diagram 8: Storage Class Diagram
+
+
+The diagram above gives an overview of how the `Storage` component is implemented.
+
**API** : [`Storage.java`](../src/main/java/seedu/taskell/storage/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 Task Manager data in xml format and read it back.
-### Common classes
+### Common Classes
-Classes used by multiple components are in the `seedu.addressbook.commons` package.
+Classes used by multiple components are in the `seedu.taskmanager.commons` package.
## Implementation
@@ -182,14 +232,14 @@ and logging destinations.
**Logging Levels**
* `SEVERE` : Critical problem detected which may possibly cause the termination of the application
-* `WARNING` : Can continue, but with caution
-* `INFO` : Information showing the noteworthy actions by the App
+* `WARNING` : Program can continue, but with caution
+* `INFO` : Information showing the noteworthy actions by the Application
* `FINE` : Details that is not usually noteworthy but may be useful in debugging
e.g. print the actual list instead of just its size
### Configuration
-Certain properties of the application can be controlled (e.g App name, logging level) through the configuration file
+Certain properties of the application can be controlled (e.g Application name, logging level) through the configuration file
(default: `config.json`):
@@ -200,7 +250,7 @@ Tests can be found in the `./src/test/java` folder.
**In Eclipse**:
* To run all tests, right-click on the `src/test/java` folder and choose
`Run as` > `JUnit Test`
-* To run a subset of tests, you can right-click on a test package, test class, or a test and choose
+* To run a subset of tests, right-click on a test package, test class, or a test and choose
to run as a JUnit test.
**Using Gradle**:
@@ -208,22 +258,22 @@ Tests can be found in the `./src/test/java` folder.
We have two types of tests:
-1. **GUI Tests** - These are _System Tests_ that test the entire App by simulating user actions on the GUI.
+1. **GUI Tests** - These are _System Tests_ that test the entire Application by simulating user actions on the GUI.
These are in the `guitests` package.
2. **Non-GUI Tests** - These are tests not involving the GUI. They include,
1. _Unit tests_ targeting the lowest level methods/classes.
- e.g. `seedu.address.commons.UrlUtilTest`
+ e.g. `seedu.taskell.model.task.TaskDateTest`
2. _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`
- 3. Hybrids of unit and integration tests. These test are checking multiple code units as well as
+ e.g. `seedu.taskell.storage.StorageManagerTest`
+ 3. Hybrids of unit and integration tests. These tests are checking multiple code units as well as
how the are connected together.
- e.g. `seedu.address.logic.LogicManagerTest`
+ e.g. `seedu.taskell.logic.LogicManagerTest`
**Headless GUI Testing** :
Thanks to the [TestFX](https://github.com/TestFX/TestFX) library we use,
- our GUI tests can be run in the _headless_ mode.
+ our GUI tests can be run in the headless mode.
In the headless mode, GUI tests do not show up on the screen.
That means the developer can do other things on the Computer while the tests are running.
See [UsingGradle.md](UsingGradle.md#running-tests) to learn how to run tests in headless mode.
@@ -252,17 +302,17 @@ See [UsingTravis.md](UsingTravis.md) for more details.
Here are the steps to create a new release.
1. Generate a JAR file [using Gradle](UsingGradle.md#creating-the-jar-file).
- 2. Tag the repo with the version number. e.g. `v0.1`
- 2. [Crete a new release using GitHub](https://help.github.com/articles/creating-releases/)
+ 2. Tag the repository with the version number. e.g. `v0.1`
+ 2. [Create a new release using GitHub](https://help.github.com/articles/creating-releases/)
and upload the JAR file your created.
### Managing Dependencies
-A project often depends on third-party libraries. For example, Address Book depends on the
+A project often depends on third-party libraries. For example, Taskell depends on the
[Jackson library](http://wiki.fasterxml.com/JacksonHome) for XML parsing. Managing these _dependencies_
can be automated using Gradle. For example, Gradle can download the dependencies automatically, which
is better than these alternatives.
-a. Include those libraries in the repo (this bloats the repo size)
+a. Include those libraries in the repository (this bloats the repository size)
b. Require developers to download those libraries manually (this creates extra work for developers)
## Appendix A : User Stories
@@ -271,51 +321,234 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (un
Priority | As a ... | I want to ... | So that I can...
--------- | :-------- | :--------- | :-----------
-`* * *` | new user | see usage instructions | refer to instructions when I forget how to use the App
-`* * *` | user | add a new person |
-`* * *` | user | delete a person | remove entries that I no longer need
-`* * *` | user | find a person by name | locate details of persons without having to go through the entire list
-`* *` | user | hide [private contact details](#private-contact-detail) by default | minimize chance of someone else seeing them by accident
-`*` | user with many persons in the address book | sort persons by name | locate a person easily
-
-{More to be added}
+-------- | :---------- | :--------- | :-----------
+`* * *` | new user | see user guide | refer to the different commands when I forget how to use the application.
+`* * *` | user | add a task | take note of all my tasks.
+`* * *` | user | delete a task | remove task that I no longer need.
+`* * *` | user | find a task by its description | locate details of tasks without having to go through the entire list.
+`* * *` | user | categorize my tasks | group and view tasks of similar type.
+`* * *` | user | view all the tasks, sorted by day, month | plan my schedule.
+`* * *` | user | edit task | make changes to the task created.
+`* * *` | user | have a start and end time for an event | take note of the duration of the event.
+`* * *` | user | set deadlines for a task | remember when the task is due.
+`* * *` | user | undo my previous action | correct any mistakes made.
+`* * *` | user | mark a task as done | focus on the uncompleted tasks.
+`* * *` | user | have flexible command format |have various options to execute a command.
+`* * *` | user | specify a folder with cloud syncing service as the storage location | I can easily access my task manager from different computers.
+`* * *` | user | I want to see a list of completed tasks | view all the tasks I had done.
+`* *` | user | delete tasks based on a certain index | delete a few tasks instead of one.
+`*` | user | set some of my task recursively | schedule them on a daily/weekly/monthly basis.
+`*` | user | be able to block multiple timeslots, and release the timeslots when timing is confirmed| schedule in events which have uncertain timings more efficiently.
+`*` | user | sort tasks by priority | view the most important tasks.
+`*` | user | edit my notification time period | customise if I wanted to be reminded earlier or later.
+`*` | user | use the history command | saves time typing repeated commands.
+`*` | user | view the task in either calendar form or list form | switch between the two display format.
## Appendix B : Use Cases
-(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise)
+#### Use case: Add task
+
+**MSS**
+
+1. User requests to add tasks
+
+2. Taskell adds the task
+Use case ends
+
+**Extensions**
+
+2a. The user did not follow the given format to add the task
+
+> 2a1. Taskell displays invalid command format warning
+ Use case resumes at step 1
-#### Use case: Delete person
+#### Use case: Delete task
**MSS**
-1. User requests to list persons
-2. AddressBook shows a list of persons
-3. User requests to delete a specific person in the list
-4. AddressBook deletes the person
-Use case ends.
+1. User requests to list tasks
+2. Taskell shows a list of uncompleted tasks
+3. User requests to delete a specific task in the list
+4. Taskell deletes the task
+Use case ends
**Extensions**
2a. The list is empty
-> Use case ends
+3a. The given index is invalid
+
+> 3a1. Taskell shows an error message
+ Use case resumes at step 2
+
+#### Use case: Done task
+
+**MSS**
+
+1. User requests to list tasks
+2. Taskell shows a list of uncompleted tasks
+3. User requests to mark a specific task in the list as completed
+4. Taskell marks the task as completed
+Use case ends
+
+**Extensions**
+
+2a. The list is empty
+
+3a. The given index is invalid
+
+> 3a1. Taskell shows an error message
+ Use case resumes at step 2
+
+4a. User tries to mark a completed task as completed
+
+#### Use case: Help task
+
+**MSS**
+
+1. User requests to view the different command
+2. User enters "help"
+3. User displays a summary of all the different command.
+Use case ends
+
+**Extensions**
+
+2a. The user types "help" incorrectly
+
+> 3a1. Taskell stil displays the help message
+
+#### Use case: Find task
+
+**MSS**
+
+1. User requests to find tasks with specific keywords
+2. Taskell displays the tasks with all matching keywords
+Use case ends
+
+**Extensions**
+
+1a. No keyword is given
+
+> 1a1. Taskell shows an error message
+
+#### Use case: Edit task
+
+**MSS**
+
+1. User requests to list tasks
+2. Taskell shows a list of tasks
+3. User requests to edit either the description, date, time or priority of a task
+4. Taskell edits the respective field
+5. Taskell displays the both the old and updated version of the task
+Use case ends
+
+**Extensions**
+
+2a. The list is empty
3a. The given index is invalid
+3b. The user did not key in the new field of the task
+3c. The user did not key in a valid parameter
+
+> 3a1, 3b1 and 3c1. Taskell shows an error message
+ Use case resumes at step 2
+
+#### Use case: Undo task
+
+**MSS**
+
+1. User enters a command
+2. Taskell executes it
+<<<<<<< HEAD
+3. User requests to list commands history
+4. User requests to undo command at specific index
+5. Taskell undoes the previous command
+=======
+3. User requests to list undo commands history
+4. User requests to undo command at specific index
+5. Taskell revert the command
+>>>>>>> 9d3e940bc97dc4a324dca16582e28cdbfc8c5ebc
+Use case ends
+
+**Extensions**
+
+3a. The user did not enter any previous command
+
+> 3a1. Taskell shows a message indicating no commands available for undo
+
+4a. The user enters invalid index
+
+> 4a1. Taskell shows error message indicating index is invalid
+
+#### Use case: List task
+
+**MSS**
+
+1. User requests to list either all tasks, incomplete tasks, completed tasks, task with specific start date or task with specific priority
+2. Taskell shows a list of tasks accordingly
+Use case ends
+
+**Extensions**
+
+2a. The list is empty
-> 3a1. AddressBook shows an error message
+> 2a1. Taskell shows an error message
Use case resumes at step 2
+
+#### Use case: View calendar for the week
+
+**MSS**
+
+1. User requests to view calendar
+2. Taskell displays calendar
+
+#### Use case: Save data to specified folder
+
+**MSS**
+
+1. User requests to save all tasks
+2. Taskell saves all tasks in the requested folder
+Use case ends
+
+**Extensions**
+
+2a. Data cannot be written to the requested folder (invalid directory or access prohibited)
+
+> 2a1. Taskell shows an error message and still saves data in previous old location.
+
+#### Use case: Clear task
+
+**MSS**
-{More to be added}
+1. User requests to clear all tasks
+2. Taskell deletes all tasks
+Use case ends
+
+**Extensions**
+
+2a. The list is empty
+
+> 2a1. Taskell shows an error message
+
+#### Use case: Exit task
+
+**MSS**
+
+1. User requests to exit Taskell
+2. Taskell saves all the data and stops
+Use case ends
+
+**Extensions**
+
+NIL
## Appendix C : Non Functional Requirements
1. Should work on any [mainstream OS](#mainstream-os) as long as it has Java `1.8.0_60` or higher installed.
-2. Should be able to hold up to 1000 persons.
+2. Should be able to hold up to 1000 tasks.
3. Should come with automated unit tests and open source code.
4. Should favor DOS style commands over Unix-style commands.
-
-{More to be added}
+5. Should execute commands under 5 seconds.
## Appendix D : Glossary
@@ -323,11 +556,53 @@ Use case ends.
> Windows, Linux, Unix, OS-X
-##### Private contact detail
+##### Floating Tasks
-> A contact detail that is not meant to be shared with others
+> Tasks with no deadline
## Appendix E : Product Survey
-
-{TODO: Add a summary of competing products}
-
+#### WunderList
+**Pros:**
+1. Has support for cross-platform operations
+2. Can share tasks with other people and manage them
+3. Can categorize tasks into different categories
+4. Can attach different types of file inside the task, such as photos, PDF and PowerPoint
+
+**Cons:**
+1. Has limited number of priority levels
+2. Has no undo operation
+
+#### Remember the Milk
+**Pros:**
+1. Can be used offline and tasks are synced once internet connection is established
+2. Can handle some natural language processing by saving deadlines from task information itself (e.g. Do math homework tomorrow: Saves task with deadline set to tomorrow)
+3. Can undo when marking tasks as done (recover from accidentally marking a task as done)
+4. Can set priority, and list tasks by priority
+5. Can set recursive tasks
+
+**Cons:**
+1. Need to click frequently to enter or edit a task
+2. Need to remember lots of shortcuts, so user is less likely to use them
+3. Has a cluttered interface, which is not intuitive
+4. Does not support calendar view in-house
+
+#### Google Calendar
+**Pros:**
+1. Can add in public holidays
+2. Can update in terms of time zone
+3. Can customize background picture
+
+**Cons:**
+1. Does not have flexibility in viewing the calendar
+2. Has too much information in 1 page in application
+
+#### Any.do
+**Pros:**
+1. Displays a reminder when the task is almost due (set in advance)
+2. Able to clear all tasks in one go
+3. Do a daily review at the start/end of day
+4. Arranges tasks by today, tomorrow, someday
+
+**Cons:**
+1. Requires internet connection
+2. Has no support for recurring tasks
\ No newline at end of file
diff --git a/docs/LearningOutcomes.md b/docs/LearningOutcomes.md
index 5ee57072a8d8..553a23732037 100644
--- a/docs/LearningOutcomes.md
+++ b/docs/LearningOutcomes.md
@@ -29,7 +29,7 @@ facilitate communication between event creators and event consumers.
## Use API Design `[LO-ApiDesign]`
-Note how components of AddressBook have well-defined APIs. For example, the API of the `Logic` component
+Note how components of TaskManager have well-defined APIs. For example, the API of the `Logic` component
is given in the [`Logic.java`](../src/main/java/seedu/address/logic/Logic.java)
@@ -41,7 +41,7 @@ is given in the [`Logic.java`](../src/main/java/seedu/address/logic/Logic.java)
## Use Assertions `[LO-Assertions]`
-Note how the AddressBook app uses Java `assert`s to verify assumptions.
+Note how the TaskManager app uses Java `assert`s to verify assumptions.
**Resources**
* [Programming With Assertions](http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html) - a
@@ -52,13 +52,13 @@ Note how the AddressBook app uses Java `assert`s to verify assumptions.
* Make sure assertions are enabled in Eclipse by forcing an assertion failure (e.g. add `assert false;` somewhere in
the code and run the code to ensure the runtime reports an assertion failure).
- * Add more assertions to AddressBook as you see fit.
+ * Add more assertions to TaskManager as you see fit.
------------------------------------------------------------------------------------------------------
## Use Logging `[LO-Logging]`
-Note [how the AddressBook app uses Java's `java.util.log` package to do logging](DeveloperGuide.md#logging).
+Note [how the TaskManager app uses Java's `java.util.log` package to do logging](DeveloperGuide.md#logging).
**Resources**
* Tutorials
@@ -71,17 +71,17 @@ Note [how the AddressBook app uses Java's `java.util.log` package to do logging]
* [Base 22 Java Logging Standards and Guidelines](https://wiki.base22.com/display/btg/Java+Logging+Standards+and+Guidelines)
#### Exercise: Add more logging
- Add more logging to AddressBook as you see fit.
+ Add more logging to TaskManager as you see fit.
------------------------------------------------------------------------------------------------------
## Use Defensive Coding `[LO-DefensiveCoding]`
- Note how AddressBook uses the `ReadOnly*` interfaces to prevent objects being modified by clients who are not
+ Note how TaskManager uses the `ReadOnly*` interfaces to prevent objects being modified by clients who are not
supposed to modify them.
#### Exercise: identify more places for defensive coding
- Analyze the AddressBook code/design to identify,
+ Analyze the TaskManager code/design to identify,
* where defensive coding is used
* where the code can be more defensive
@@ -89,7 +89,7 @@ Note [how the AddressBook app uses Java's `java.util.log` package to do logging]
## Use Build Automation `[LO-BuildAutomation]`
-Note [how the AddressBook app uses Gradle to automate build tasks](UsingGradle.md).
+Note [how the TaskManager app uses Gradle to automate build tasks](UsingGradle.md).
**Resources**
* Tutorials
@@ -108,7 +108,7 @@ Note [how the AddressBook app uses Gradle to automate build tasks](UsingGradle.m
## Use Continuous Integration `[LO-ContinuousIntegration]`
-Note [how the AddressBook app uses Travis to perform Continuous Integration](UsingTravis.md).
+Note [how the TaskManager app uses Travis to perform Continuous Integration](UsingTravis.md).
**Resources**
* Tutorials
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index 0cf4b84f7470..00d312dfdac5 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -1,134 +1,259 @@
# User Guide
-
+* [Introduction](#introduction)
* [Quick Start](#quick-start)
* [Features](#features)
* [FAQ](#faq)
* [Command Summary](#command-summary)
+* [Appendix A](#appendix-a)
+* [Appendix B](#appendix-b)
+
+//@@author A0142073R
+## Introduction
+Are you having a hard time remembering all the work you have to do? Do you have trouble finding a task manager that suits your preference for keyboard input? Well, worry no more, Taskell is here for you!
+Taskell will be your personal secretary. It will keep track of your daily tasks and remind you of any important dates and deadlines. What distinguishes Taskell from other task managers is that Taskell only requires a single line of command for every task input. This means that you can record each one of your tasks with just a single statement. You will no longer have to use a mouse if you do not wish to.
+Ready to begin life anew with a more efficient task manager? Read on to find out more!
+//@@author
## Quick Start
-0. Ensure you have Java version `1.8.0_60` or later installed in your Computer.
- > Having any Java 8 version is not enough.
- This app will not work with earlier versions of Java 8.
-
-1. Download the latest `addressbook.jar` from the [releases](../../../releases) tab.
-2. Copy the file to the folder you want to use as the home folder for your Address Book.
-3. Double-click the file to start the app. The GUI should appear in a few seconds.
- >
-
-4. Type the command in the command box and press Enter to execute it.
- e.g. typing **`help`** and pressing Enter will open the help window.
-5. Some example commands you can try:
- * **`list`** : lists all contacts
- * **`add`**` John Doe p/98765432 e/johnd@gmail.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
-6. Refer to the [Features](#features) section below for details of each command.
+Step 1: Ensure you have Java version `1.8.0_60` or later installed in your Computer.
+
+ > Having any Java 8 version is not enough.
+ This application will not work with earlier versions of Java 8.
+
+Step 2: Download the latest `taskell.jar` from here.
+
+Step 3: Copy the file to the folder you want to use as the home folder for your Task Manager.
+Step 4: Double-click the file to start the application. The GUI should appear in a few seconds.
+
+Diagram 1: A screenshot of the Graphical User Interface (GUI)
+
Step 5: Type the relevant command in the command box and press Enter to execute it.
+Step 6: Some example commands you can try:
+ * **`list`** : displays all contacts
+ * **`add`** buy MA1101R textbook today : adds a task called buy MA1101R textbook to be done by today.
+ * **`delete`** 3 : deletes the 3rd task shown in the current list
+ * **`exit`** : exits the application
+Refer to the [Features](#features) section below for details of each command.
## Features
-> **Command Format**
-> * Words in `UPPER_CASE` are the parameters.
-> * Items in `SQUARE_BRACKETS` are optional.
-> * Items with `...` after them can have multiple instances.
-> * The order of parameters is fixed.
+This section shows the different commands that you can use in Taskell. Words that are in UPPER_CASE are parameters. These parameters have to be in the order stated below. Words that are in italics are used to identify the parameters while words enclosed in SQUARE_BRACKETS are optional. INDEX refers to the index number shown in the most recent listing.
+
+#### Viewing list of commands : `help`
+
+To open the help window
+ Format: `help`
+
+
+//@@ author A0139257X
+#### Adding a task: `add`
+To add a floating task
+Format:
+- `add` TASK
+Example: `add` read Harry Potter Book
+
+To add a deadline task
+> Please refer to Appendix A and B for date and time format respectively that Taskell supports.
-#### Viewing help : `help`
-Format: `help`
+Formats:
+- `add` TASK by [DATE]
+Example: add buy textbook by today
+- `add` TASK by [TIME]
+Example: add visit Sandy at her house by the seaside by 3.35pm
+- `add` TASK by [DATE] by [TIME]
+Example: `add` do lab homework by Friday by 7pm
-> Help is also shown if you enter an incorrect command e.g. `abcd`
+To have a greater flexibility in the command format, Taskell supports a few natural variation such as on and at.
+
+- `add ` TASK on [DATE]
+Example: `add ` go for meeting on monday
+- `add ` TASK at [TIME]
+Example: `add ` go for meeting at 3pm
+- `add ` TASK on [DATE] at [TIME]
+Example: `add ` go for meeting on Sunday at 3pm
+- `add ` TASK on [DATE] by[TIME]
+Example: `add ` go for meeting on 1-jan by 3pm
+
+To add an event task
+Formats:
+- `add ` TASK on [DATE] startat [TIME] endat [TIME]
+Example: `add ` schedule meeting on Thursday startat 1pm endat 9pm
+
+- `add ` TASK startat [TIME]
+Example: `add ` concert by 2am band startat 7pm
+
+- `add ` TASK endat [TIME]
+Example: `add ` netball training endat 7pm
+//@@ author
+//@@ author A0148004Rz
+#### Listing tasks : `list`
+Formats:
+- `list`
+Displays a list of uncompleted tasks.
+- `list-all`
+Displays a list of all tasks.
+- `list-date` DATE
+Displays a list of all the tasks due on the specific date.
+- `list-done`
+Displays a list of completed tasks.
+- `list-priority` PRIORITY
+Displays a list of tasks with given priority.
+
+Diagram 2: Displays all the tasks to be done by today after typing list-date.
+//@@ author
+
+
+#### Finding tasks: `find`
+You can use the find command to view tasks with specific keywords.
+Formats:
+-`find KEYWORD [MORE_KEYWORDS]`
+Displays a list of tasks with description or tags that match all the keywords.
+Example: `find banana milk essay`
+This returns all tasks with description or tags that match all keywords `banana`, `milk`, and `essay`.
+
+-`find-tag TAG [MORE_TAGS]`
+Displays list of tasks with the same tags.
+Example: `find homework essay cs2103`
+This returns any task with either tag `homework`, `essay`, or `cs2103`.
+
+
-#### Adding a person: `add`
-Adds a person to the address book
-Format: `add NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...`
-
-> Persons can have any number of tags (including 0)
-
-Examples:
-* `add John Doe p/98765432 e/johnd@gmail.com a/John street, block 123, #01-01`
-* `add Betsy Crowe p/1234567 e/betsycrowe@gmail.com a/Newgate Prison t/criminal t/friend`
-
-#### Listing all persons : `list`
-Shows a list of all persons in the address book.
-Format: `list`
-
-#### Finding all persons containing any keyword in their name: `find`
-Finds persons whose names contain any of the given keywords.
-Format: `find KEYWORD [MORE_KEYWORDS]`
-
-> * The search is case sensitive. e.g `hans` will not 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` will match `Hans Bo`
-
-Examples:
-* `find John`
- Returns `John Doe` but not `john`
-* `find Betsy Tim John`
- Returns Any person having names `Betsy`, `Tim`, or `John`
-
-#### Deleting a person : `delete`
-Deletes the specified person from the address book. Irreversible.
-Format: `delete INDEX`
-
-> Deletes the person at the specified `INDEX`.
- The index refers to the index number shown in the most recent listing.
- The index **must be a positive integer** 1, 2, 3, ...
-
-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.
-
-#### Select a person : `select`
-Selects the person identified by the index number used in the last person listing.
-Format: `select INDEX`
-
-> 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 most recent listing.
- The index **must be a positive integer** 1, 2, 3, ...
-
-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.
-
-#### Clearing all entries : `clear`
-Clears all entries from the address book.
-Format: `clear`
+
+
+Diagram 3 and 4: Keying in �find report� displays list of tasks with report as one of the keywords in task description
+
+> Take Note!
+> * The order of the keywords does not matter. e.g. `chicken egg` will match `egg chicken`.
+> * Full words will be matched e.g. `chicken` will match `chickens`.
+> * Tasks matching at least one keyword will be returned (i.e. `OR` search).
+ e.g. `chicken` will match `chicken duck`
+
+
+
+#### Reverting previous action : `undo`
+If you wish to undo your previous actions, Enter list-undo to see a list of
+previous commands that can be undone.
+Then use undo command at the specified INDEX in the list.
+Format: `undo INDEX`
+Example: `list-undo`, then `undo 3`, will undo third command in command history.
+
+
+
+#### Deleting a task : `delete`
+To delete a task, use the delete command. This command deletes the task at a specified INDEX. The index refers to the index number shown in the most recent listing.
+Format: `delete INDEX`
+
+Picture 5 and 6: Entering `delete 1 will delete "Arrange meeting with XYZ company".`
+
+Example: `find violin, then delete 1
+This deletes the 1st task in the results of the find command.
+=======
+Format: `delete` INDEX
+
+Diagram 4: Deletes the first task in the list.
+>>>>>>> 9d3e940bc97dc4a324dca16582e28cdbfc8c5ebc
+
+#### Marking a task as completed: `done`
+Format: `done` INDEX
+Example: `done` 1
+This adds the 1st task as completed and moves it to the completed list.
+
+#### Editing a task : `edit`
+To edit the description of a task
+Formats:
+- `edit-desc` INDEX NEWDESCRIPTION
+- `edit-name` INDEX NEWDESCRIPTION
+
+Diagram 5: Edits the 2nd task on the list
+
+To edit the time of a task
+Formats:
+- `edit-startTime` INDEX NEWTIME
+- `edit-endTime` INDEX NEWTIME
+
+To edit the date of a task
+Formats:
+- `edit-startDate` INDEX NEWDATE
+- `edit-endDate` INDEX NEWDATE
+
+To edit the priority of a task
+Formats:
+- `edit-priority` INDEX NEWDATE
+
+
+
+#### Showing calendar view : `calendar` or `cal`
+You can view the calendar for the week on right panel to refer to the dates when adding tasks and scheduling events.
+To save time, Taskell has a short form command `cal`.
+Format: `calendar`
+
+#### Saving the information in Taskell : `save`
+You can specify the path of a folder to store Taskell's data file. Please note that you should have permissions to access the folder.
+If the specified directory is valid but the file is missing, for example if command is `save C:/Users/Jim/Documents/chicken`, and `C:/Users/Jim/Documents/chicken` is valid
+but `chicken` file is not created, Taskell will create the file for you.
+Format: `save FOLDERPATH`
+Example: `save C:/Users/Jim/Documents`
+
+
+
+#### Clearing all entries : `clear`
+Format: `clear`
#### 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.
-There is no need to save manually.
-
## 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 application in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Taskell folder.
## Command Summary
Command | Format
-------- | :--------
-Add | `add NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...`
+Add Floating Task | `add` TASK ITEM
+Add Event | `add` TASK ITEM by [DATE]
+Add Event | `add` TASK ITEM by [TIME]
+Add Event With Deadline | `add` TASK ITEM by [DATE][TIME]
+Calendar View | `calendar` or `cal`
Clear | `clear`
-Delete | `delete INDEX`
-Find | `find KEYWORD [MORE_KEYWORDS]`
-List | `list`
+Complete | `done` INDEX
+Delete | `delete` INDEX
+Edit | `edit` INDEX NEWTASK
+Find | `find` KEYWORD [MORE_KEYWORDS]
+Find Tag | `find-tag` KEYWORD [MORE_KEYWORDS]
Help | `help`
-Select | `select INDEX`
+List Incomplete Tasks| `list`
+List All Tasks | `list-all`
+List Given Day | `list-date` [DATE]
+List Tasks Done | `list-done` [DONE]
+List Undo | `list-undo`
+Undo | `undo INDEX`
+Calendar View | `calendar` or `cal`
+
+## Appendix A
+
+Supported Date Format | Example
+-------- | :--------
+DD-MM-YY |1-1-16
+DD-MM-YY | 1-1-2016
+DD-MM-YY | 1-Jan-2016
+DD-MM-YY | 1-January-2016
+DD-MM-YY | 1.Jan.2016
+DD-MM-YY | 1.January.2016
+MM-YY | july-16
+MM | july
+day | today
+day | tdy
+day | tmr
+day | tomorrow
+day | thursday
+
+## Appendix B
+
+Supported Time Format | Example
+-------- | :--------
+12hour |1pm
+12hour |12am
+12hour |111.45pm
diff --git a/docs/UsingGradle.md b/docs/UsingGradle.md
index 578c5f8634c2..e46bf10ffa2c 100644
--- a/docs/UsingGradle.md
+++ b/docs/UsingGradle.md
@@ -35,10 +35,10 @@ Gradle commands look like this:
## Creating the JAR file
* **`shadowJar`**
- Creates the `addressbook.jar` file in the `build/jar` folder, _if the current file is outdated_.
+ Creates the `taskell.jar` file in the `build/jar` folder, _if the current file is outdated_.
e.g. `./gradlew shadowJar`
- > To force Gradle to create the JAR file even if the current one is up-to-date, you can '`clean`' first.
+ > To force Gradle to create the JAR file even if the current one is up-to-startDate, you can '`clean`' first.
e.g. `./gradlew clean shadowJar`
**Note: Why do we create a fat JAR?**
@@ -56,7 +56,7 @@ If we package only our own class files into the JAR file, it will not work prope
Runs all tests in the `guitests` package
* **`nonGuiTests`**
- Runs all non-GUI tests in the `seedu.address` package
+ Runs all non-GUI tests in the `seedu.taskell` package
* **`headless`**
Sets the test mode as _headless_.
diff --git a/docs/diagrams/Diagrams.pptx b/docs/diagrams/Diagrams.pptx
index 3c28abe9c1d3..666532dc77c5 100644
Binary files a/docs/diagrams/Diagrams.pptx and b/docs/diagrams/Diagrams.pptx differ
diff --git a/docs/gif/listToday.gif b/docs/gif/listToday.gif
new file mode 100644
index 000000000000..45474411e6b9
Binary files /dev/null and b/docs/gif/listToday.gif differ
diff --git a/docs/images/AddTaskSdForLogic.png b/docs/images/AddTaskSdForLogic.png
new file mode 100644
index 000000000000..a99c36e0cb02
Binary files /dev/null and b/docs/images/AddTaskSdForLogic.png differ
diff --git a/docs/images/DeletePersonSdForLogic.png b/docs/images/DeletePersonSdForLogic.png
deleted file mode 100644
index 6c272fb17af6..000000000000
Binary files a/docs/images/DeletePersonSdForLogic.png and /dev/null differ
diff --git a/docs/images/DeleteTaskSdForLogic.png b/docs/images/DeleteTaskSdForLogic.png
new file mode 100644
index 000000000000..da681d1a5e18
Binary files /dev/null and b/docs/images/DeleteTaskSdForLogic.png differ
diff --git a/docs/images/GUI.png b/docs/images/GUI.png
new file mode 100644
index 000000000000..33d5f2cf6f84
Binary files /dev/null and b/docs/images/GUI.png differ
diff --git a/docs/images/Icon.png b/docs/images/Icon.png
new file mode 100644
index 000000000000..0e8fab8aaa1c
Binary files /dev/null and b/docs/images/Icon.png differ
diff --git a/docs/images/Jazlyn.png b/docs/images/Jazlyn.png
new file mode 100644
index 000000000000..068259585db7
Binary files /dev/null and b/docs/images/Jazlyn.png differ
diff --git a/docs/images/ListToday.png b/docs/images/ListToday.png
new file mode 100644
index 000000000000..72349c3b0291
Binary files /dev/null and b/docs/images/ListToday.png differ
diff --git a/docs/images/Mamtha.png b/docs/images/Mamtha.png
new file mode 100644
index 000000000000..abdfc2344d1d
Binary files /dev/null and b/docs/images/Mamtha.png differ
diff --git a/docs/images/Marcus.png b/docs/images/Marcus.png
new file mode 100644
index 000000000000..c441a207a046
Binary files /dev/null and b/docs/images/Marcus.png differ
diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png
index 8cdf11ec93a1..3652ec0f8b6c 100644
Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ
diff --git a/docs/images/SDforDeletePerson.png b/docs/images/SDforDeletePerson.png
deleted file mode 100644
index 1e836f10dcd8..000000000000
Binary files a/docs/images/SDforDeletePerson.png and /dev/null differ
diff --git a/docs/images/SDforDeletePersonEventHandling.png b/docs/images/SDforDeletePersonEventHandling.png
deleted file mode 100644
index ecec0805d32c..000000000000
Binary files a/docs/images/SDforDeletePersonEventHandling.png and /dev/null differ
diff --git a/docs/images/SDforDeleteTask.png b/docs/images/SDforDeleteTask.png
new file mode 100644
index 000000000000..b8816441f7bd
Binary files /dev/null and b/docs/images/SDforDeleteTask.png differ
diff --git a/docs/images/SDforDeleteTaskEventHandling.png b/docs/images/SDforDeleteTaskEventHandling.png
new file mode 100644
index 000000000000..88c40b585ce4
Binary files /dev/null and b/docs/images/SDforDeleteTaskEventHandling.png differ
diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png
index 7a4cd2700cbf..83b2098890aa 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 7121a50a442a..d6069e23ca7d 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 459245e267af..0ad175d067c2 100644
Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ
diff --git a/docs/images/ZhuoLin.png b/docs/images/ZhuoLin.png
new file mode 100644
index 000000000000..d79bb8f1ca37
Binary files /dev/null and b/docs/images/ZhuoLin.png differ
diff --git a/docs/images/delete1.png b/docs/images/delete1.png
new file mode 100644
index 000000000000..b72a91bd3ef5
Binary files /dev/null and b/docs/images/delete1.png differ
diff --git a/docs/images/editCmd.png b/docs/images/editCmd.png
new file mode 100644
index 000000000000..002469c17a3a
Binary files /dev/null and b/docs/images/editCmd.png differ
diff --git a/docs/images/findReport.png b/docs/images/findReport.png
new file mode 100644
index 000000000000..f06ee74a631e
Binary files /dev/null and b/docs/images/findReport.png differ
diff --git a/docs/images/findReportResult.png b/docs/images/findReportResult.png
new file mode 100644
index 000000000000..4e00fd25f875
Binary files /dev/null and b/docs/images/findReportResult.png differ
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 347a8359e0d5..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() + ", number of tags " + data.getTagList().size();
- }
-}
diff --git a/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java b/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java
deleted file mode 100644
index 95377b326fa6..000000000000
--- a/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package seedu.address.commons.events.ui;
-
-import seedu.address.commons.events.BaseEvent;
-import seedu.address.model.person.ReadOnlyPerson;
-
-/**
- * Represents a selection change in the Person List Panel
- */
-public class PersonPanelSelectionChangedEvent extends BaseEvent {
-
-
- private final ReadOnlyPerson newSelection;
-
- public PersonPanelSelectionChangedEvent(ReadOnlyPerson newSelection){
- this.newSelection = newSelection;
- }
-
- @Override
- public String toString() {
- return this.getClass().getSimpleName();
- }
-
- public ReadOnlyPerson getNewSelection() {
- return newSelection;
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java
deleted file mode 100644
index 2860a9ab2a85..000000000000
--- a/src/main/java/seedu/address/logic/commands/AddCommand.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.logic.commands;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.person.*;
-import seedu.address.model.tag.Tag;
-import seedu.address.model.tag.UniqueTagList;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Adds a person to the address book.
- */
-public class AddCommand extends Command {
-
- public static final String COMMAND_WORD = "add";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. "
- + "Parameters: NAME p/PHONE e/EMAIL a/ADDRESS [t/TAG]...\n"
- + "Example: " + COMMAND_WORD
- + " John Doe p/98765432 e/johnd@gmail.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney";
-
- public static final String MESSAGE_SUCCESS = "New person added: %1$s";
- public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book";
-
- private final Person toAdd;
-
- /**
- * Convenience constructor using raw values.
- *
- * @throws IllegalValueException if any of the raw values are invalid
- */
- public AddCommand(String name, String phone, String email, String address, Set tags)
- throws IllegalValueException {
- final Set tagSet = new HashSet<>();
- for (String tagName : tags) {
- tagSet.add(new Tag(tagName));
- }
- this.toAdd = new Person(
- new Name(name),
- new Phone(phone),
- new Email(email),
- new Address(address),
- new UniqueTagList(tagSet)
- );
- }
-
- @Override
- public CommandResult execute() {
- assert model != null;
- try {
- model.addPerson(toAdd);
- return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
- } catch (UniquePersonList.DuplicatePersonException e) {
- return new CommandResult(MESSAGE_DUPLICATE_PERSON);
- }
-
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
deleted file mode 100644
index 1bfebe8912a8..000000000000
--- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package seedu.address.logic.commands;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.UnmodifiableObservableList;
-import seedu.address.model.person.ReadOnlyPerson;
-import seedu.address.model.person.UniquePersonList.PersonNotFoundException;
-
-/**
- * Deletes a person identified using it's last displayed index from the address book.
- */
-public class DeleteCommand extends Command {
-
- public static final String COMMAND_WORD = "delete";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD
- + ": Deletes the person identified by the index number used in the last person listing.\n"
- + "Parameters: INDEX (must be a positive integer)\n"
- + "Example: " + COMMAND_WORD + " 1";
-
- public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
-
- public final int targetIndex;
-
- public DeleteCommand(int targetIndex) {
- this.targetIndex = targetIndex;
- }
-
-
- @Override
- public CommandResult execute() {
-
- UnmodifiableObservableList lastShownList = model.getFilteredPersonList();
-
- if (lastShownList.size() < targetIndex) {
- indicateAttemptToExecuteIncorrectCommand();
- return new CommandResult(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- ReadOnlyPerson personToDelete = lastShownList.get(targetIndex - 1);
-
- try {
- model.deletePerson(personToDelete);
- } catch (PersonNotFoundException pnfe) {
- assert false : "The target person cannot be missing";
- }
-
- return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
deleted file mode 100644
index 1d61bf6cc857..000000000000
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package seedu.address.logic.commands;
-
-import java.util.Set;
-
-/**
- * Finds and lists all persons in address book whose name contains any of the argument keywords.
- * Keyword matching is case sensitive.
- */
-public class FindCommand extends Command {
-
- public static final String COMMAND_WORD = "find";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of "
- + "the specified keywords (case-sensitive) and displays them as a list with index numbers.\n"
- + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
- + "Example: " + COMMAND_WORD + " alice bob charlie";
-
- private final Set keywords;
-
- public FindCommand(Set keywords) {
- this.keywords = keywords;
- }
-
- @Override
- public CommandResult execute() {
- model.updateFilteredPersonList(keywords);
- return new CommandResult(getMessageForPersonListShownSummary(model.getFilteredPersonList().size()));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java
deleted file mode 100644
index 9bdd457a1b01..000000000000
--- a/src/main/java/seedu/address/logic/commands/ListCommand.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package seedu.address.logic.commands;
-
-
-/**
- * Lists all persons in the address book to the user.
- */
-public class ListCommand extends Command {
-
- public static final String COMMAND_WORD = "list";
-
- public static final String MESSAGE_SUCCESS = "Listed all persons";
-
- public ListCommand() {}
-
- @Override
- public CommandResult execute() {
- model.updateFilteredListToShowAll();
- return new CommandResult(MESSAGE_SUCCESS);
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/SelectCommand.java b/src/main/java/seedu/address/logic/commands/SelectCommand.java
deleted file mode 100644
index 9ca0551f1951..000000000000
--- a/src/main/java/seedu/address/logic/commands/SelectCommand.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package seedu.address.logic.commands;
-
-import seedu.address.commons.core.EventsCenter;
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.events.ui.JumpToListRequestEvent;
-import seedu.address.commons.core.UnmodifiableObservableList;
-import seedu.address.model.person.ReadOnlyPerson;
-
-/**
- * Selects a person identified using it's last displayed index from the address book.
- */
-public class SelectCommand extends Command {
-
- public final int targetIndex;
-
- public static final String COMMAND_WORD = "select";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD
- + ": Selects the person identified by the index number used in the last person listing.\n"
- + "Parameters: INDEX (must be a positive integer)\n"
- + "Example: " + COMMAND_WORD + " 1";
-
- public static final String MESSAGE_SELECT_PERSON_SUCCESS = "Selected Person: %1$s";
-
- public SelectCommand(int targetIndex) {
- this.targetIndex = targetIndex;
- }
-
- @Override
- public CommandResult execute() {
-
- UnmodifiableObservableList lastShownList = model.getFilteredPersonList();
-
- if (lastShownList.size() < targetIndex) {
- indicateAttemptToExecuteIncorrectCommand();
- return new CommandResult(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- EventsCenter.getInstance().post(new JumpToListRequestEvent(targetIndex - 1));
- return new CommandResult(String.format(MESSAGE_SELECT_PERSON_SUCCESS, targetIndex));
-
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/Parser.java b/src/main/java/seedu/address/logic/parser/Parser.java
deleted file mode 100644
index 959b2cd0383c..000000000000
--- a/src/main/java/seedu/address/logic/parser/Parser.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package seedu.address.logic.parser;
-
-import seedu.address.logic.commands.*;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.commons.exceptions.IllegalValueException;
-
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-
-/**
- * Parses user input.
- */
-public class Parser {
-
- /**
- * Used for initial separation of command word and args.
- */
- private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
-
- private static final Pattern PERSON_INDEX_ARGS_FORMAT = Pattern.compile("(?.+)");
-
- private static final Pattern KEYWORDS_ARGS_FORMAT =
- Pattern.compile("(?\\S+(?:\\s+\\S+)*)"); // one or more keywords separated by whitespace
-
- private static final Pattern PERSON_DATA_ARGS_FORMAT = // '/' forward slashes are reserved for delimiter prefixes
- Pattern.compile("(?[^/]+)"
- + " (?p?)p/(?[^/]+)"
- + " (?p?)e/(?[^/]+)"
- + " (?p?)a/(?[^/]+)"
- + "(?(?: t/[^/]+)*)"); // variable number of tags
-
- public Parser() {}
-
- /**
- * Parses user input into command for execution.
- *
- * @param userInput full user input string
- * @return the command based on the user input
- */
- public Command parseCommand(String userInput) {
- final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
- if (!matcher.matches()) {
- return new IncorrectCommand(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 prepareAdd(arguments);
-
- case SelectCommand.COMMAND_WORD:
- return prepareSelect(arguments);
-
- case DeleteCommand.COMMAND_WORD:
- return prepareDelete(arguments);
-
- case ClearCommand.COMMAND_WORD:
- return new ClearCommand();
-
- case FindCommand.COMMAND_WORD:
- return prepareFind(arguments);
-
- case ListCommand.COMMAND_WORD:
- return new ListCommand();
-
- case ExitCommand.COMMAND_WORD:
- return new ExitCommand();
-
- case HelpCommand.COMMAND_WORD:
- return new HelpCommand();
-
- default:
- return new IncorrectCommand(MESSAGE_UNKNOWN_COMMAND);
- }
- }
-
- /**
- * Parses arguments in the context of the add person command.
- *
- * @param args full command args string
- * @return the prepared command
- */
- private Command prepareAdd(String args){
- final Matcher matcher = PERSON_DATA_ARGS_FORMAT.matcher(args.trim());
- // Validate arg string format
- if (!matcher.matches()) {
- return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
- }
- try {
- return new AddCommand(
- matcher.group("name"),
- matcher.group("phone"),
- matcher.group("email"),
- matcher.group("address"),
- getTagsFromArgs(matcher.group("tagArguments"))
- );
- } catch (IllegalValueException ive) {
- return new IncorrectCommand(ive.getMessage());
- }
- }
-
- /**
- * Extracts the new person's tags from the add command's tag arguments string.
- * Merges duplicate tag strings.
- */
- private static Set getTagsFromArgs(String tagArguments) throws IllegalValueException {
- // no tags
- if (tagArguments.isEmpty()) {
- return Collections.emptySet();
- }
- // replace first delimiter prefix, then split
- final Collection tagStrings = Arrays.asList(tagArguments.replaceFirst(" t/", "").split(" t/"));
- return new HashSet<>(tagStrings);
- }
-
- /**
- * Parses arguments in the context of the delete person command.
- *
- * @param args full command args string
- * @return the prepared command
- */
- private Command prepareDelete(String args) {
-
- Optional index = parseIndex(args);
- if(!index.isPresent()){
- return new IncorrectCommand(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
- }
-
- return new DeleteCommand(index.get());
- }
-
- /**
- * Parses arguments in the context of the select person command.
- *
- * @param args full command args string
- * @return the prepared command
- */
- private Command prepareSelect(String args) {
- Optional index = parseIndex(args);
- if(!index.isPresent()){
- return new IncorrectCommand(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, SelectCommand.MESSAGE_USAGE));
- }
-
- return new SelectCommand(index.get());
- }
-
- /**
- * Returns the specified index in the {@code command} IF a positive unsigned integer is given as the index.
- * Returns an {@code Optional.empty()} otherwise.
- */
- private Optional parseIndex(String command) {
- final Matcher matcher = PERSON_INDEX_ARGS_FORMAT.matcher(command.trim());
- if (!matcher.matches()) {
- return Optional.empty();
- }
-
- String index = matcher.group("targetIndex");
- if(!StringUtil.isUnsignedInteger(index)){
- return Optional.empty();
- }
- return Optional.of(Integer.parseInt(index));
-
- }
-
- /**
- * Parses arguments in the context of the find person command.
- *
- * @param args full command args string
- * @return the prepared command
- */
- private Command prepareFind(String args) {
- final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim());
- if (!matcher.matches()) {
- return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
- FindCommand.MESSAGE_USAGE));
- }
-
- // keywords delimited by whitespace
- final String[] keywords = matcher.group("keywords").split("\\s+");
- final Set keywordSet = new HashSet<>(Arrays.asList(keywords));
- return new FindCommand(keywordSet);
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java
deleted file mode 100644
index 298cc1b82ce8..000000000000
--- a/src/main/java/seedu/address/model/AddressBook.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package seedu.address.model;
-
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.ReadOnlyPerson;
-import seedu.address.model.person.UniquePersonList;
-import seedu.address.model.tag.Tag;
-import seedu.address.model.tag.UniqueTagList;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * Wraps all data at the address-book level
- * Duplicates are not allowed (by .equals comparison)
- */
-public class AddressBook implements ReadOnlyAddressBook {
-
- private final UniquePersonList persons;
- private final UniqueTagList tags;
-
- {
- persons = new UniquePersonList();
- tags = new UniqueTagList();
- }
-
- public AddressBook() {}
-
- /**
- * Persons and Tags are copied into this addressbook
- */
- public AddressBook(ReadOnlyAddressBook toBeCopied) {
- this(toBeCopied.getUniquePersonList(), toBeCopied.getUniqueTagList());
- }
-
- /**
- * Persons and Tags are copied into this addressbook
- */
- public AddressBook(UniquePersonList persons, UniqueTagList tags) {
- resetData(persons.getInternalList(), tags.getInternalList());
- }
-
- public static ReadOnlyAddressBook getEmptyAddressBook() {
- return new AddressBook();
- }
-
-//// list overwrite operations
-
- public ObservableList getPersons() {
- return persons.getInternalList();
- }
-
- public void setPersons(List persons) {
- this.persons.getInternalList().setAll(persons);
- }
-
- public void setTags(Collection tags) {
- this.tags.getInternalList().setAll(tags);
- }
-
- public void resetData(Collection extends ReadOnlyPerson> newPersons, Collection newTags) {
- setPersons(newPersons.stream().map(Person::new).collect(Collectors.toList()));
- setTags(newTags);
- }
-
- public void resetData(ReadOnlyAddressBook newData) {
- resetData(newData.getPersonList(), newData.getTagList());
- }
-
-//// person-level operations
-
- /**
- * Adds a person to the address book.
- * Also checks the new person's tags and updates {@link #tags} with any new tags found,
- * and updates the Tag objects in the person to point to those in {@link #tags}.
- *
- * @throws UniquePersonList.DuplicatePersonException if an equivalent person already exists.
- */
- public void addPerson(Person p) throws UniquePersonList.DuplicatePersonException {
- syncTagsWithMasterList(p);
- persons.add(p);
- }
-
- /**
- * Ensures that every tag in this person:
- * - exists in the master list {@link #tags}
- * - points to a Tag object in the master list
- */
- private void syncTagsWithMasterList(Person person) {
- final UniqueTagList personTags = person.getTags();
- tags.mergeFrom(personTags);
-
- // Create map with values = tag object references in the master list
- final Map masterTagObjects = new HashMap<>();
- for (Tag tag : tags) {
- masterTagObjects.put(tag, tag);
- }
-
- // Rebuild the list of person tags using references from the master list
- final Set commonTagReferences = new HashSet<>();
- for (Tag tag : personTags) {
- commonTagReferences.add(masterTagObjects.get(tag));
- }
- person.setTags(new UniqueTagList(commonTagReferences));
- }
-
- public boolean removePerson(ReadOnlyPerson key) throws UniquePersonList.PersonNotFoundException {
- if (persons.remove(key)) {
- return true;
- } else {
- throw new UniquePersonList.PersonNotFoundException();
- }
- }
-
-//// tag-level operations
-
- public void addTag(Tag t) throws UniqueTagList.DuplicateTagException {
- tags.add(t);
- }
-
-//// util methods
-
- @Override
- public String toString() {
- return persons.getInternalList().size() + " persons, " + tags.getInternalList().size() + " tags";
- // TODO: refine later
- }
-
- @Override
- public List getPersonList() {
- return Collections.unmodifiableList(persons.getInternalList());
- }
-
- @Override
- public List getTagList() {
- return Collections.unmodifiableList(tags.getInternalList());
- }
-
- @Override
- public UniquePersonList getUniquePersonList() {
- return this.persons;
- }
-
- @Override
- public UniqueTagList getUniqueTagList() {
- return this.tags;
- }
-
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof AddressBook // instanceof handles nulls
- && this.persons.equals(((AddressBook) other).persons)
- && this.tags.equals(((AddressBook) other).tags));
- }
-
- @Override
- public int hashCode() {
- // use this method for custom fields hashing instead of implementing your own
- return Objects.hash(persons, tags);
- }
-}
diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java
deleted file mode 100644
index d14a27a93b5e..000000000000
--- a/src/main/java/seedu/address/model/Model.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package seedu.address.model;
-
-import seedu.address.commons.core.UnmodifiableObservableList;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.ReadOnlyPerson;
-import seedu.address.model.person.UniquePersonList;
-
-import java.util.Set;
-
-/**
- * The API of the Model component.
- */
-public interface Model {
- /** Clears existing backing model and replaces with the provided new data. */
- void resetData(ReadOnlyAddressBook newData);
-
- /** Returns the AddressBook */
- ReadOnlyAddressBook getAddressBook();
-
- /** Deletes the given person. */
- void deletePerson(ReadOnlyPerson target) throws UniquePersonList.PersonNotFoundException;
-
- /** Adds the given person */
- void addPerson(Person person) throws UniquePersonList.DuplicatePersonException;
-
- /** Returns the filtered person list as an {@code UnmodifiableObservableList} */
- UnmodifiableObservableList getFilteredPersonList();
-
- /** Updates the filter of the filtered person list to show all persons */
- void updateFilteredListToShowAll();
-
- /** Updates the filter of the filtered person list to filter by the given keywords*/
- void updateFilteredPersonList(Set keywords);
-
-}
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
deleted file mode 100644
index 869226d02bf1..000000000000
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package seedu.address.model;
-
-import javafx.collections.transformation.FilteredList;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.core.UnmodifiableObservableList;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.commons.events.model.AddressBookChangedEvent;
-import seedu.address.commons.core.ComponentManager;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.ReadOnlyPerson;
-import seedu.address.model.person.UniquePersonList;
-import seedu.address.model.person.UniquePersonList.PersonNotFoundException;
-
-import java.util.Set;
-import java.util.logging.Logger;
-
-/**
- * Represents the in-memory model of the address book data.
- * All changes to any model should be synchronized.
- */
-public class ModelManager extends ComponentManager implements Model {
- private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
-
- private final AddressBook addressBook;
- private final FilteredList filteredPersons;
-
- /**
- * Initializes a ModelManager with the given AddressBook
- * AddressBook and its variables should not be null
- */
- public ModelManager(AddressBook src, UserPrefs userPrefs) {
- super();
- assert src != null;
- assert userPrefs != null;
-
- logger.fine("Initializing with address book: " + src + " and user prefs " + userPrefs);
-
- addressBook = new AddressBook(src);
- filteredPersons = new FilteredList<>(addressBook.getPersons());
- }
-
- public ModelManager() {
- this(new AddressBook(), new UserPrefs());
- }
-
- public ModelManager(ReadOnlyAddressBook initialData, UserPrefs userPrefs) {
- addressBook = new AddressBook(initialData);
- filteredPersons = new FilteredList<>(addressBook.getPersons());
- }
-
- @Override
- public void resetData(ReadOnlyAddressBook newData) {
- addressBook.resetData(newData);
- indicateAddressBookChanged();
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- return addressBook;
- }
-
- /** Raises an event to indicate the model has changed */
- private void indicateAddressBookChanged() {
- raise(new AddressBookChangedEvent(addressBook));
- }
-
- @Override
- public synchronized void deletePerson(ReadOnlyPerson target) throws PersonNotFoundException {
- addressBook.removePerson(target);
- indicateAddressBookChanged();
- }
-
- @Override
- public synchronized void addPerson(Person person) throws UniquePersonList.DuplicatePersonException {
- addressBook.addPerson(person);
- updateFilteredListToShowAll();
- indicateAddressBookChanged();
- }
-
- //=========== Filtered Person List Accessors ===============================================================
-
- @Override
- public UnmodifiableObservableList getFilteredPersonList() {
- return new UnmodifiableObservableList<>(filteredPersons);
- }
-
- @Override
- public void updateFilteredListToShowAll() {
- filteredPersons.setPredicate(null);
- }
-
- @Override
- public void updateFilteredPersonList(Set keywords){
- updateFilteredPersonList(new PredicateExpression(new NameQualifier(keywords)));
- }
-
- private void updateFilteredPersonList(Expression expression) {
- filteredPersons.setPredicate(expression::satisfies);
- }
-
- //========== Inner classes/interfaces used for filtering ==================================================
-
- interface Expression {
- boolean satisfies(ReadOnlyPerson person);
- String toString();
- }
-
- private class PredicateExpression implements Expression {
-
- private final Qualifier qualifier;
-
- PredicateExpression(Qualifier qualifier) {
- this.qualifier = qualifier;
- }
-
- @Override
- public boolean satisfies(ReadOnlyPerson person) {
- return qualifier.run(person);
- }
-
- @Override
- public String toString() {
- return qualifier.toString();
- }
- }
-
- interface Qualifier {
- boolean run(ReadOnlyPerson person);
- String toString();
- }
-
- private class NameQualifier implements Qualifier {
- private Set nameKeyWords;
-
- NameQualifier(Set nameKeyWords) {
- this.nameKeyWords = nameKeyWords;
- }
-
- @Override
- public boolean run(ReadOnlyPerson person) {
- return nameKeyWords.stream()
- .filter(keyword -> StringUtil.containsIgnoreCase(person.getName().fullName, keyword))
- .findAny()
- .isPresent();
- }
-
- @Override
- public String toString() {
- return "name=" + String.join(", ", nameKeyWords);
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
deleted file mode 100644
index bfca099b1e81..000000000000
--- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package seedu.address.model;
-
-
-import seedu.address.model.person.ReadOnlyPerson;
-import seedu.address.model.person.UniquePersonList;
-import seedu.address.model.tag.Tag;
-import seedu.address.model.tag.UniqueTagList;
-
-import java.util.List;
-
-/**
- * Unmodifiable view of an address book
- */
-public interface ReadOnlyAddressBook {
-
- UniqueTagList getUniqueTagList();
-
- UniquePersonList getUniquePersonList();
-
- /**
- * Returns an unmodifiable view of persons list
- */
- List getPersonList();
-
- /**
- * Returns an unmodifiable view of tags list
- */
- List getTagList();
-
-}
diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/person/Address.java
deleted file mode 100644
index a2bd109c005e..000000000000
--- a/src/main/java/seedu/address/model/person/Address.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package seedu.address.model.person;
-
-
-import seedu.address.commons.exceptions.IllegalValueException;
-
-/**
- * Represents a Person's address in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)}
- */
-public class Address {
-
- public static final String MESSAGE_ADDRESS_CONSTRAINTS = "Person addresses can be in any format";
- public static final String ADDRESS_VALIDATION_REGEX = ".+";
-
- public final String value;
-
- /**
- * Validates given address.
- *
- * @throws IllegalValueException if given address string is invalid.
- */
- public Address(String address) throws IllegalValueException {
- assert address != null;
- if (!isValidAddress(address)) {
- throw new IllegalValueException(MESSAGE_ADDRESS_CONSTRAINTS);
- }
- this.value = address;
- }
-
- /**
- * Returns true if a given string is a valid person email.
- */
- public static boolean isValidAddress(String test) {
- return test.matches(ADDRESS_VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Address // instanceof handles nulls
- && this.value.equals(((Address) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/person/Email.java
deleted file mode 100644
index 5da4d1078236..000000000000
--- a/src/main/java/seedu/address/model/person/Email.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package seedu.address.model.person;
-
-
-import seedu.address.commons.exceptions.IllegalValueException;
-
-/**
- * Represents a Person's phone number in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)}
- */
-public class Email {
-
- public static final String MESSAGE_EMAIL_CONSTRAINTS =
- "Person emails should be 2 alphanumeric/period strings separated by '@'";
- public static final String EMAIL_VALIDATION_REGEX = "[\\w\\.]+@[\\w\\.]+";
-
- public final String value;
-
- /**
- * Validates given email.
- *
- * @throws IllegalValueException if given email address string is invalid.
- */
- public Email(String email) throws IllegalValueException {
- assert email != null;
- email = email.trim();
- if (!isValidEmail(email)) {
- throw new IllegalValueException(MESSAGE_EMAIL_CONSTRAINTS);
- }
- this.value = email;
- }
-
- /**
- * Returns if a given string is a valid person email.
- */
- public static boolean isValidEmail(String test) {
- return test.matches(EMAIL_VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Email // instanceof handles nulls
- && this.value.equals(((Email) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/person/Name.java
deleted file mode 100644
index 4f30033e70fe..000000000000
--- a/src/main/java/seedu/address/model/person/Name.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package seedu.address.model.person;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-
-/**
- * Represents a Person's name in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidName(String)}
- */
-public class Name {
-
- public static final String MESSAGE_NAME_CONSTRAINTS = "Person names should be spaces or alphanumeric characters";
- public static final String NAME_VALIDATION_REGEX = "[\\p{Alnum} ]+";
-
- public final String fullName;
-
- /**
- * Validates given name.
- *
- * @throws IllegalValueException if given name string is invalid.
- */
- public Name(String name) throws IllegalValueException {
- assert name != null;
- name = name.trim();
- if (!isValidName(name)) {
- throw new IllegalValueException(MESSAGE_NAME_CONSTRAINTS);
- }
- this.fullName = name;
- }
-
- /**
- * Returns true if a given string is a valid person name.
- */
- public static boolean isValidName(String test) {
- return test.matches(NAME_VALIDATION_REGEX);
- }
-
-
- @Override
- public String toString() {
- return fullName;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Name // instanceof handles nulls
- && this.fullName.equals(((Name) other).fullName)); // state check
- }
-
- @Override
- public int hashCode() {
- return fullName.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java
deleted file mode 100644
index 03ffce7d2e79..000000000000
--- a/src/main/java/seedu/address/model/person/Person.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package seedu.address.model.person;
-
-import seedu.address.commons.util.CollectionUtil;
-import seedu.address.model.tag.UniqueTagList;
-
-import java.util.Objects;
-
-/**
- * Represents a Person in the address book.
- * Guarantees: details are present and not null, field values are validated.
- */
-public class Person implements ReadOnlyPerson {
-
- private Name name;
- private Phone phone;
- private Email email;
- private Address address;
-
- private UniqueTagList tags;
-
- /**
- * Every field must be present and not null.
- */
- public Person(Name name, Phone phone, Email email, Address address, UniqueTagList tags) {
- assert !CollectionUtil.isAnyNull(name, phone, email, address, tags);
- this.name = name;
- this.phone = phone;
- this.email = email;
- this.address = address;
- this.tags = new UniqueTagList(tags); // protect internal tags from changes in the arg list
- }
-
- /**
- * Copy constructor.
- */
- public Person(ReadOnlyPerson source) {
- this(source.getName(), source.getPhone(), source.getEmail(), source.getAddress(), source.getTags());
- }
-
- @Override
- public Name getName() {
- return name;
- }
-
- @Override
- public Phone getPhone() {
- return phone;
- }
-
- @Override
- public Email getEmail() {
- return email;
- }
-
- @Override
- public Address getAddress() {
- return address;
- }
-
- @Override
- public UniqueTagList getTags() {
- return new UniqueTagList(tags);
- }
-
- /**
- * Replaces this person's tags with the tags in the argument tag list.
- */
- public void setTags(UniqueTagList replacement) {
- tags.setTags(replacement);
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof ReadOnlyPerson // instanceof handles nulls
- && this.isSameStateAs((ReadOnlyPerson) other));
- }
-
- @Override
- public int hashCode() {
- // use this method for custom fields hashing instead of implementing your own
- return Objects.hash(name, phone, email, address, tags);
- }
-
- @Override
- public String toString() {
- return getAsText();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/person/Phone.java
deleted file mode 100644
index d27b2244b727..000000000000
--- a/src/main/java/seedu/address/model/person/Phone.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package seedu.address.model.person;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-
-/**
- * Represents a Person's phone number in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)}
- */
-public class Phone {
-
- public static final String MESSAGE_PHONE_CONSTRAINTS = "Person phone numbers should only contain numbers";
- public static final String PHONE_VALIDATION_REGEX = "\\d+";
-
- public final String value;
-
- /**
- * Validates given phone number.
- *
- * @throws IllegalValueException if given phone string is invalid.
- */
- public Phone(String phone) throws IllegalValueException {
- assert phone != null;
- phone = phone.trim();
- if (!isValidPhone(phone)) {
- throw new IllegalValueException(MESSAGE_PHONE_CONSTRAINTS);
- }
- this.value = phone;
- }
-
- /**
- * Returns true if a given string is a valid person phone number.
- */
- public static boolean isValidPhone(String test) {
- return test.matches(PHONE_VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Phone // instanceof handles nulls
- && this.value.equals(((Phone) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/ReadOnlyPerson.java b/src/main/java/seedu/address/model/person/ReadOnlyPerson.java
deleted file mode 100644
index d45be4b5fe36..000000000000
--- a/src/main/java/seedu/address/model/person/ReadOnlyPerson.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package seedu.address.model.person;
-
-import seedu.address.model.tag.UniqueTagList;
-
-/**
- * A read-only immutable interface for a Person in the addressbook.
- * Implementations should guarantee: details are present and not null, field values are validated.
- */
-public interface ReadOnlyPerson {
-
- Name getName();
- Phone getPhone();
- Email getEmail();
- Address getAddress();
-
- /**
- * The returned TagList is a deep copy of the internal TagList,
- * changes on the returned list will not affect the person's internal tags.
- */
- UniqueTagList getTags();
-
- /**
- * Returns true if both have the same state. (interfaces cannot override .equals)
- */
- default boolean isSameStateAs(ReadOnlyPerson other) {
- return other == this // short circuit if same object
- || (other != null // this is first to avoid NPE below
- && other.getName().equals(this.getName()) // state checks here onwards
- && other.getPhone().equals(this.getPhone())
- && other.getEmail().equals(this.getEmail())
- && other.getAddress().equals(this.getAddress()));
- }
-
- /**
- * Formats the person as text, showing all contact details.
- */
- default String getAsText() {
- final StringBuilder builder = new StringBuilder();
- builder.append(getName())
- .append(" Phone: ")
- .append(getPhone())
- .append(" Email: ")
- .append(getEmail())
- .append(" Address: ")
- .append(getAddress())
- .append(" Tags: ");
- getTags().forEach(builder::append);
- return builder.toString();
- }
-
- /**
- * Returns a string representation of this Person's tags
- */
- default String tagsString() {
- final StringBuffer buffer = new StringBuffer();
- final String separator = ", ";
- getTags().forEach(tag -> buffer.append(tag).append(separator));
- if (buffer.length() == 0) {
- return "";
- } else {
- return buffer.substring(0, buffer.length() - separator.length());
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/person/UniquePersonList.java
deleted file mode 100644
index 263f1fcc7dd5..000000000000
--- a/src/main/java/seedu/address/model/person/UniquePersonList.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package seedu.address.model.person;
-
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-import seedu.address.commons.util.CollectionUtil;
-import seedu.address.commons.exceptions.DuplicateDataException;
-
-import java.util.*;
-
-/**
- * A list of persons that enforces uniqueness between its elements and does not allow nulls.
- *
- * Supports a minimal set of list operations.
- *
- * @see Person#equals(Object)
- * @see CollectionUtil#elementsAreUnique(Collection)
- */
-public class UniquePersonList implements Iterable {
-
- /**
- * Signals that an operation would have violated the 'no duplicates' property of the list.
- */
- public static class DuplicatePersonException extends DuplicateDataException {
- protected DuplicatePersonException() {
- super("Operation would result in duplicate persons");
- }
- }
-
- /**
- * Signals that an operation targeting a specified person in the list would fail because
- * there is no such matching person in the list.
- */
- public static class PersonNotFoundException extends Exception {}
-
- private final ObservableList internalList = FXCollections.observableArrayList();
-
- /**
- * Constructs empty PersonList.
- */
- public UniquePersonList() {}
-
- /**
- * Returns true if the list contains an equivalent person as the given argument.
- */
- public boolean contains(ReadOnlyPerson toCheck) {
- assert toCheck != null;
- return internalList.contains(toCheck);
- }
-
- /**
- * Adds a person to the list.
- *
- * @throws DuplicatePersonException if the person to add is a duplicate of an existing person in the list.
- */
- public void add(Person toAdd) throws DuplicatePersonException {
- assert toAdd != null;
- if (contains(toAdd)) {
- throw new DuplicatePersonException();
- }
- internalList.add(toAdd);
- }
-
- /**
- * Removes the equivalent person from the list.
- *
- * @throws PersonNotFoundException if no such person could be found in the list.
- */
- public boolean remove(ReadOnlyPerson toRemove) throws PersonNotFoundException {
- assert toRemove != null;
- final boolean personFoundAndDeleted = internalList.remove(toRemove);
- if (!personFoundAndDeleted) {
- throw new PersonNotFoundException();
- }
- return personFoundAndDeleted;
- }
-
- public ObservableList getInternalList() {
- return internalList;
- }
-
- @Override
- public Iterator iterator() {
- return internalList.iterator();
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof UniquePersonList // instanceof handles nulls
- && this.internalList.equals(
- ((UniquePersonList) other).internalList));
- }
-
- @Override
- public int hashCode() {
- return internalList.hashCode();
- }
-}
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 80033086985b..000000000000
--- a/src/main/java/seedu/address/storage/AddressBookStorage.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package seedu.address.storage;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-
-import java.io.IOException;
-import java.util.Optional;
-
-/**
- * Represents a storage for {@link seedu.address.model.AddressBook}.
- */
-public interface AddressBookStorage {
-
- /**
- * Returns the file path of the data file.
- */
- String 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(String 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, String filePath) throws IOException;
-
-}
diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java
deleted file mode 100644
index 91002a8a821a..000000000000
--- a/src/main/java/seedu/address/storage/Storage.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package seedu.address.storage;
-
-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 java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Optional;
-
-/**
- * API of the Storage component
- */
-public interface Storage extends AddressBookStorage, UserPrefsStorage {
-
- @Override
- Optional readUserPrefs() throws DataConversionException, IOException;
-
- @Override
- void saveUserPrefs(UserPrefs userPrefs) throws IOException;
-
- @Override
- String getAddressBookFilePath();
-
- @Override
- Optional readAddressBook() throws DataConversionException, IOException;
-
- @Override
- void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
-
- /**
- * Saves the current version of the Address Book to the hard disk.
- * Creates the data file if it is missing.
- * Raises {@link DataSavingExceptionEvent} if there was an error during saving.
- */
- void handleAddressBookChangedEvent(AddressBookChangedEvent abce);
-}
diff --git a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java
deleted file mode 100644
index f2167ec201b4..000000000000
--- a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package seedu.address.storage;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.person.*;
-import seedu.address.model.tag.Tag;
-import seedu.address.model.tag.UniqueTagList;
-
-import javax.xml.bind.annotation.XmlElement;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * JAXB-friendly version of the Person.
- */
-public class XmlAdaptedPerson {
-
- @XmlElement(required = true)
- private String name;
- @XmlElement(required = true)
- private String phone;
- @XmlElement(required = true)
- private String email;
- @XmlElement(required = true)
- private String address;
-
- @XmlElement
- private List tagged = new ArrayList<>();
-
- /**
- * No-arg constructor for JAXB use.
- */
- public XmlAdaptedPerson() {}
-
-
- /**
- * Converts a given Person into this class for JAXB use.
- *
- * @param source future changes to this will not affect the created XmlAdaptedPerson
- */
- public XmlAdaptedPerson(ReadOnlyPerson source) {
- name = source.getName().fullName;
- phone = source.getPhone().value;
- email = source.getEmail().value;
- address = source.getAddress().value;
- tagged = new ArrayList<>();
- for (Tag tag : source.getTags()) {
- tagged.add(new XmlAdaptedTag(tag));
- }
- }
-
- /**
- * Converts this jaxb-friendly adapted person object into the model's Person object.
- *
- * @throws IllegalValueException if there were any data constraints violated in the adapted person
- */
- public Person toModelType() throws IllegalValueException {
- final List personTags = new ArrayList<>();
- for (XmlAdaptedTag tag : tagged) {
- personTags.add(tag.toModelType());
- }
- final Name name = new Name(this.name);
- final Phone phone = new Phone(this.phone);
- final Email email = new Email(this.email);
- final Address address = new Address(this.address);
- final UniqueTagList tags = new UniqueTagList(personTags);
- return new Person(name, phone, email, address, tags);
- }
-}
diff --git a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java b/src/main/java/seedu/address/storage/XmlAddressBookStorage.java
deleted file mode 100644
index 30cb00270cc4..000000000000
--- a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package seedu.address.storage;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.util.FileUtil;
-import seedu.address.model.ReadOnlyAddressBook;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-/**
- * A class to access AddressBook data stored as an xml file on the hard disk.
- */
-public class XmlAddressBookStorage implements AddressBookStorage {
-
- private static final Logger logger = LogsCenter.getLogger(XmlAddressBookStorage.class);
-
- private String filePath;
-
- public XmlAddressBookStorage(String filePath){
- this.filePath = filePath;
- }
-
- public String getAddressBookFilePath(){
- return filePath;
- }
-
- /**
- * Similar to {@link #readAddressBook()}
- * @param filePath location of the data. Cannot be null
- * @throws DataConversionException if the file is not in the correct format.
- */
- public Optional readAddressBook(String filePath) throws DataConversionException, FileNotFoundException {
- assert filePath != null;
-
- File addressBookFile = new File(filePath);
-
- if (!addressBookFile.exists()) {
- logger.info("AddressBook file " + addressBookFile + " not found");
- return Optional.empty();
- }
-
- ReadOnlyAddressBook addressBookOptional = XmlFileStorage.loadDataFromSaveFile(new File(filePath));
-
- return Optional.of(addressBookOptional);
- }
-
- /**
- * Similar to {@link #saveAddressBook(ReadOnlyAddressBook)}
- * @param filePath location of the data. Cannot be null
- */
- public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) throws IOException {
- assert addressBook != null;
- assert filePath != null;
-
- File file = new File(filePath);
- FileUtil.createIfMissing(file);
- XmlFileStorage.saveDataToFile(file, new XmlSerializableAddressBook(addressBook));
- }
-
- @Override
- public Optional readAddressBook() throws DataConversionException, IOException {
- return readAddressBook(filePath);
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, filePath);
- }
-}
diff --git a/src/main/java/seedu/address/ui/BrowserPanel.java b/src/main/java/seedu/address/ui/BrowserPanel.java
deleted file mode 100644
index 54b88318019b..000000000000
--- a/src/main/java/seedu/address/ui/BrowserPanel.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package seedu.address.ui;
-
-import javafx.event.Event;
-import javafx.scene.Node;
-import javafx.scene.layout.AnchorPane;
-import javafx.scene.web.WebView;
-import seedu.address.commons.util.FxViewUtil;
-import seedu.address.model.person.ReadOnlyPerson;
-import seedu.address.commons.core.LogsCenter;
-
-import java.util.logging.Logger;
-
-/**
- * The Browser Panel of the App.
- */
-public class BrowserPanel extends UiPart{
-
- private static Logger logger = LogsCenter.getLogger(BrowserPanel.class);
- private WebView browser;
-
- /**
- * Constructor is kept private as {@link #load(AnchorPane)} is the only way to create a BrowserPanel.
- */
- private BrowserPanel() {
-
- }
-
- @Override
- public void setNode(Node node) {
- //not applicable
- }
-
- @Override
- public String getFxmlPath() {
- return null; //not applicable
- }
-
- /**
- * Factory method for creating a Browser Panel.
- * This method should be called after the FX runtime is initialized and in FX application thread.
- * @param placeholder The AnchorPane where the BrowserPanel must be inserted
- */
- public static BrowserPanel load(AnchorPane placeholder){
- logger.info("Initializing browser");
- BrowserPanel browserPanel = new BrowserPanel();
- browserPanel.browser = new WebView();
- placeholder.setOnKeyPressed(Event::consume); // To prevent triggering events for typing inside the loaded Web page.
- FxViewUtil.applyAnchorBoundaryParameters(browserPanel.browser, 0.0, 0.0, 0.0, 0.0);
- placeholder.getChildren().add(browserPanel.browser);
- return browserPanel;
- }
-
- public void loadPersonPage(ReadOnlyPerson person) {
- loadPage("https://www.google.com.sg/#safe=off&q=" + person.getName().fullName.replaceAll(" ", "+"));
- }
-
- public void loadPage(String url){
- browser.getEngine().load(url);
- }
-
- /**
- * Frees resources allocated to the browser.
- */
- public void freeResources() {
- browser = null;
- }
-
-}
diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java
deleted file mode 100644
index 259e9ad0d333..000000000000
--- a/src/main/java/seedu/address/ui/PersonCard.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package seedu.address.ui;
-
-import javafx.fxml.FXML;
-import javafx.scene.Node;
-import javafx.scene.control.Label;
-import javafx.scene.layout.HBox;
-import seedu.address.model.person.ReadOnlyPerson;
-
-public class PersonCard extends UiPart{
-
- private static final String FXML = "PersonListCard.fxml";
-
- @FXML
- private HBox cardPane;
- @FXML
- private Label name;
- @FXML
- private Label id;
- @FXML
- private Label phone;
- @FXML
- private Label address;
- @FXML
- private Label email;
- @FXML
- private Label tags;
-
- private ReadOnlyPerson person;
- private int displayedIndex;
-
- public PersonCard(){
-
- }
-
- public static PersonCard load(ReadOnlyPerson person, int displayedIndex){
- PersonCard card = new PersonCard();
- card.person = person;
- card.displayedIndex = displayedIndex;
- return UiPartLoader.loadUiPart(card);
- }
-
- @FXML
- public void initialize() {
- name.setText(person.getName().fullName);
- id.setText(displayedIndex + ". ");
- phone.setText(person.getPhone().value);
- address.setText(person.getAddress().value);
- email.setText(person.getEmail().value);
- tags.setText(person.tagsString());
- }
-
- public HBox getLayout() {
- return cardPane;
- }
-
- @Override
- public void setNode(Node node) {
- cardPane = (HBox)node;
- }
-
- @Override
- public String getFxmlPath() {
- return FXML;
- }
-}
diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/PersonListPanel.java
deleted file mode 100644
index 27d9381c47b5..000000000000
--- a/src/main/java/seedu/address/ui/PersonListPanel.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package seedu.address.ui;
-
-import javafx.application.Platform;
-import javafx.collections.ObservableList;
-import javafx.fxml.FXML;
-import javafx.scene.Node;
-import javafx.scene.control.ListCell;
-import javafx.scene.control.ListView;
-import javafx.scene.control.SplitPane;
-import javafx.scene.layout.AnchorPane;
-import javafx.scene.layout.VBox;
-import javafx.stage.Stage;
-import seedu.address.commons.events.ui.PersonPanelSelectionChangedEvent;
-import seedu.address.model.person.ReadOnlyPerson;
-import seedu.address.commons.core.LogsCenter;
-
-import java.util.logging.Logger;
-
-/**
- * Panel containing the list of persons.
- */
-public class PersonListPanel extends UiPart {
- private final Logger logger = LogsCenter.getLogger(PersonListPanel.class);
- private static final String FXML = "PersonListPanel.fxml";
- private VBox panel;
- private AnchorPane placeHolderPane;
-
- @FXML
- private ListView personListView;
-
- public PersonListPanel() {
- super();
- }
-
- @Override
- public void setNode(Node node) {
- panel = (VBox) node;
- }
-
- @Override
- public String getFxmlPath() {
- return FXML;
- }
-
- @Override
- public void setPlaceholder(AnchorPane pane) {
- this.placeHolderPane = pane;
- }
-
- public static PersonListPanel load(Stage primaryStage, AnchorPane personListPlaceholder,
- ObservableList personList) {
- PersonListPanel personListPanel =
- UiPartLoader.loadUiPart(primaryStage, personListPlaceholder, new PersonListPanel());
- personListPanel.configure(personList);
- return personListPanel;
- }
-
- private void configure(ObservableList personList) {
- setConnections(personList);
- addToPlaceholder();
- }
-
- private void setConnections(ObservableList personList) {
- personListView.setItems(personList);
- personListView.setCellFactory(listView -> new PersonListViewCell());
- setEventHandlerForSelectionChangeEvent();
- }
-
- private void addToPlaceholder() {
- SplitPane.setResizableWithParent(placeHolderPane, false);
- placeHolderPane.getChildren().add(panel);
- }
-
- private void setEventHandlerForSelectionChangeEvent() {
- personListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
- if (newValue != null) {
- logger.fine("Selection in person list panel changed to : '" + newValue + "'");
- raise(new PersonPanelSelectionChangedEvent(newValue));
- }
- });
- }
-
- public void scrollTo(int index) {
- Platform.runLater(() -> {
- personListView.scrollTo(index);
- personListView.getSelectionModel().clearAndSelect(index);
- });
- }
-
- class PersonListViewCell extends ListCell {
-
- public PersonListViewCell() {
- }
-
- @Override
- protected void updateItem(ReadOnlyPerson person, boolean empty) {
- super.updateItem(person, empty);
-
- if (empty || person == null) {
- setGraphic(null);
- setText(null);
- } else {
- setGraphic(PersonCard.load(person, getIndex() + 1).getLayout());
- }
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/taskell/MainApp.java
similarity index 69%
rename from src/main/java/seedu/address/MainApp.java
rename to src/main/java/seedu/taskell/MainApp.java
index 36dc72a74b7a..2f9ef6b39f87 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/taskell/MainApp.java
@@ -1,24 +1,27 @@
-package seedu.address;
+package seedu.taskell;
import com.google.common.eventbus.Subscribe;
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.StringUtil;
-import seedu.address.logic.Logic;
-import seedu.address.logic.LogicManager;
-import seedu.address.model.*;
-import seedu.address.commons.util.ConfigUtil;
-import seedu.address.storage.Storage;
-import seedu.address.storage.StorageManager;
-import seedu.address.ui.Ui;
-import seedu.address.ui.UiManager;
+import seedu.taskell.commons.core.Config;
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.core.Version;
+import seedu.taskell.commons.events.storage.StorageLocationChangedEvent;
+import seedu.taskell.commons.events.ui.ExitAppRequestEvent;
+import seedu.taskell.commons.exceptions.DataConversionException;
+import seedu.taskell.commons.util.ConfigUtil;
+import seedu.taskell.commons.util.StringUtil;
+import seedu.taskell.logic.Logic;
+import seedu.taskell.logic.LogicManager;
+import seedu.taskell.logic.commands.SaveStorageLocationCommand;
+import seedu.taskell.logic.commands.UndoCommand;
+import seedu.taskell.model.*;
+import seedu.taskell.storage.Storage;
+import seedu.taskell.storage.StorageManager;
+import seedu.taskell.ui.Ui;
+import seedu.taskell.ui.UiManager;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -45,11 +48,11 @@ public MainApp() {}
@Override
public void init() throws Exception {
- logger.info("=============================[ Initializing AddressBook ]===========================");
+ logger.info("=============================[ Initializing Task Manager ]===========================");
super.init();
config = initConfig(getApplicationParameter("config"));
- storage = new StorageManager(config.getAddressBookFilePath(), config.getUserPrefsFilePath());
+ storage = new StorageManager(config.getTaskManagerFilePath(), config.getUserPrefsFilePath());
userPrefs = initPrefs(config);
@@ -62,6 +65,11 @@ public void init() throws Exception {
ui = new UiManager(logic, config, userPrefs);
initEventsCenter();
+
+ UndoCommand.initializeCommandHistory();
+ UndoCommand.getInstance().setData(model);
+ SaveStorageLocationCommand.setConfig(config);
+ SaveStorageLocationCommand.setStorage(storage);
}
private String getApplicationParameter(String parameterName){
@@ -70,20 +78,20 @@ private String getApplicationParameter(String parameterName){
}
private Model initModelManager(Storage storage, UserPrefs userPrefs) {
- Optional addressBookOptional;
- ReadOnlyAddressBook initialData;
+ Optional taskManagerOptional;
+ ReadOnlyTaskManager initialData;
try {
- addressBookOptional = storage.readAddressBook();
- if(!addressBookOptional.isPresent()){
- logger.info("Data file not found. Will be starting with an empty AddressBook");
+ taskManagerOptional = storage.readTaskManager();
+ if(!taskManagerOptional.isPresent()){
+ logger.info("Data file not found. Will be starting with an empty TaskManager");
}
- initialData = addressBookOptional.orElse(new AddressBook());
+ initialData = taskManagerOptional.orElse(new TaskManager());
} 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 TaskManager");
+ initialData = new TaskManager();
} 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 TaskManager");
+ initialData = new TaskManager();
}
return new ModelManager(initialData, userPrefs);
@@ -139,7 +147,7 @@ protected UserPrefs initPrefs(Config config) {
"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 TaskManager");
initializedPrefs = new UserPrefs();
}
@@ -159,13 +167,13 @@ private void initEventsCenter() {
@Override
public void start(Stage primaryStage) {
- logger.info("Starting AddressBook " + MainApp.VERSION);
+ logger.info("Starting TaskManager " + MainApp.VERSION);
ui.start(primaryStage);
}
@Override
public void stop() {
- logger.info("============================ [ Stopping Address Book ] =============================");
+ logger.info("============================ [ Stopping Task Manager ] =============================");
ui.stop();
try {
storage.saveUserPrefs(userPrefs);
@@ -181,6 +189,14 @@ public void handleExitAppRequestEvent(ExitAppRequestEvent event) {
logger.info(LogsCenter.getEventHandlingLogMessage(event));
this.stop();
}
+
+ /** @@author A0142130A **/
+ @Subscribe
+ private void handleStorageLocationChangedEvent(StorageLocationChangedEvent event) {
+ config = event.getConfig();
+ storage = new StorageManager(config.getTaskManagerFilePath(), config.getUserPrefsFilePath());
+ }
+ /** @@author **/
public static void main(String[] args) {
launch(args);
diff --git a/src/main/java/seedu/address/commons/core/ComponentManager.java b/src/main/java/seedu/taskell/commons/core/ComponentManager.java
similarity index 87%
rename from src/main/java/seedu/address/commons/core/ComponentManager.java
rename to src/main/java/seedu/taskell/commons/core/ComponentManager.java
index 4bc8564e5824..e839ac9e2414 100644
--- a/src/main/java/seedu/address/commons/core/ComponentManager.java
+++ b/src/main/java/seedu/taskell/commons/core/ComponentManager.java
@@ -1,6 +1,6 @@
-package seedu.address.commons.core;
+package seedu.taskell.commons.core;
-import seedu.address.commons.events.BaseEvent;
+import seedu.taskell.commons.events.BaseEvent;
/**
* Base class for *Manager classes
diff --git a/src/main/java/seedu/address/commons/core/Config.java b/src/main/java/seedu/taskell/commons/core/Config.java
similarity index 62%
rename from src/main/java/seedu/address/commons/core/Config.java
rename to src/main/java/seedu/taskell/commons/core/Config.java
index 6441c9ef20f4..e16e49b00fc0 100644
--- a/src/main/java/seedu/address/commons/core/Config.java
+++ b/src/main/java/seedu/taskell/commons/core/Config.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.taskell.commons.core;
import java.util.Objects;
import java.util.logging.Level;
@@ -11,11 +11,11 @@ public class Config {
public static final String DEFAULT_CONFIG_FILE = "config.json";
// Config values customizable through config file
- private String appTitle = "Address App";
+ private String appTitle = "Taskell";
private Level logLevel = Level.INFO;
private String userPrefsFilePath = "preferences.json";
- private String addressBookFilePath = "data/addressbook.xml";
- private String addressBookName = "MyAddressBook";
+ private String taskManagerFilePath = "data/taskmanager.xml";
+ private String taskManagerName = "MyTaskManager";
public Config() {
@@ -45,29 +45,28 @@ public void setUserPrefsFilePath(String userPrefsFilePath) {
this.userPrefsFilePath = userPrefsFilePath;
}
- public String getAddressBookFilePath() {
- return addressBookFilePath;
+ public String getTaskManagerFilePath() {
+ return taskManagerFilePath;
}
- public void setAddressBookFilePath(String addressBookFilePath) {
- this.addressBookFilePath = addressBookFilePath;
+ public void setTaskManagerFilePath(String taskManagerFilePath) {
+ this.taskManagerFilePath = taskManagerFilePath;
}
- public String getAddressBookName() {
- return addressBookName;
+ public String getTaskManagerName() {
+ return taskManagerName;
}
- public void setAddressBookName(String addressBookName) {
- this.addressBookName = addressBookName;
+ public void setTaskManagerName(String taskManagerName) {
+ this.taskManagerName = taskManagerName;
}
-
@Override
public boolean equals(Object other) {
- if (other == this){
+ if (other == this) {
return true;
}
- if (!(other instanceof Config)){ //this handles null as well.
+ if (!(other instanceof Config)) { //this handles null as well.
return false;
}
@@ -76,23 +75,23 @@ public boolean equals(Object other) {
return Objects.equals(appTitle, o.appTitle)
&& Objects.equals(logLevel, o.logLevel)
&& Objects.equals(userPrefsFilePath, o.userPrefsFilePath)
- && Objects.equals(addressBookFilePath, o.addressBookFilePath)
- && Objects.equals(addressBookName, o.addressBookName);
+ && Objects.equals(taskManagerFilePath, o.taskManagerFilePath)
+ && Objects.equals(taskManagerName, o.taskManagerName);
}
@Override
public int hashCode() {
- return Objects.hash(appTitle, logLevel, userPrefsFilePath, addressBookFilePath, addressBookName);
+ return Objects.hash(appTitle, logLevel, userPrefsFilePath, taskManagerFilePath, taskManagerName);
}
@Override
- public String toString(){
+ public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("App title : " + appTitle);
sb.append("\nCurrent log level : " + logLevel);
sb.append("\nPreference file Location : " + userPrefsFilePath);
- sb.append("\nLocal data file location : " + addressBookFilePath);
- sb.append("\nAddressBook name : " + addressBookName);
+ sb.append("\nLocal data file location : " + taskManagerFilePath);
+ sb.append("\nTaskManager name : " + taskManagerName);
return sb.toString();
}
diff --git a/src/main/java/seedu/address/commons/core/EventsCenter.java b/src/main/java/seedu/taskell/commons/core/EventsCenter.java
similarity index 92%
rename from src/main/java/seedu/address/commons/core/EventsCenter.java
rename to src/main/java/seedu/taskell/commons/core/EventsCenter.java
index 9652cd5c227b..c546c0b09e1d 100644
--- a/src/main/java/seedu/address/commons/core/EventsCenter.java
+++ b/src/main/java/seedu/taskell/commons/core/EventsCenter.java
@@ -1,7 +1,8 @@
-package seedu.address.commons.core;
+package seedu.taskell.commons.core;
import com.google.common.eventbus.EventBus;
-import seedu.address.commons.events.BaseEvent;
+
+import seedu.taskell.commons.events.BaseEvent;
import java.util.logging.Logger;
diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/taskell/commons/core/GuiSettings.java
similarity index 98%
rename from src/main/java/seedu/address/commons/core/GuiSettings.java
rename to src/main/java/seedu/taskell/commons/core/GuiSettings.java
index e157ac8b8679..b8f551716126 100644
--- a/src/main/java/seedu/address/commons/core/GuiSettings.java
+++ b/src/main/java/seedu/taskell/commons/core/GuiSettings.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.taskell.commons.core;
import java.awt.*;
import java.io.Serializable;
diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/taskell/commons/core/LogsCenter.java
similarity index 96%
rename from src/main/java/seedu/address/commons/core/LogsCenter.java
rename to src/main/java/seedu/taskell/commons/core/LogsCenter.java
index 17939bab4975..ebb8ad5927af 100644
--- a/src/main/java/seedu/address/commons/core/LogsCenter.java
+++ b/src/main/java/seedu/taskell/commons/core/LogsCenter.java
@@ -1,10 +1,10 @@
-package seedu.address.commons.core;
-
-import seedu.address.commons.events.BaseEvent;
+package seedu.taskell.commons.core;
import java.io.IOException;
import java.util.logging.*;
+import seedu.taskell.commons.events.BaseEvent;
+
/**
* Configures and manages loggers and handlers, including their logging level
* Named {@link Logger}s can be obtained from this class
@@ -15,7 +15,7 @@
public class LogsCenter {
private static final int MAX_FILE_COUNT = 5;
private static final int MAX_FILE_SIZE_IN_BYTES = (int) (Math.pow(2, 20) * 5); // 5MB
- private static final String LOG_FILE = "addressbook.log";
+ private static final String LOG_FILE = "taskmanager.log";
private static Level currentLogLevel = Level.INFO;
private static final Logger logger = LogsCenter.getLogger(LogsCenter.class);
private static FileHandler fileHandler;
diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/taskell/commons/core/Messages.java
similarity index 51%
rename from src/main/java/seedu/address/commons/core/Messages.java
rename to src/main/java/seedu/taskell/commons/core/Messages.java
index 1deb3a1e4695..5237f37b560f 100644
--- a/src/main/java/seedu/address/commons/core/Messages.java
+++ b/src/main/java/seedu/taskell/commons/core/Messages.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.taskell.commons.core;
/**
* Container for user visible messages.
@@ -7,7 +7,7 @@ public class Messages {
public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
- public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
- public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
+ public static final String MESSAGE_INVALID_TASK_DISPLAYED_INDEX = "The task index provided is invalid";
+ public static final String MESSAGE_TASKS_LISTED_OVERVIEW = "%1$d tasks listed!";
}
diff --git a/src/main/java/seedu/address/commons/core/UnmodifiableObservableList.java b/src/main/java/seedu/taskell/commons/core/UnmodifiableObservableList.java
similarity index 99%
rename from src/main/java/seedu/address/commons/core/UnmodifiableObservableList.java
rename to src/main/java/seedu/taskell/commons/core/UnmodifiableObservableList.java
index 5c25d8647a8d..803d7ff77329 100644
--- a/src/main/java/seedu/address/commons/core/UnmodifiableObservableList.java
+++ b/src/main/java/seedu/taskell/commons/core/UnmodifiableObservableList.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.taskell.commons.core;
import javafx.beans.InvalidationListener;
import javafx.collections.ListChangeListener;
diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/seedu/taskell/commons/core/Version.java
similarity index 98%
rename from src/main/java/seedu/address/commons/core/Version.java
rename to src/main/java/seedu/taskell/commons/core/Version.java
index 7ecb85b18f82..61920725c5ed 100644
--- a/src/main/java/seedu/address/commons/core/Version.java
+++ b/src/main/java/seedu/taskell/commons/core/Version.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.taskell.commons.core;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
diff --git a/src/main/java/seedu/address/commons/events/BaseEvent.java b/src/main/java/seedu/taskell/commons/events/BaseEvent.java
similarity index 90%
rename from src/main/java/seedu/address/commons/events/BaseEvent.java
rename to src/main/java/seedu/taskell/commons/events/BaseEvent.java
index 723a9c69fbd5..24ff9515243c 100644
--- a/src/main/java/seedu/address/commons/events/BaseEvent.java
+++ b/src/main/java/seedu/taskell/commons/events/BaseEvent.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.events;
+package seedu.taskell.commons.events;
public abstract class BaseEvent {
diff --git a/src/main/java/seedu/taskell/commons/events/model/TaskManagerChangedEvent.java b/src/main/java/seedu/taskell/commons/events/model/TaskManagerChangedEvent.java
new file mode 100644
index 000000000000..30c9db225ef7
--- /dev/null
+++ b/src/main/java/seedu/taskell/commons/events/model/TaskManagerChangedEvent.java
@@ -0,0 +1,19 @@
+package seedu.taskell.commons.events.model;
+
+import seedu.taskell.commons.events.BaseEvent;
+import seedu.taskell.model.ReadOnlyTaskManager;
+
+/** Indicates the TaskManager in the model has changed*/
+public class TaskManagerChangedEvent extends BaseEvent {
+
+ public final ReadOnlyTaskManager data;
+
+ public TaskManagerChangedEvent(ReadOnlyTaskManager data){
+ this.data = data;
+ }
+
+ @Override
+ public String toString() {
+ return "number of tasks " + data.getTaskList().size() + ", number of tags " + data.getTagList().size();
+ }
+}
diff --git a/src/main/java/seedu/address/commons/events/storage/DataSavingExceptionEvent.java b/src/main/java/seedu/taskell/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/seedu/taskell/commons/events/storage/DataSavingExceptionEvent.java
index f0a0640ee523..dba2a61ebc8d 100644
--- a/src/main/java/seedu/address/commons/events/storage/DataSavingExceptionEvent.java
+++ b/src/main/java/seedu/taskell/commons/events/storage/DataSavingExceptionEvent.java
@@ -1,6 +1,6 @@
-package seedu.address.commons.events.storage;
+package seedu.taskell.commons.events.storage;
-import seedu.address.commons.events.BaseEvent;
+import seedu.taskell.commons.events.BaseEvent;
/**
* Indicates an exception during a file saving
diff --git a/src/main/java/seedu/taskell/commons/events/storage/StorageLocationChangedEvent.java b/src/main/java/seedu/taskell/commons/events/storage/StorageLocationChangedEvent.java
new file mode 100644
index 000000000000..ac1f736672af
--- /dev/null
+++ b/src/main/java/seedu/taskell/commons/events/storage/StorageLocationChangedEvent.java
@@ -0,0 +1,24 @@
+/** @@author A0142130A **/
+package seedu.taskell.commons.events.storage;
+
+import seedu.taskell.commons.core.Config;
+import seedu.taskell.commons.events.BaseEvent;
+
+public class StorageLocationChangedEvent extends BaseEvent {
+
+ private Config config;
+
+ public StorageLocationChangedEvent(Config config) {
+ this.config = config;
+ }
+
+ public Config getConfig() {
+ return config;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/commons/events/ui/DisplayCalendarViewEvent.java b/src/main/java/seedu/taskell/commons/events/ui/DisplayCalendarViewEvent.java
new file mode 100644
index 000000000000..09de3dc514ab
--- /dev/null
+++ b/src/main/java/seedu/taskell/commons/events/ui/DisplayCalendarViewEvent.java
@@ -0,0 +1,15 @@
+/** @@author A0142130A **/
+package seedu.taskell.commons.events.ui;
+
+import seedu.taskell.commons.events.BaseEvent;
+
+/** Indicates display panel needs to show calendar **/
+
+public class DisplayCalendarViewEvent extends BaseEvent {
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/commons/events/ui/DisplayListChangedEvent.java b/src/main/java/seedu/taskell/commons/events/ui/DisplayListChangedEvent.java
new file mode 100644
index 000000000000..125948cd6635
--- /dev/null
+++ b/src/main/java/seedu/taskell/commons/events/ui/DisplayListChangedEvent.java
@@ -0,0 +1,27 @@
+/** @@author A0142130A **/
+package seedu.taskell.commons.events.ui;
+
+import java.util.ArrayList;
+
+import seedu.taskell.commons.events.BaseEvent;
+
+/** Indicates a list needs to be displayed on Display Panel
+ * */
+public class DisplayListChangedEvent extends BaseEvent {
+
+ private ArrayList list;
+
+ public DisplayListChangedEvent(ArrayList list) {
+ this.list = list;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ public ArrayList getList() {
+ return list;
+ }
+
+}
diff --git a/src/main/java/seedu/address/commons/events/ui/ExitAppRequestEvent.java b/src/main/java/seedu/taskell/commons/events/ui/ExitAppRequestEvent.java
similarity index 70%
rename from src/main/java/seedu/address/commons/events/ui/ExitAppRequestEvent.java
rename to src/main/java/seedu/taskell/commons/events/ui/ExitAppRequestEvent.java
index 9af6194543a3..5400dc303cac 100644
--- a/src/main/java/seedu/address/commons/events/ui/ExitAppRequestEvent.java
+++ b/src/main/java/seedu/taskell/commons/events/ui/ExitAppRequestEvent.java
@@ -1,6 +1,6 @@
-package seedu.address.commons.events.ui;
+package seedu.taskell.commons.events.ui;
-import seedu.address.commons.events.BaseEvent;
+import seedu.taskell.commons.events.BaseEvent;
/**
* Indicates a request for App termination
diff --git a/src/main/java/seedu/address/commons/events/ui/IncorrectCommandAttemptedEvent.java b/src/main/java/seedu/taskell/commons/events/ui/IncorrectCommandAttemptedEvent.java
similarity index 68%
rename from src/main/java/seedu/address/commons/events/ui/IncorrectCommandAttemptedEvent.java
rename to src/main/java/seedu/taskell/commons/events/ui/IncorrectCommandAttemptedEvent.java
index 991f7ae9fa25..d07ccc8d5fac 100644
--- a/src/main/java/seedu/address/commons/events/ui/IncorrectCommandAttemptedEvent.java
+++ b/src/main/java/seedu/taskell/commons/events/ui/IncorrectCommandAttemptedEvent.java
@@ -1,7 +1,7 @@
-package seedu.address.commons.events.ui;
+package seedu.taskell.commons.events.ui;
-import seedu.address.commons.events.BaseEvent;
-import seedu.address.logic.commands.Command;
+import seedu.taskell.commons.events.BaseEvent;
+import seedu.taskell.logic.commands.Command;
/**
* Indicates an attempt to execute an incorrect command
diff --git a/src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java b/src/main/java/seedu/taskell/commons/events/ui/JumpToListRequestEvent.java
similarity index 68%
rename from src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java
rename to src/main/java/seedu/taskell/commons/events/ui/JumpToListRequestEvent.java
index 0580d27aecf5..94ded5eab69e 100644
--- a/src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java
+++ b/src/main/java/seedu/taskell/commons/events/ui/JumpToListRequestEvent.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.events.ui;
+package seedu.taskell.commons.events.ui;
-import seedu.address.commons.events.BaseEvent;
+import seedu.taskell.commons.events.BaseEvent;
/**
- * Indicates a request to jump to the list of persons
+ * Indicates a request to jump to the list of tasks
*/
public class JumpToListRequestEvent extends BaseEvent {
diff --git a/src/main/java/seedu/address/commons/events/ui/ShowHelpRequestEvent.java b/src/main/java/seedu/taskell/commons/events/ui/ShowHelpRequestEvent.java
similarity index 70%
rename from src/main/java/seedu/address/commons/events/ui/ShowHelpRequestEvent.java
rename to src/main/java/seedu/taskell/commons/events/ui/ShowHelpRequestEvent.java
index a7e40940b2c7..f35eaa16f4b1 100644
--- a/src/main/java/seedu/address/commons/events/ui/ShowHelpRequestEvent.java
+++ b/src/main/java/seedu/taskell/commons/events/ui/ShowHelpRequestEvent.java
@@ -1,6 +1,6 @@
-package seedu.address.commons.events.ui;
+package seedu.taskell.commons.events.ui;
-import seedu.address.commons.events.BaseEvent;
+import seedu.taskell.commons.events.BaseEvent;
/**
* An event requesting to view the help page.
diff --git a/src/main/java/seedu/taskell/commons/events/ui/TaskPanelSelectionChangedEvent.java b/src/main/java/seedu/taskell/commons/events/ui/TaskPanelSelectionChangedEvent.java
new file mode 100644
index 000000000000..29d70ad6cfb3
--- /dev/null
+++ b/src/main/java/seedu/taskell/commons/events/ui/TaskPanelSelectionChangedEvent.java
@@ -0,0 +1,26 @@
+package seedu.taskell.commons.events.ui;
+
+import seedu.taskell.commons.events.BaseEvent;
+import seedu.taskell.model.task.ReadOnlyTask;
+
+/**
+ * Represents a selection change in the Task List Panel
+ */
+public class TaskPanelSelectionChangedEvent extends BaseEvent {
+
+
+ private final ReadOnlyTask newSelection;
+
+ public TaskPanelSelectionChangedEvent(ReadOnlyTask newSelection){
+ this.newSelection = newSelection;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ public ReadOnlyTask getNewSelection() {
+ return newSelection;
+ }
+}
diff --git a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java b/src/main/java/seedu/taskell/commons/exceptions/DataConversionException.java
similarity index 84%
rename from src/main/java/seedu/address/commons/exceptions/DataConversionException.java
rename to src/main/java/seedu/taskell/commons/exceptions/DataConversionException.java
index 1f689bd8e3f9..04f4f5e2e5ea 100644
--- a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java
+++ b/src/main/java/seedu/taskell/commons/exceptions/DataConversionException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.taskell.commons.exceptions;
/**
* Represents an error during conversion of data from one format to another
diff --git a/src/main/java/seedu/address/commons/exceptions/DuplicateDataException.java b/src/main/java/seedu/taskell/commons/exceptions/DuplicateDataException.java
similarity index 85%
rename from src/main/java/seedu/address/commons/exceptions/DuplicateDataException.java
rename to src/main/java/seedu/taskell/commons/exceptions/DuplicateDataException.java
index 17aa63d5020c..28a22d88f6ae 100644
--- a/src/main/java/seedu/address/commons/exceptions/DuplicateDataException.java
+++ b/src/main/java/seedu/taskell/commons/exceptions/DuplicateDataException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.taskell.commons.exceptions;
/**
* Signals an error caused by duplicate data where there should be none.
diff --git a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java b/src/main/java/seedu/taskell/commons/exceptions/IllegalValueException.java
similarity index 88%
rename from src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
rename to src/main/java/seedu/taskell/commons/exceptions/IllegalValueException.java
index a473b43bd86f..6ad188df01f8 100644
--- a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
+++ b/src/main/java/seedu/taskell/commons/exceptions/IllegalValueException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.taskell.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/seedu/taskell/commons/util/AppUtil.java
similarity index 81%
rename from src/main/java/seedu/address/commons/util/AppUtil.java
rename to src/main/java/seedu/taskell/commons/util/AppUtil.java
index 649cc19aaeda..766b57c5b425 100644
--- a/src/main/java/seedu/address/commons/util/AppUtil.java
+++ b/src/main/java/seedu/taskell/commons/util/AppUtil.java
@@ -1,7 +1,7 @@
-package seedu.address.commons.util;
+package seedu.taskell.commons.util;
import javafx.scene.image.Image;
-import seedu.address.MainApp;
+import seedu.taskell.MainApp;
/**
* A container for App specific utility functions
diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/seedu/taskell/commons/util/CollectionUtil.java
similarity index 96%
rename from src/main/java/seedu/address/commons/util/CollectionUtil.java
rename to src/main/java/seedu/taskell/commons/util/CollectionUtil.java
index fde8394f31e5..6196975c934e 100644
--- a/src/main/java/seedu/address/commons/util/CollectionUtil.java
+++ b/src/main/java/seedu/taskell/commons/util/CollectionUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.taskell.commons.util;
import java.util.Collection;
import java.util.HashSet;
diff --git a/src/main/java/seedu/address/commons/util/ConfigUtil.java b/src/main/java/seedu/taskell/commons/util/ConfigUtil.java
similarity index 91%
rename from src/main/java/seedu/address/commons/util/ConfigUtil.java
rename to src/main/java/seedu/taskell/commons/util/ConfigUtil.java
index af42e03df06c..d91f07efb9da 100644
--- a/src/main/java/seedu/address/commons/util/ConfigUtil.java
+++ b/src/main/java/seedu/taskell/commons/util/ConfigUtil.java
@@ -1,14 +1,14 @@
-package seedu.address.commons.util;
-
-import seedu.address.commons.core.Config;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
+package seedu.taskell.commons.util;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
import java.util.logging.Logger;
+import seedu.taskell.commons.core.Config;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.exceptions.DataConversionException;
+
/**
* A class for accessing the Config File.
*/
diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/seedu/taskell/commons/util/FileUtil.java
similarity index 98%
rename from src/main/java/seedu/address/commons/util/FileUtil.java
rename to src/main/java/seedu/taskell/commons/util/FileUtil.java
index ca8221250de4..9ed774632f2a 100644
--- a/src/main/java/seedu/address/commons/util/FileUtil.java
+++ b/src/main/java/seedu/taskell/commons/util/FileUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.taskell.commons.util;
import java.io.File;
import java.io.IOException;
diff --git a/src/main/java/seedu/address/commons/util/FxViewUtil.java b/src/main/java/seedu/taskell/commons/util/FxViewUtil.java
similarity index 92%
rename from src/main/java/seedu/address/commons/util/FxViewUtil.java
rename to src/main/java/seedu/taskell/commons/util/FxViewUtil.java
index 900efa6bf5c3..b43bda757bb2 100644
--- a/src/main/java/seedu/address/commons/util/FxViewUtil.java
+++ b/src/main/java/seedu/taskell/commons/util/FxViewUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.taskell.commons.util;
import javafx.scene.Node;
import javafx.scene.layout.AnchorPane;
diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/seedu/taskell/commons/util/JsonUtil.java
similarity index 98%
rename from src/main/java/seedu/address/commons/util/JsonUtil.java
rename to src/main/java/seedu/taskell/commons/util/JsonUtil.java
index 80b67de5b7e8..51223ab439fa 100644
--- a/src/main/java/seedu/address/commons/util/JsonUtil.java
+++ b/src/main/java/seedu/taskell/commons/util/JsonUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.taskell.commons.util;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/taskell/commons/util/StringUtil.java
similarity index 96%
rename from src/main/java/seedu/address/commons/util/StringUtil.java
rename to src/main/java/seedu/taskell/commons/util/StringUtil.java
index 2e94740456a6..4cb571bb902b 100644
--- a/src/main/java/seedu/address/commons/util/StringUtil.java
+++ b/src/main/java/seedu/taskell/commons/util/StringUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.taskell.commons.util;
import java.io.PrintWriter;
import java.io.StringWriter;
diff --git a/src/main/java/seedu/address/commons/util/UrlUtil.java b/src/main/java/seedu/taskell/commons/util/UrlUtil.java
similarity index 94%
rename from src/main/java/seedu/address/commons/util/UrlUtil.java
rename to src/main/java/seedu/taskell/commons/util/UrlUtil.java
index 6bbab52b9840..a8e378738d57 100644
--- a/src/main/java/seedu/address/commons/util/UrlUtil.java
+++ b/src/main/java/seedu/taskell/commons/util/UrlUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.taskell.commons.util;
import java.net.URL;
diff --git a/src/main/java/seedu/address/commons/util/XmlUtil.java b/src/main/java/seedu/taskell/commons/util/XmlUtil.java
similarity index 98%
rename from src/main/java/seedu/address/commons/util/XmlUtil.java
rename to src/main/java/seedu/taskell/commons/util/XmlUtil.java
index 2087e7628a1d..142dbc266d4f 100644
--- a/src/main/java/seedu/address/commons/util/XmlUtil.java
+++ b/src/main/java/seedu/taskell/commons/util/XmlUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.taskell.commons.util;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/taskell/logic/Logic.java
similarity index 58%
rename from src/main/java/seedu/address/logic/Logic.java
rename to src/main/java/seedu/taskell/logic/Logic.java
index 4df1bc65cabb..c652c8685262 100644
--- a/src/main/java/seedu/address/logic/Logic.java
+++ b/src/main/java/seedu/taskell/logic/Logic.java
@@ -1,8 +1,8 @@
-package seedu.address.logic;
+package seedu.taskell.logic;
import javafx.collections.ObservableList;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.model.person.ReadOnlyPerson;
+import seedu.taskell.logic.commands.CommandResult;
+import seedu.taskell.model.task.ReadOnlyTask;
/**
* API of the Logic component
@@ -15,7 +15,7 @@ public interface Logic {
*/
CommandResult execute(String commandText);
- /** Returns the filtered list of persons */
- ObservableList getFilteredPersonList();
+ /** Returns the filtered list of tasks */
+ ObservableList getFilteredTaskList();
}
diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/taskell/logic/LogicManager.java
similarity index 60%
rename from src/main/java/seedu/address/logic/LogicManager.java
rename to src/main/java/seedu/taskell/logic/LogicManager.java
index ce4dc1903cff..76554fca0514 100644
--- a/src/main/java/seedu/address/logic/LogicManager.java
+++ b/src/main/java/seedu/taskell/logic/LogicManager.java
@@ -1,14 +1,14 @@
-package seedu.address.logic;
+package seedu.taskell.logic;
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.parser.Parser;
-import seedu.address.model.Model;
-import seedu.address.model.person.ReadOnlyPerson;
-import seedu.address.storage.Storage;
+import seedu.taskell.commons.core.ComponentManager;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.logic.commands.Command;
+import seedu.taskell.logic.commands.CommandResult;
+import seedu.taskell.logic.parser.Parser;
+import seedu.taskell.model.Model;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.storage.Storage;
import java.util.logging.Logger;
@@ -35,7 +35,7 @@ public CommandResult execute(String commandText) {
}
@Override
- public ObservableList getFilteredPersonList() {
- return model.getFilteredPersonList();
+ public ObservableList getFilteredTaskList() {
+ return model.getFilteredTaskList();
}
}
diff --git a/src/main/java/seedu/taskell/logic/commands/AddCommand.java b/src/main/java/seedu/taskell/logic/commands/AddCommand.java
new file mode 100644
index 000000000000..aba90b74b3ba
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/AddCommand.java
@@ -0,0 +1,69 @@
+package seedu.taskell.logic.commands;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.*;
+
+//@@author A0139257X
+/**
+ * Adds a task to the task manager.
+ */
+public class AddCommand extends Command {
+
+ public static final String COMMAND_WORD = "add";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a task to the task manager. "
+ + "Parameters: DESCRIPTION by/on[DATE] from[START_TIME] to[END_TIME] [p/PRIORITY] [#TAG]...\n"
+ + "Example: " + COMMAND_WORD
+ + " go for meeting on 1-1-2100 from 12.30AM to 12.45AM p/3 #work";
+
+ public static final String MESSAGE_SUCCESS = "New task added: %1$s";
+ public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the task manager";
+
+ private final Task toAdd;
+
+ /**
+ * Convenience constructor using raw values.
+ *
+ * @throws IllegalValueException if any of the raw values are invalid
+ */
+
+ public AddCommand(String description, String taskType, String startDate, String endDate, String startTime, String endTime, String taskPriority, Set tags)
+ throws IllegalValueException {
+ final Set tagSet = new HashSet<>();
+ for (String tagName : tags) {
+ tagSet.add(new Tag(tagName));
+ }
+
+ switch (taskType) {
+ case Task.FLOATING_TASK:
+ this.toAdd = new FloatingTask(description, taskPriority, TaskStatus.INCOMPLETE, new UniqueTagList(tagSet));
+ break;
+ case Task.EVENT_TASK:
+ this.toAdd = new EventTask(description, startDate, endDate, startTime, endTime, taskPriority, TaskStatus.INCOMPLETE, new UniqueTagList(tagSet));
+ break;
+ default:
+ toAdd = null;
+ }
+ }
+
+ //@@author A0139257X-reused
+ @Override
+ public CommandResult execute() {
+ assert model != null;
+ try {
+ model.addTask(toAdd);
+ UndoCommand.addTaskToCommandHistory(toAdd);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
+ } catch (UniqueTaskList.DuplicateTaskException e) {
+ UndoCommand.deletePreviousCommand();
+ return new CommandResult(MESSAGE_DUPLICATE_TASK);
+ }
+
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/taskell/logic/commands/ClearCommand.java
similarity index 56%
rename from src/main/java/seedu/address/logic/commands/ClearCommand.java
rename to src/main/java/seedu/taskell/logic/commands/ClearCommand.java
index 522d57189f51..ad354af80372 100644
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ b/src/main/java/seedu/taskell/logic/commands/ClearCommand.java
@@ -1,14 +1,14 @@
-package seedu.address.logic.commands;
+package seedu.taskell.logic.commands;
-import seedu.address.model.AddressBook;
+import seedu.taskell.model.TaskManager;
/**
- * Clears the address book.
+ * Clears the task manager.
*/
public class ClearCommand extends Command {
public static final String COMMAND_WORD = "clear";
- public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
+ public static final String MESSAGE_SUCCESS = "Task manager has been cleared!";
public ClearCommand() {}
@@ -16,7 +16,7 @@ public ClearCommand() {}
@Override
public CommandResult execute() {
assert model != null;
- model.resetData(AddressBook.getEmptyAddressBook());
+ model.resetData(TaskManager.getEmptyTaskManager());
return new CommandResult(MESSAGE_SUCCESS);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/taskell/logic/commands/Command.java
similarity index 67%
rename from src/main/java/seedu/address/logic/commands/Command.java
rename to src/main/java/seedu/taskell/logic/commands/Command.java
index 7c0ba2fd0161..87f517c5b4cc 100644
--- a/src/main/java/seedu/address/logic/commands/Command.java
+++ b/src/main/java/seedu/taskell/logic/commands/Command.java
@@ -1,9 +1,9 @@
-package seedu.address.logic.commands;
+package seedu.taskell.logic.commands;
-import seedu.address.commons.core.EventsCenter;
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.events.ui.IncorrectCommandAttemptedEvent;
-import seedu.address.model.Model;
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.events.ui.IncorrectCommandAttemptedEvent;
+import seedu.taskell.model.Model;
/**
* Represents a command with hidden internal logic and the ability to be executed.
@@ -12,13 +12,13 @@ public abstract class Command {
protected Model model;
/**
- * Constructs a feedback message to summarise an operation that displayed a listing of persons.
+ * Constructs a feedback message to summarise an operation that displayed a listing of tasks.
*
* @param displaySize used to generate summary
- * @return summary message for persons displayed
+ * @return summary message for tasks displayed
*/
- public static String getMessageForPersonListShownSummary(int displaySize) {
- return String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, displaySize);
+ public static String getMessageForTaskListShownSummary(int displaySize) {
+ return String.format(Messages.MESSAGE_TASKS_LISTED_OVERVIEW, displaySize);
}
/**
diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/taskell/logic/commands/CommandResult.java
similarity index 87%
rename from src/main/java/seedu/address/logic/commands/CommandResult.java
rename to src/main/java/seedu/taskell/logic/commands/CommandResult.java
index f46f2f31353e..fbc2d5e97862 100644
--- a/src/main/java/seedu/address/logic/commands/CommandResult.java
+++ b/src/main/java/seedu/taskell/logic/commands/CommandResult.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands;
+package seedu.taskell.logic.commands;
/**
* Represents the result of a command execution.
diff --git a/src/main/java/seedu/taskell/logic/commands/DeleteCommand.java b/src/main/java/seedu/taskell/logic/commands/DeleteCommand.java
new file mode 100644
index 000000000000..784eb030d199
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/DeleteCommand.java
@@ -0,0 +1,55 @@
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * Deletes a task identified using it's last displayed index from the task manager.
+ */
+public class DeleteCommand extends Command {
+
+ public static final String COMMAND_WORD = "delete";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DELETE_TASK_SUCCESS = "Deleted Task: %1$s";
+
+ public final int targetIndex;
+
+ public DeleteCommand(int targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ UndoCommand.deletePreviousCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ ReadOnlyTask taskToDelete = lastShownList.get(targetIndex - 1);
+
+ try {
+ model.deleteTask(taskToDelete);
+ UndoCommand.addTaskToCommandHistory((Task) taskToDelete);
+ ListUndoCommand.getInstance().setData(model);
+ ListUndoCommand.getInstance().indicateDisplayListChanged();
+ } catch (TaskNotFoundException tnfe) {
+ assert false : "The target task cannot be missing";
+ }
+
+ return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS, taskToDelete));
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/logic/commands/DoneCommand.java b/src/main/java/seedu/taskell/logic/commands/DoneCommand.java
new file mode 100644
index 000000000000..2ab71310c84b
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/DoneCommand.java
@@ -0,0 +1,58 @@
+//@@author A0148004R
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.TaskStatus;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+public class DoneCommand extends Command {
+ public static final String COMMAND_WORD = "done";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Done the task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DONE_TASK_SUCCESS = "Done Task: %1$s";
+
+ public final int targetIndex;
+
+
+ public DoneCommand(int targetIndex) {
+ this.targetIndex = targetIndex;
+
+ }
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ TaskStatus finsihedStatus = new TaskStatus(TaskStatus.FINISHED);
+
+ ReadOnlyTask taskToDone = lastShownList.get(targetIndex - 1);
+
+ Task newTask = new Task(taskToDone.getDescription(), taskToDone.getTaskType(), taskToDone.getStartDate(), taskToDone.getEndDate(),
+ taskToDone.getStartTime(), taskToDone.getEndTime(), taskToDone.getTaskPriority(), finsihedStatus, taskToDone.getTags());
+
+ try {
+ model.editTask(taskToDone, newTask);
+ } catch (TaskNotFoundException pnfe) {
+ assert false : "The target task cannot be missing";
+ } catch (UniqueTaskList.DuplicateTaskException e) {
+ return new CommandResult(AddCommand.MESSAGE_DUPLICATE_TASK);
+ }
+
+ return new CommandResult(String.format(MESSAGE_DONE_TASK_SUCCESS, taskToDone));
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/logic/commands/EditDescriptionCommand.java b/src/main/java/seedu/taskell/logic/commands/EditDescriptionCommand.java
new file mode 100644
index 000000000000..9f3345940ecb
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/EditDescriptionCommand.java
@@ -0,0 +1,71 @@
+//@@author A0142073R
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.Description;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.TaskDate;
+import seedu.taskell.model.task.TaskPriority;
+import seedu.taskell.model.task.TaskTime;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * Edits a task identified using it's last displayed index from the task manager.
+ */
+public class EditDescriptionCommand extends Command {
+ public static final String COMMAND_WORD_1 = "edit-desc";
+ public static final String COMMAND_WORD_2 = "edit-name";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD_1
+ + "/"+ COMMAND_WORD_2
+ + ": Edits the description task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer) NEW_DESCRIPTION\n"
+ + "Example: " + COMMAND_WORD_1 + " 1 buy cake\n"
+ + "Example: " + COMMAND_WORD_2 + " 2 do 2103t\n";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Original Task: %1$s \n\nUpdated Task: %2$s";
+
+ public final int targetIndex;
+ public final Description description;
+
+ public EditDescriptionCommand(int targetIndex, String newDescription) throws IllegalValueException {
+ this.targetIndex = targetIndex;
+ this.description = new Description(newDescription);
+ }
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ ReadOnlyTask taskToEdit = lastShownList.get(targetIndex - 1);
+
+ Task newTask = new Task(description,taskToEdit.getTaskType(),taskToEdit.getStartDate(), taskToEdit.getEndDate(), taskToEdit.getStartTime(),taskToEdit.getEndTime(),
+ taskToEdit.getTaskPriority(),taskToEdit.getTaskStatus(), taskToEdit.getTags()
+ );
+ try {
+ model.editTask(taskToEdit,newTask);
+ UndoCommand.addTaskToCommandHistory(newTask);
+ UndoCommand.addOldTaskToCommandHistory((Task) taskToEdit);
+ } catch (TaskNotFoundException pnfe) {
+ assert false : "The target task cannot be missing";
+ } catch (UniqueTaskList.DuplicateTaskException e) {
+ UndoCommand.deletePreviousCommand();
+ return new CommandResult(AddCommand.MESSAGE_DUPLICATE_TASK);
+ }
+
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, taskToEdit, newTask));
+ }
+}
+//@@author
diff --git a/src/main/java/seedu/taskell/logic/commands/EditEndDateCommand.java b/src/main/java/seedu/taskell/logic/commands/EditEndDateCommand.java
new file mode 100644
index 000000000000..14d27b4d8c06
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/EditEndDateCommand.java
@@ -0,0 +1,68 @@
+//@@author A0142073R
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.TaskDate;
+import seedu.taskell.model.task.TaskPriority;
+import seedu.taskell.model.task.TaskTime;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * Edits a task EndDate identified using it's last displayed index from the task
+ * manager.
+ */
+public class EditEndDateCommand extends Command {
+ public static final String COMMAND_WORD = "edit-endDate";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Edits the EndDate of a task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer) NEW_DATE\n" + "Example: " + COMMAND_WORD + " 1 8-8-2016 ";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Original Task: %1$s \n\nUpdatedTask: %2$s";
+
+ public final int targetIndex;
+ public final TaskDate endDate;
+
+ public EditEndDateCommand(int targetIndex, String EndDate) throws IllegalValueException {
+ this.targetIndex = targetIndex;
+ this.endDate = new TaskDate(EndDate);
+ }
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ ReadOnlyTask taskToEdit = lastShownList.get(targetIndex - 1);
+ if (taskToEdit.getTaskType().equals("FLOATING")) {
+ return new CommandResult("Unable to edit date of floating task");
+ }
+ Task newTask = new Task(taskToEdit.getDescription(), taskToEdit.getTaskType(), taskToEdit.getStartDate(),
+
+ endDate, taskToEdit.getStartTime(), taskToEdit.getEndTime(), taskToEdit.getTaskPriority(), taskToEdit.getTaskStatus(),
+
+ taskToEdit.getTags());
+ try {
+ model.editTask(taskToEdit, newTask);
+ } catch (TaskNotFoundException pnfe) {
+ assert false : "The target task cannot be missing";
+ } catch (UniqueTaskList.DuplicateTaskException e) {
+ return new CommandResult(AddCommand.MESSAGE_DUPLICATE_TASK);
+ }
+
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, taskToEdit, newTask));
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/logic/commands/EditEndTimeCommand.java b/src/main/java/seedu/taskell/logic/commands/EditEndTimeCommand.java
new file mode 100644
index 000000000000..4c3ea11997f2
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/EditEndTimeCommand.java
@@ -0,0 +1,69 @@
+//@@author A0142073R
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.TaskDate;
+import seedu.taskell.model.task.TaskPriority;
+import seedu.taskell.model.task.TaskTime;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * Edits a task end time identified using it's last displayed index from the task manager.
+ */
+public class EditEndTimeCommand extends Command {
+ public static final String COMMAND_WORD = "edit-endTime";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Edits the end time of a task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer) NEW_END_TIME\n"
+ + "Example: " + COMMAND_WORD + " 1 9pm ";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Original Task: %1$s \n\nUpdatedTask: %2$s";
+
+ public final int targetIndex;
+ public final TaskTime endTime;
+
+ public EditEndTimeCommand(int targetIndex, String newTime) throws IllegalValueException {
+ this.targetIndex = targetIndex;
+ this.endTime = new TaskTime(newTime);
+ }
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ ReadOnlyTask taskToEdit = lastShownList.get(targetIndex - 1);
+ if (taskToEdit.getTaskType().equals("FLOATING")) {
+ return new CommandResult("Unable to edit time of floating task");
+ }
+ Task newTask = new Task(taskToEdit.getDescription(),taskToEdit.getTaskType(),taskToEdit.getStartDate(), taskToEdit.getEndDate(), taskToEdit.getStartTime(),endTime,
+ taskToEdit.getTaskPriority(),taskToEdit.getTaskStatus(), taskToEdit.getTags()
+ );
+ try {
+ model.editTask(taskToEdit,newTask);
+ UndoCommand.addTaskToCommandHistory(newTask);
+ UndoCommand.addOldTaskToCommandHistory((Task) taskToEdit);
+ } catch (TaskNotFoundException pnfe) {
+ assert false : "The target task cannot be missing";
+ } catch (UniqueTaskList.DuplicateTaskException e) {
+ UndoCommand.deletePreviousCommand();
+ return new CommandResult(AddCommand.MESSAGE_DUPLICATE_TASK);
+ }
+
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, taskToEdit, newTask));
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/logic/commands/EditPriorityCommand.java b/src/main/java/seedu/taskell/logic/commands/EditPriorityCommand.java
new file mode 100644
index 000000000000..f939254ca226
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/EditPriorityCommand.java
@@ -0,0 +1,67 @@
+//@@author A0142073R
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.Description;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.TaskDate;
+import seedu.taskell.model.task.TaskPriority;
+import seedu.taskell.model.task.TaskTime;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * Edits the priority of a task identified using it's last displayed index from the task manager.
+ */
+public class EditPriorityCommand extends Command {
+ public static final String COMMAND_WORD = "edit-priority";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Edits the priority of a task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer) NEW_PRIORITY(must be between 0 to 3)\n"
+ + "Example: " + COMMAND_WORD + " 1 3 ";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Original Task: %1$s \n\nUpdatedTask: %2$s";
+
+ public final int targetIndex;
+ public final TaskPriority taskPriority;
+
+ public EditPriorityCommand(int targetIndex, String taskPriority) throws IllegalValueException {
+ this.targetIndex = targetIndex;
+ this.taskPriority = new TaskPriority(taskPriority);
+ }
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ ReadOnlyTask taskToEdit = lastShownList.get(targetIndex - 1);
+ Task newTask = new Task(taskToEdit.getDescription(),taskToEdit.getTaskType(),taskToEdit.getStartDate(), taskToEdit.getEndDate(), taskToEdit.getStartTime(),taskToEdit.getEndTime(),
+ taskPriority,taskToEdit.getTaskStatus(), taskToEdit.getTags()
+ );
+ try {
+ model.editTask(taskToEdit,newTask);
+ UndoCommand.addTaskToCommandHistory(newTask);
+ UndoCommand.addOldTaskToCommandHistory((Task) taskToEdit);
+ } catch (TaskNotFoundException pnfe) {
+ assert false : "The target task cannot be missing";
+ } catch (UniqueTaskList.DuplicateTaskException e) {
+ UndoCommand.deletePreviousCommand();
+ return new CommandResult(AddCommand.MESSAGE_DUPLICATE_TASK);
+ }
+
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, taskToEdit, newTask));
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/logic/commands/EditStartDateCommand.java b/src/main/java/seedu/taskell/logic/commands/EditStartDateCommand.java
new file mode 100644
index 000000000000..3b0de8d8d7c2
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/EditStartDateCommand.java
@@ -0,0 +1,68 @@
+//@@author A0142073R
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.TaskDate;
+import seedu.taskell.model.task.TaskPriority;
+import seedu.taskell.model.task.TaskTime;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * Edits a task startDate identified using it's last displayed index from the task
+ * manager.
+ */
+public class EditStartDateCommand extends Command {
+ public static final String COMMAND_WORD = "edit-startDate";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Edits the startDate of a task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer) NEW_DATE\n" + "Example: " + COMMAND_WORD + " 1 8-8-2016 ";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Original Task: %1$s \n\nUpdatedTask: %2$s";
+
+ public final int targetIndex;
+ public final TaskDate startDate;
+
+ public EditStartDateCommand(int targetIndex, String startDate) throws IllegalValueException {
+ this.targetIndex = targetIndex;
+ this.startDate = new TaskDate(startDate);
+ }
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ ReadOnlyTask taskToEdit = lastShownList.get(targetIndex - 1);
+ if (taskToEdit.getTaskType().equals("FLOATING")) {
+ return new CommandResult("Unable to edit date of floating task");
+ }
+ Task newTask = new Task(taskToEdit.getDescription(), taskToEdit.getTaskType(), startDate, taskToEdit.getEndDate(),
+ taskToEdit.getStartTime(), taskToEdit.getEndTime(), taskToEdit.getTaskPriority(), taskToEdit.getTaskStatus(), taskToEdit.getTags());
+ try {
+ model.editTask(taskToEdit, newTask);
+ UndoCommand.addTaskToCommandHistory(newTask);
+ UndoCommand.addOldTaskToCommandHistory((Task) taskToEdit);
+ } catch (TaskNotFoundException pnfe) {
+ assert false : "The target task cannot be missing";
+ } catch (UniqueTaskList.DuplicateTaskException e) {
+ UndoCommand.deletePreviousCommand();
+ return new CommandResult(AddCommand.MESSAGE_DUPLICATE_TASK);
+ }
+
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, taskToEdit, newTask));
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/logic/commands/EditStartTimeCommand.java b/src/main/java/seedu/taskell/logic/commands/EditStartTimeCommand.java
new file mode 100644
index 000000000000..42e7a38d7194
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/EditStartTimeCommand.java
@@ -0,0 +1,70 @@
+//@@author A0142073R
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.TaskDate;
+import seedu.taskell.model.task.TaskPriority;
+import seedu.taskell.model.task.TaskTime;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * Edits a task start time identified using it's last displayed index from the task manager.
+ */
+public class EditStartTimeCommand extends Command {
+ public static final String COMMAND_WORD = "edit-startTime";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Edits the start time of a task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer) NEW_START_TIME\n"
+ + "Example: " + COMMAND_WORD + " 1 2pm ";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Original Task: %1$s \n\nUpdatedTask: %2$s";
+
+ public final int targetIndex;
+ public final TaskTime startTime;
+
+ public EditStartTimeCommand(int targetIndex, String newTime) throws IllegalValueException {
+ this.targetIndex = targetIndex;
+ this.startTime = new TaskTime(newTime);
+ }
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ ReadOnlyTask taskToEdit = lastShownList.get(targetIndex - 1);
+
+ if (taskToEdit.getTaskType().equals("FLOATING")) {
+ return new CommandResult("Unable to edit time of floating task");
+ }
+ Task newTask = new Task(taskToEdit.getDescription(),taskToEdit.getTaskType(),taskToEdit.getStartDate(), taskToEdit.getEndDate(), startTime,taskToEdit.getEndTime(),
+ taskToEdit.getTaskPriority(),taskToEdit.getTaskStatus(), taskToEdit.getTags()
+ );
+ try {
+ model.editTask(taskToEdit,newTask);
+ UndoCommand.addTaskToCommandHistory(newTask);
+ UndoCommand.addOldTaskToCommandHistory((Task) taskToEdit);
+ } catch (TaskNotFoundException pnfe) {
+ assert false : "The target task cannot be missing";
+ } catch (UniqueTaskList.DuplicateTaskException e) {
+ UndoCommand.deletePreviousCommand();
+ return new CommandResult(AddCommand.MESSAGE_DUPLICATE_TASK);
+ }
+
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, taskToEdit, newTask));
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/taskell/logic/commands/ExitCommand.java
similarity index 69%
rename from src/main/java/seedu/address/logic/commands/ExitCommand.java
rename to src/main/java/seedu/taskell/logic/commands/ExitCommand.java
index d98233ce2a0b..e246ac2ed236 100644
--- a/src/main/java/seedu/address/logic/commands/ExitCommand.java
+++ b/src/main/java/seedu/taskell/logic/commands/ExitCommand.java
@@ -1,7 +1,7 @@
-package seedu.address.logic.commands;
+package seedu.taskell.logic.commands;
-import seedu.address.commons.core.EventsCenter;
-import seedu.address.commons.events.ui.ExitAppRequestEvent;
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.events.ui.ExitAppRequestEvent;
/**
* Terminates the program.
@@ -10,7 +10,7 @@ public class ExitCommand extends Command {
public static final String COMMAND_WORD = "exit";
- public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ...";
+ public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Task Manager as requested ...";
public ExitCommand() {}
diff --git a/src/main/java/seedu/taskell/logic/commands/FindCommand.java b/src/main/java/seedu/taskell/logic/commands/FindCommand.java
new file mode 100644
index 000000000000..22c3e4bda5d5
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/FindCommand.java
@@ -0,0 +1,31 @@
+/** @@author A0142130A **/
+package seedu.taskell.logic.commands;
+
+import java.util.Set;
+
+/**
+ * Finds and lists all tasks in task manager whose description and tags contains all of the argument keywords.
+ * Keyword matching is not case sensitive.
+ */
+public class FindCommand extends Command {
+
+ public static final String COMMAND_WORD = "find";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all tasks whose description contains all of "
+ + "the specified keywords (not case-sensitive) and displays them as a list with index numbers.\n"
+ + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
+ + "Example: " + COMMAND_WORD + " milk bananas chicken";
+
+ private final Set keywords;
+
+ public FindCommand(Set keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public CommandResult execute() {
+ model.updateFilteredTaskList(keywords);
+ return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size()));
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/logic/commands/FindTagCommand.java b/src/main/java/seedu/taskell/logic/commands/FindTagCommand.java
new file mode 100644
index 000000000000..c4d1e97b6c59
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/FindTagCommand.java
@@ -0,0 +1,31 @@
+/** @@author A0142130A **/
+package seedu.taskell.logic.commands;
+
+import java.util.Set;
+
+/**
+ * Finds and lists all tasks in task manager whose description contains any of the argument keywords.
+ * Keyword matching is not case sensitive.
+ */
+
+public class FindTagCommand extends Command {
+
+ public static final String COMMAND_WORD = "find-tag";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all tasks whose description contain any of "
+ + "the specified keywords (not case-sensitive) and displays them as a list with index numbers.\n"
+ + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
+ + "Example: " + COMMAND_WORD + " help study homework";
+
+ private final Set keywords;
+
+ public FindTagCommand(Set keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public CommandResult execute() {
+ model.updateFilteredTaskListByAnyKeyword(keywords);
+ return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size()));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/taskell/logic/commands/HelpCommand.java
similarity index 80%
rename from src/main/java/seedu/address/logic/commands/HelpCommand.java
rename to src/main/java/seedu/taskell/logic/commands/HelpCommand.java
index 65af96940242..70181eeff23e 100644
--- a/src/main/java/seedu/address/logic/commands/HelpCommand.java
+++ b/src/main/java/seedu/taskell/logic/commands/HelpCommand.java
@@ -1,8 +1,8 @@
-package seedu.address.logic.commands;
+package seedu.taskell.logic.commands;
-import seedu.address.commons.core.EventsCenter;
-import seedu.address.commons.events.ui.ShowHelpRequestEvent;
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.events.ui.ShowHelpRequestEvent;
/**
* Format full help instructions for every command for display.
diff --git a/src/main/java/seedu/address/logic/commands/IncorrectCommand.java b/src/main/java/seedu/taskell/logic/commands/IncorrectCommand.java
similarity index 92%
rename from src/main/java/seedu/address/logic/commands/IncorrectCommand.java
rename to src/main/java/seedu/taskell/logic/commands/IncorrectCommand.java
index 491d9cb9da35..c317d003693e 100644
--- a/src/main/java/seedu/address/logic/commands/IncorrectCommand.java
+++ b/src/main/java/seedu/taskell/logic/commands/IncorrectCommand.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands;
+package seedu.taskell.logic.commands;
/**
diff --git a/src/main/java/seedu/taskell/logic/commands/ListAllCommand.java b/src/main/java/seedu/taskell/logic/commands/ListAllCommand.java
new file mode 100644
index 000000000000..aa1422bfe787
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/ListAllCommand.java
@@ -0,0 +1,18 @@
+//@@author A0148004R
+package seedu.taskell.logic.commands;
+
+public class ListAllCommand extends Command {
+
+ public static final String COMMAND_WORD = "list-all";
+
+ public static final String MESSAGE_SUCCESS = "Listed all tasks";
+
+ public ListAllCommand() {}
+
+ @Override
+ public CommandResult execute() {
+ model.updateFilteredListToShowAll();
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/logic/commands/ListCommand.java b/src/main/java/seedu/taskell/logic/commands/ListCommand.java
new file mode 100644
index 000000000000..088dc66e499c
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/ListCommand.java
@@ -0,0 +1,32 @@
+//@@author A0148004R
+package seedu.taskell.logic.commands;
+
+
+/**
+ * Lists all tasks in the task manager to the user.
+ */
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import seedu.taskell.model.task.TaskStatus;
+
+public class ListCommand extends Command {
+
+ public static final String COMMAND_WORD = "list";
+
+ public static final String MESSAGE_SUCCESS = "Listed all tasks need to be done";
+
+ private Set keywordSet = new HashSet<>(Arrays.asList(TaskStatus.INCOMPLETE));
+
+ public ListCommand() {
+
+ }
+
+ @Override
+ public CommandResult execute() {
+ model.updateFilteredtaskListCompleted(keywordSet);
+ return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size()));
+ }
+}
+//@@author
diff --git a/src/main/java/seedu/taskell/logic/commands/ListDateCommand.java b/src/main/java/seedu/taskell/logic/commands/ListDateCommand.java
new file mode 100644
index 000000000000..087fdef408cf
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/ListDateCommand.java
@@ -0,0 +1,32 @@
+//@@author A0142073R
+package seedu.taskell.logic.commands;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import seedu.taskell.model.task.Task;
+
+public class ListDateCommand extends Command {
+
+ public static final String COMMAND_WORD = "list-date";
+
+ public static final String MESSAGE_SUCCESS = "Listed all tasks on a given date";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Lists tasks on a specific date.\n"
+ + "Parameters: DATE (must be a positive integer)\n" + "Example: " + COMMAND_WORD + " 8-8-2016 ";
+
+ private Set keywordSet;
+
+ public ListDateCommand(String date) {
+ keywordSet = new HashSet<>(Arrays.asList(date, Task.EVENT_TASK));
+ }
+
+ @Override
+ public CommandResult execute() {
+ model.updateFilteredtaskListDate(keywordSet);
+ return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size()));
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/logic/commands/ListDoneCommand.java b/src/main/java/seedu/taskell/logic/commands/ListDoneCommand.java
new file mode 100644
index 000000000000..36dd8bd35f75
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/ListDoneCommand.java
@@ -0,0 +1,28 @@
+//@@author A0148004R
+package seedu.taskell.logic.commands;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import seedu.taskell.model.task.TaskStatus;
+
+public class ListDoneCommand extends Command {
+
+ public static final String COMMAND_WORD = "list-done";
+
+ public static final String MESSAGE_SUCCESS = "Listed all completed tasks";
+
+ private Set keywordSet = new HashSet<>(Arrays.asList(TaskStatus.FINISHED));
+
+ public ListDoneCommand() {
+
+ }
+
+ @Override
+ public CommandResult execute() {
+ model.updateFilteredtaskListCompleted(keywordSet);
+ return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size()));
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/logic/commands/ListPriorityCommand.java b/src/main/java/seedu/taskell/logic/commands/ListPriorityCommand.java
new file mode 100644
index 000000000000..d2dfeab93679
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/ListPriorityCommand.java
@@ -0,0 +1,44 @@
+//@@author A0142073R
+package seedu.taskell.logic.commands;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import seedu.taskell.model.task.TaskPriority;
+
+public class ListPriorityCommand extends Command {
+
+ public static final String COMMAND_WORD = "list-priority";
+
+ public static final String MESSAGE_SUCCESS = "Listed all completed tasks in descending priority";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": List the task with the specified priority. "
+ + "Parameters: INDEX (must be between 0 and 3 inclusive).\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ private Set mostImportant = new HashSet<>(Arrays.asList(TaskPriority.HIGH_PRIORITY));
+ private Set important = new HashSet<>(Arrays.asList(TaskPriority.MEDIUM_PRIORITY));
+ private Set lessImportant = new HashSet<>(Arrays.asList(TaskPriority.LOW_PRIORITY));
+ private Set leastImportant = new HashSet<>(Arrays.asList(TaskPriority.NO_PRIORITY));
+
+ private Set keyword;
+ public ListPriorityCommand(String priority) {
+ if(priority.equals(TaskPriority.HIGH_PRIORITY))
+ keyword = mostImportant;
+ else if(priority.equals(TaskPriority.MEDIUM_PRIORITY))
+ keyword = important;
+ else if(priority.equals(TaskPriority.LOW_PRIORITY))
+ keyword = lessImportant;
+ else
+ keyword = leastImportant;
+ }
+
+ @Override
+ public CommandResult execute() {
+ model.updateFilteredTaskListPriority(keyword);
+ return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size()));
+ }
+}
+//@@author
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/logic/commands/ListUndoCommand.java b/src/main/java/seedu/taskell/logic/commands/ListUndoCommand.java
new file mode 100644
index 000000000000..5f66e64dc0e2
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/ListUndoCommand.java
@@ -0,0 +1,36 @@
+/** @@author A0142130A **/
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.events.ui.DisplayListChangedEvent;
+
+/** Lists a list of previous commands available for Undo operation
+ * */
+public class ListUndoCommand extends Command {
+
+ public static final String COMMAND_WORD = "list-undo";
+
+ public static final String MESSAGE_SUCCESS = "Listed all commands available for undo.";
+
+ private static ListUndoCommand self;
+
+ public static ListUndoCommand getInstance() {
+ if (self == null) {
+ self = new ListUndoCommand();
+ }
+
+ return self;
+ }
+
+ @Override
+ public CommandResult execute() {
+ indicateDisplayListChanged();
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+
+ public void indicateDisplayListChanged() {
+ EventsCenter.getInstance().post(
+ new DisplayListChangedEvent(UndoCommand.getListOfCommandHistoryText()));
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/logic/commands/SaveStorageLocationCommand.java b/src/main/java/seedu/taskell/logic/commands/SaveStorageLocationCommand.java
new file mode 100644
index 000000000000..d293c82834a0
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/SaveStorageLocationCommand.java
@@ -0,0 +1,105 @@
+/** @@author A0142130A **/
+package seedu.taskell.logic.commands;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import seedu.taskell.commons.core.Config;
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.events.storage.StorageLocationChangedEvent;
+import seedu.taskell.model.ReadOnlyTaskManager;
+import seedu.taskell.storage.JsonConfigStorage;
+import seedu.taskell.storage.Storage;
+
+/** Saves current data file to new filepath.
+ * */
+
+public class SaveStorageLocationCommand extends Command {
+
+ private Logger logger = LogsCenter.getLogger(SaveStorageLocationCommand.class.getName());
+
+ public static final String COMMAND_WORD = "save";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Saves data file to new location specified. "
+ + "New files can be auto-created as long as given directory is valid.\n"
+ + "Parameters: FILEPATH (must be valid)\n"
+ + "Example: " + COMMAND_WORD + " C:/Users/chicken/Desktop/cat";
+
+ private static final String MESSAGE_SUCCESS = "Data successfully saved to new location.";
+ private static final String MESSAGE_INVALID_PATH = "Filepath given is invalid. Filepath will be reset to old path.";
+
+ private static Config config;
+ private String newStorageFilePath, oldStorageFilePath;
+ private ReadOnlyTaskManager taskManager;
+ private static JsonConfigStorage jsonConfigStorage;
+ private static Storage storage;
+
+ public SaveStorageLocationCommand(String newStorageFilePath) {
+ this.oldStorageFilePath = config.getTaskManagerFilePath();
+ logger.info("Old file path: " + oldStorageFilePath);
+
+ this.newStorageFilePath = newStorageFilePath.trim().replace("\\", "/") + "/taskmanager.xml";
+ logger.info("New file path: " + this.newStorageFilePath);
+ jsonConfigStorage = new JsonConfigStorage(Config.DEFAULT_CONFIG_FILE);
+ }
+
+ public static void setConfig(Config c) {
+ config = c;
+ }
+
+ public static void setStorage(Storage s) {
+ storage = s;
+ }
+
+ @Override
+ public CommandResult execute() {
+ assert config != null;
+ assert jsonConfigStorage != null;
+
+ taskManager = model.getTaskManager();
+
+ config.setTaskManagerFilePath(newStorageFilePath);
+ indicateStorageLocationChanged();
+ try {
+ storage.saveTaskManager(taskManager, newStorageFilePath);
+ } catch (IOException e) {
+ handleInvalidFilePathException();
+ return new CommandResult(MESSAGE_INVALID_PATH);
+ }
+
+ saveToConfigJson();
+ model.updateFilteredListToShowAll();
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+
+ private void indicateStorageLocationChanged() {
+ assert config != null;
+ EventsCenter.getInstance().post(new StorageLocationChangedEvent(config));
+ }
+
+ private void handleInvalidFilePathException() {
+ logger.info("Error writing to filepath. Handling data save exception.");
+ assert config != null;
+
+ config.setTaskManagerFilePath(oldStorageFilePath); //set back to old filepath
+ indicateStorageLocationChanged();
+
+ try {
+ storage.saveTaskManager(taskManager, newStorageFilePath);
+ } catch (IOException e) {
+ logger.severe("Error saving task manager");
+ }
+
+ saveToConfigJson();
+ }
+
+ private void saveToConfigJson() {
+ try {
+ jsonConfigStorage.saveConfigFile(config);
+ } catch (IOException e) {
+ logger.severe("save to config json error");
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/logic/commands/SelectCommand.java b/src/main/java/seedu/taskell/logic/commands/SelectCommand.java
new file mode 100644
index 000000000000..88c591b77775
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/SelectCommand.java
@@ -0,0 +1,44 @@
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.core.Messages;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.commons.events.ui.JumpToListRequestEvent;
+import seedu.taskell.model.task.ReadOnlyTask;
+
+/**
+ * Selects a task identified using it's last displayed index from the task manager.
+ */
+public class SelectCommand extends Command {
+
+ public final int targetIndex;
+
+ public static final String COMMAND_WORD = "select";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Selects the task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_SELECT_TASK_SUCCESS = "Selected Task: %1$s";
+
+ public SelectCommand(int targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ EventsCenter.getInstance().post(new JumpToListRequestEvent(targetIndex - 1));
+ return new CommandResult(String.format(MESSAGE_SELECT_TASK_SUCCESS, targetIndex));
+
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/logic/commands/UndoCommand.java b/src/main/java/seedu/taskell/logic/commands/UndoCommand.java
new file mode 100644
index 000000000000..03e82acb57b2
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/UndoCommand.java
@@ -0,0 +1,291 @@
+/** @@author A0142130A **/
+package seedu.taskell.logic.commands;
+
+import java.util.ArrayList;
+import java.util.logging.Logger;
+
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.events.ui.DisplayListChangedEvent;
+import seedu.taskell.model.CommandHistory;
+import seedu.taskell.model.Model;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.UniqueTaskList.DuplicateTaskException;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * Undo previously executed command (add or delete only for now)
+ * Note: only for current session only (meaning after app is closed, history will be cleared)
+ */
+public class UndoCommand extends Command {
+ private static final Logger logger = LogsCenter.getLogger(UndoCommand.class.getName());
+
+ public static final String COMMAND_WORD = "undo";
+ public static final String EDIT = "edit";
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Undo a previously executed command.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 3";
+
+ private static final String MESSAGE_DELETE_TASK_SUCCESS = "Deleted Task: %1$s";
+ private static final String MESSAGE_ADD_TASK_SUCCESS = "Task added back: %1$s";
+ private static final String MESSAGE_EDIT_TASK_SUCCESS = "Task edited back to old version: %1$s";
+
+ private static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the task manager";
+ private static final String MESSAGE_NO_TASK_TO_UNDO = "No add or delete commands available to undo.";
+ private static final String MESSAGE_COMMAND_HISTORY_EMPTY = "No command history available for undo.";
+ private static final String MESSAGE_INVALID_INDEX = "Index is invalid";
+
+ private static ArrayList commandHistoryList;
+ private static UndoCommand self;
+
+ private int index;
+ private CommandHistory commandHistory;
+
+ public UndoCommand(int index) {
+ logger.info("Creating UndoCommand with index: " + index);
+ this.index = index;
+ }
+
+ public static UndoCommand getInstance() {
+ if (self == null) {
+ self = new UndoCommand(0);
+ }
+
+ return self;
+ }
+
+ public static ArrayList getListOfCommandHistoryText() {
+ assert commandHistoryList != null;
+
+ UndoCommand.getInstance().updateCommandList();
+
+ ArrayList list = new ArrayList<>();
+ for (CommandHistory history: commandHistoryList) {
+ list.add(history.getCommandText());
+ }
+
+ return list;
+ }
+
+ //removes commandHistory with tasks not present in system
+ private void updateCommandList() {
+ if (model == null) {
+ logger.severe("model is null");
+ return;
+ }
+ for (CommandHistory commandHistory: commandHistoryList) {
+ if (isCommandTypeAddOrEdit(commandHistory)
+ && !model.isTaskPresent(commandHistory.getTask())) {
+ commandHistoryList.remove(commandHistory);
+ } else if (isUndoEditCommand(commandHistory)
+ && !model.isTaskPresent(commandHistory.getOldTask())) {
+ commandHistoryList.remove(commandHistory);
+ }
+ }
+
+ }
+
+ private boolean isCommandTypeAddOrEdit(CommandHistory commandHistory) {
+ return (commandHistory.getCommandType().contains(AddCommand.COMMAND_WORD)
+ || commandHistory.getCommandType().contains(EDIT))
+ && !commandHistory.isRedoTrue();
+ }
+
+ private boolean isUndoEditCommand(CommandHistory commandHistory) {
+ return commandHistory.isRedoTrue()
+ && commandHistory.getCommandType().contains(EDIT);
+ }
+
+ @Override
+ public CommandResult execute() {
+
+ if (commandHistoryList.isEmpty()) {
+ return new CommandResult(String.format(MESSAGE_COMMAND_HISTORY_EMPTY));
+ } else if (index > commandHistoryList.size()) {
+ return new CommandResult(String.format(MESSAGE_INVALID_INDEX));
+ }
+
+ commandHistory = commandHistoryList.get(getOffset(index));
+
+ if (commandHistory.isRedoTrue()) {
+ return redoUndo();
+ }
+
+ switch (commandHistory.getCommandType()) {
+ case AddCommand.COMMAND_WORD:
+ return undoAdd();
+ case DeleteCommand.COMMAND_WORD:
+ return undoDelete();
+ case EditStartDateCommand.COMMAND_WORD:
+ return undoEdit();
+ case EditEndDateCommand.COMMAND_WORD:
+ return undoEdit();
+ case EditDescriptionCommand.COMMAND_WORD_1:
+ return undoEdit();
+ case EditDescriptionCommand.COMMAND_WORD_2:
+ return undoEdit();
+ case EditStartTimeCommand.COMMAND_WORD:
+ return undoEdit();
+ case EditEndTimeCommand.COMMAND_WORD:
+ return undoEdit();
+ case EditPriorityCommand.COMMAND_WORD:
+ return undoEdit();
+ default:
+ logger.severe("CommandHistory is invalid");
+ return new CommandResult(String.format(MESSAGE_NO_TASK_TO_UNDO));
+ }
+ }
+
+ private CommandResult redoUndo() {
+ switch (commandHistory.getCommandType()) {
+ case AddCommand.COMMAND_WORD:
+ return undoDelete();
+ case DeleteCommand.COMMAND_WORD:
+ return undoAdd();
+ case EditStartDateCommand.COMMAND_WORD:
+ return redoEdit();
+ case EditEndDateCommand.COMMAND_WORD:
+ return redoEdit();
+ case EditDescriptionCommand.COMMAND_WORD_1:
+ return redoEdit();
+ case EditDescriptionCommand.COMMAND_WORD_2:
+ return redoEdit();
+ case EditStartTimeCommand.COMMAND_WORD:
+ return redoEdit();
+ case EditEndTimeCommand.COMMAND_WORD:
+ return redoEdit();
+ case EditPriorityCommand.COMMAND_WORD:
+ return redoEdit();
+ default:
+ logger.severe("CommandHistory is invalid");
+ return new CommandResult(String.format(MESSAGE_NO_TASK_TO_UNDO));
+ }
+ }
+
+ private CommandResult undoEdit() {
+ try {
+ model.editTask(commandHistory.getTask(), commandHistory.getOldTask());
+ deleteCommandHistory();
+ addUndoCommand(commandHistory);
+ indicateDisplayListChanged();
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, commandHistory.getOldTask()));
+ } catch (DuplicateTaskException e) {
+ return new CommandResult(MESSAGE_DUPLICATE_TASK);
+ } catch (TaskNotFoundException e) {
+ assert false : "The target task cannot be missing";
+ }
+
+ assert false: "Undo edit should return a command result";
+ return null;
+ }
+
+ private CommandResult redoEdit() {
+ try {
+ model.editTask(commandHistory.getOldTask(), commandHistory.getTask());
+ deleteCommandHistory();
+ indicateDisplayListChanged();
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, commandHistory.getTask()));
+ } catch (DuplicateTaskException e) {
+ return new CommandResult(MESSAGE_DUPLICATE_TASK);
+ } catch (TaskNotFoundException e) {
+ assert false : "The target task cannot be missing";
+ }
+
+ assert false: "Redo edit should return a command result";
+ return null;
+ }
+
+ private CommandResult undoDelete() {
+ try {
+ model.addTask(commandHistory.getTask());
+ deleteCommandHistory();
+ addUndoCommand(commandHistory);
+ indicateDisplayListChanged();
+ return new CommandResult(String.format(MESSAGE_ADD_TASK_SUCCESS, commandHistory.getTask()));
+ } catch (DuplicateTaskException e) {
+ return new CommandResult(MESSAGE_DUPLICATE_TASK);
+ }
+ }
+
+ private CommandResult undoAdd() {
+ try {
+ model.deleteTask(commandHistory.getTask());
+ deleteCommandHistory();
+ addUndoCommand(commandHistory);
+ indicateDisplayListChanged();
+ } catch (TaskNotFoundException e) {
+ assert false : "The target task cannot be missing";
+ }
+ return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS, commandHistory.getTask()));
+ }
+
+ private void deleteCommandHistory() {
+ commandHistoryList.remove(commandHistory);
+ }
+
+ private void addUndoCommand(CommandHistory commandHistory) {
+ if (commandHistory.isRedoTrue()) {
+ return;
+ }
+ commandHistory.setCommandText("undo " + commandHistory.getCommandText());
+ commandHistory.setToRedoToTrue();
+ commandHistoryList.add(commandHistory);
+ }
+
+ /******** static methods *********/
+
+ public static void initializeCommandHistory() {
+ if (commandHistoryList == null) {
+ commandHistoryList = new ArrayList<>();
+ }
+ }
+
+ public static void clearCommandHistory() {
+ commandHistoryList.clear();
+ }
+
+ private static int getOffset(int index) {
+ return index - 1;
+ }
+
+ public static void addCommandToHistory(String commandText,
+ String commandType) {
+ assert commandHistoryList != null;
+ commandHistoryList.add(new CommandHistory(commandText, commandType));
+ }
+
+ public static void addTaskToCommandHistory(Task task) {
+ logger.info("Adding task to history");
+ if (commandHistoryList.isEmpty()) {
+ logger.warning("No command history to add task to");
+ return;
+ }
+
+ commandHistoryList.get(getOffset(commandHistoryList.size())).setTask(task);
+ }
+
+ public static void addOldTaskToCommandHistory(Task task) {
+ logger.info("Adding old task to history");
+ if (commandHistoryList.isEmpty()) {
+ logger.warning("No command history to add task to");
+ return;
+ }
+
+ commandHistoryList.get(getOffset(commandHistoryList.size())).setOldTask(task);
+ }
+
+ public static void deletePreviousCommand() {
+ logger.info("Command unsuccessfully executed. Deleting command history.");
+ if (commandHistoryList.isEmpty()) {
+ logger.warning("No command history to delete");
+ return;
+ }
+ commandHistoryList.remove(getOffset(commandHistoryList.size()));
+ }
+
+ /****** Event ******/
+ public void indicateDisplayListChanged() {
+ EventsCenter.getInstance().post(
+ new DisplayListChangedEvent(getListOfCommandHistoryText()));
+ }
+}
diff --git a/src/main/java/seedu/taskell/logic/commands/ViewCalendarCommand.java b/src/main/java/seedu/taskell/logic/commands/ViewCalendarCommand.java
new file mode 100644
index 000000000000..502cea7b9cd9
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/commands/ViewCalendarCommand.java
@@ -0,0 +1,26 @@
+/** @@author A0142130A **/
+package seedu.taskell.logic.commands;
+
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.events.ui.DisplayCalendarViewEvent;
+
+/** Shows calendar view on right panel
+ * */
+public class ViewCalendarCommand extends Command {
+
+ public static final String COMMAND_WORD_1 = "calendar";
+ public static final String COMMAND_WORD_2 = "cal";
+
+ private static final String MESSAGE_SUCCESS = "Displayed calendar.";
+
+ @Override
+ public CommandResult execute() {
+ indicateDisplayCalendarView();
+ return new CommandResult(String.format(MESSAGE_SUCCESS));
+ }
+
+ private void indicateDisplayCalendarView() {
+ EventsCenter.getInstance().post(new DisplayCalendarViewEvent());
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/logic/parser/Parser.java b/src/main/java/seedu/taskell/logic/parser/Parser.java
new file mode 100644
index 000000000000..8c6686a3a85e
--- /dev/null
+++ b/src/main/java/seedu/taskell/logic/parser/Parser.java
@@ -0,0 +1,873 @@
+package seedu.taskell.logic.parser;
+
+import static seedu.taskell.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.taskell.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+import static seedu.taskell.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.commons.util.StringUtil;
+import seedu.taskell.logic.commands.*;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.TaskDate;
+import seedu.taskell.model.task.TaskPriority;
+import seedu.taskell.model.task.TaskTime;
+
+/**
+ * Parses user input.
+ */
+public class Parser {
+
+ /**
+ * Used for initial separation of command word and args.
+ */
+ private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
+
+ private static final Pattern TASK_INDEX_ARGS_FORMAT = Pattern.compile("(?.+)");
+
+ private static final Pattern KEYWORDS_ARGS_FORMAT = Pattern.compile("(?\\S+(?:\\s+\\S+)*)"); // one
+
+ private static final Pattern TASK_DATA_ARGS_FORMAT = // '/' forward slashes
+ // are reserved for
+ // delimiter prefixes
+ Pattern.compile("(?[^/]+)" + " (?p?)p/(?[^/]+)"
+ + " (?p?)p/(?[^/]+)" + " (?p?)e/(?[^/]+)"
+ + " (?p?)e/(?[^/]+)"
+ + " (?p?)a/(?[^/]+)"
+ + " (?p?)a/(?[^/]+)" + "(?(?: t/[^/]+)*)"); // variable
+ // number
+ private static final String BY = "by";
+ private static final String ON = "on";
+ private static final String AT = "at";
+ private static final String FROM = "from";
+ private static final String TO = "to";
+
+ public Parser() {
+ }
+
+ /**
+ * Parses user input into command for execution.
+ *
+ * @param userInput
+ * full user input string
+ * @return the command based on the user input
+ */
+ public Command parseCommand(String userInput) {
+ final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
+ if (!matcher.matches()) {
+ return new IncorrectCommand(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:
+ UndoCommand.addCommandToHistory(userInput, commandWord);
+ return prepareAdd(arguments);
+
+ case SelectCommand.COMMAND_WORD:
+ return prepareSelect(arguments);
+
+ case DeleteCommand.COMMAND_WORD:
+ UndoCommand.addCommandToHistory(userInput, commandWord);
+ return prepareDelete(arguments);
+
+ case EditStartDateCommand.COMMAND_WORD:
+ UndoCommand.addCommandToHistory(userInput, commandWord);
+ return prepareEditStartDate(arguments);
+
+ case EditEndDateCommand.COMMAND_WORD:
+ UndoCommand.addCommandToHistory(userInput, commandWord);
+ return prepareEditEndDate(arguments);
+
+ case EditDescriptionCommand.COMMAND_WORD_1:
+ UndoCommand.addCommandToHistory(userInput, commandWord);
+ return prepareEditDescription(arguments);
+
+ case EditDescriptionCommand.COMMAND_WORD_2:
+ UndoCommand.addCommandToHistory(userInput, commandWord);
+ return prepareEditDescription(arguments);
+
+ case EditStartTimeCommand.COMMAND_WORD:
+ UndoCommand.addCommandToHistory(userInput, commandWord);
+ return prepareEditStartTime(arguments);
+
+ case EditEndTimeCommand.COMMAND_WORD:
+ UndoCommand.addCommandToHistory(userInput, commandWord);
+ return prepareEditEndTime(arguments);
+
+ case EditPriorityCommand.COMMAND_WORD:
+ UndoCommand.addCommandToHistory(userInput, commandWord);
+ return prepareEditPriority(arguments);
+
+ case ClearCommand.COMMAND_WORD:
+ return new ClearCommand();
+
+ case FindCommand.COMMAND_WORD:
+ return prepareFind(arguments);
+
+ case FindTagCommand.COMMAND_WORD:
+ return prepareFindByTag(arguments);
+
+ case ListCommand.COMMAND_WORD:
+ return new ListCommand();
+
+ case ListAllCommand.COMMAND_WORD:
+ return new ListAllCommand();
+
+ case ListDoneCommand.COMMAND_WORD:
+ return new ListDoneCommand();
+
+ case ListDateCommand.COMMAND_WORD:
+ return prepareListDate(arguments);
+
+ case ListPriorityCommand.COMMAND_WORD:
+ return prepareListPriority(arguments);
+
+ case UndoCommand.COMMAND_WORD:
+ return prepareUndo(arguments);
+
+ case SaveStorageLocationCommand.COMMAND_WORD:
+ return prepareSaveStorageLocation(arguments);
+
+ case ExitCommand.COMMAND_WORD:
+ return new ExitCommand();
+
+ case HelpCommand.COMMAND_WORD:
+ return new HelpCommand();
+
+ case DoneCommand.COMMAND_WORD:
+ return prepareDone(arguments);
+
+ case ListUndoCommand.COMMAND_WORD:
+ return new ListUndoCommand();
+
+ case ViewCalendarCommand.COMMAND_WORD_1:
+ return new ViewCalendarCommand();
+
+ case ViewCalendarCommand.COMMAND_WORD_2:
+ return new ViewCalendarCommand();
+
+
+
+ default:
+ return new IncorrectCommand(MESSAGE_UNKNOWN_COMMAND);
+ }
+ }
+
+ //@@author A0142073R
+ private Command prepareListDate(String arguments) {
+ if (arguments.isEmpty()) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListDateCommand.MESSAGE_USAGE));
+ }
+ StringTokenizer st = new StringTokenizer(arguments.trim(), " ");
+ String date = st.nextToken();
+ if (!TaskDate.isValidDate(date)) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListDateCommand.MESSAGE_USAGE));
+ }
+
+ return new ListDateCommand(date);
+ }
+
+
+ private Command prepareListPriority(String args) {
+ if (args.isEmpty()) {
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListPriorityCommand.MESSAGE_USAGE));
+ }
+ StringTokenizer st = new StringTokenizer(args.trim(), " ");
+ String intValue = st.nextToken();
+ if (st.hasMoreTokens()) {
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListPriorityCommand.MESSAGE_USAGE));
+ }
+ if (!isInt(intValue)) {
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditEndDateCommand.MESSAGE_USAGE));
+ }
+ int targetIdx = Integer.valueOf(intValue);
+ if (targetIdx < 0 || targetIdx > 3) {
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_TASK_DISPLAYED_INDEX, ListPriorityCommand.MESSAGE_USAGE));
+ } else
+ return new ListPriorityCommand(intValue);
+ }
+
+ /**
+ * Parses arguments in the context of the edit task startDate command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareEditStartDate(String args) {
+ String arguments = "";
+ if (args.isEmpty()) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditStartDateCommand.MESSAGE_USAGE));
+ }
+ StringTokenizer st = new StringTokenizer(args.trim(), " ");
+ String intValue = st.nextToken();
+ if (!isInt(intValue)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_TASK_DISPLAYED_INDEX, EditEndDateCommand.MESSAGE_USAGE));
+ }
+ int targetIdx = Integer.valueOf(intValue);
+ arguments = st.nextToken();
+ if (st.hasMoreTokens()) {
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditStartDateCommand.MESSAGE_USAGE));
+ }
+ if (!TaskDate.isValidDate(arguments)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditStartDateCommand.MESSAGE_USAGE));
+ }
+
+ try {
+ return new EditStartDateCommand(targetIdx, arguments);
+ } catch (IllegalValueException ive) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(ive.getMessage());
+ }
+ }
+
+
+ /**
+ * Parses arguments in the context of the edit task description command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareEditDescription(String args) {
+ String arguments = "";
+ if (args.isEmpty()) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditDescriptionCommand.MESSAGE_USAGE));
+ }
+ StringTokenizer st = new StringTokenizer(args.trim(), " ");
+ String intValue = st.nextToken();
+ if (!isInt(intValue)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_TASK_DISPLAYED_INDEX, EditDescriptionCommand.MESSAGE_USAGE));
+ }
+ int targetIdx = Integer.valueOf(intValue);
+ while (st.hasMoreTokens()) {
+ arguments += st.nextToken() + " ";
+ }
+ arguments = arguments.trim();
+ try {
+ return new EditDescriptionCommand(targetIdx, arguments);
+ } catch (IllegalValueException ive) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(ive.getMessage());
+ }
+ }
+
+
+ /**
+ * Parses arguments in the context of the edit start time command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareEditStartTime(String args) {
+ String arguments = "";
+ if (args.isEmpty()) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditStartTimeCommand.MESSAGE_USAGE));
+ }
+ StringTokenizer st = new StringTokenizer(args.trim(), " ");
+ String intValue = st.nextToken();
+ if (!isInt(intValue)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_TASK_DISPLAYED_INDEX, EditStartTimeCommand.MESSAGE_USAGE));
+ }
+
+ int targetIdx = Integer.valueOf(intValue);
+ arguments = st.nextToken();
+ if (st.hasMoreTokens()) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditStartTimeCommand.MESSAGE_USAGE));
+ }
+
+ if (!TaskTime.isValidTime(arguments)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditStartTimeCommand.MESSAGE_USAGE));
+ }
+
+ try {
+ return new EditStartTimeCommand(targetIdx, arguments);
+ } catch (IllegalValueException ive) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(ive.getMessage());
+ }
+ }
+
+ /**
+ * Parses arguments in the context of the edit task endDate command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareEditEndDate(String args) {
+ String arguments = "";
+ if (args.isEmpty()) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditEndDateCommand.MESSAGE_USAGE));
+ }
+ StringTokenizer st = new StringTokenizer(args.trim(), " ");
+ String intValue = st.nextToken();
+ if (!isInt(intValue)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditEndDateCommand.MESSAGE_USAGE));
+ }
+ int targetIdx = Integer.valueOf(intValue);
+ arguments = st.nextToken();
+ if (st.hasMoreTokens() || !TaskDate.isValidDate(arguments)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditEndDateCommand.MESSAGE_USAGE));
+ }
+
+ try {
+ return new EditEndDateCommand(targetIdx, arguments);
+ } catch (IllegalValueException ive) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(ive.getMessage());
+ }
+ }
+
+
+ /**
+ * Parses arguments in the context of the edit task end time command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareEditEndTime(String args) {
+ String arguments = "";
+ if (args.isEmpty()) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditEndTimeCommand.MESSAGE_USAGE));
+ }
+ StringTokenizer st = new StringTokenizer(args.trim(), " ");
+ String intValue = st.nextToken();
+ if (!isInt(intValue)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditEndTimeCommand.MESSAGE_USAGE));
+ }
+ int targetIdx = Integer.valueOf(intValue);
+ arguments = st.nextToken();
+ if (st.hasMoreTokens() || !TaskTime.isValidTime(arguments)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditEndTimeCommand.MESSAGE_USAGE));
+ }
+
+ try {
+ return new EditEndTimeCommand(targetIdx, arguments);
+ } catch (IllegalValueException ive) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(ive.getMessage());
+ }
+ }
+
+
+ /**
+ * Parses arguments in the context of the edit task priority command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareEditPriority(String args) {
+ String arguments = "";
+ if (args.isEmpty()) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditPriorityCommand.MESSAGE_USAGE));
+ }
+ StringTokenizer st = new StringTokenizer(args.trim(), " ");
+ int targetIdx = Integer.valueOf(st.nextToken());
+ arguments = st.nextToken();
+ if (st.hasMoreTokens() || !TaskPriority.isValidPriority(arguments)) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditPriorityCommand.MESSAGE_USAGE));
+ }
+ try {
+ return new EditPriorityCommand(targetIdx, arguments);
+ } catch (IllegalValueException ive) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(ive.getMessage());
+ }
+ }
+
+ //@@author
+
+
+ //@@author A0139257X
+
+ /**
+ * Parses arguments in the context of the add task command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareAdd(String args) {
+ if (args.isEmpty()) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+ }
+
+ ArrayList argsList = tokenizeArguments(args);
+ Queue initialQueue = initialiseArgQueue(argsList);
+ Queue descriptionQueue = new LinkedList();
+ Queue byQueue = new LinkedList();
+ Queue onQueue = new LinkedList();
+ Queue atQueue = new LinkedList();
+ Queue fromQueue = new LinkedList();
+ Queue toQueue = new LinkedList();
+
+ String description = "";
+ String startDate = TaskDate.DEFAULT_DATE;
+ String endDate = startDate;
+ String startTime = TaskTime.DEFAULT_START_TIME;
+ String endTime = TaskTime.DEFAULT_END_TIME;
+ String token = "";
+ String taskPriority = TaskPriority.DEFAULT_PRIORITY;
+ String tagString = "";
+
+ int priorityCount = 0;
+
+ boolean hasStartDate = false;
+ boolean hasEndDate = false;
+ boolean hasStartTime = false;
+ boolean hasEndTime = false;
+
+ while (!initialQueue.isEmpty()) {
+ token = initialQueue.poll().trim();
+ String tempToken = "";
+
+ if (!token.equals(BY) && !token.equals(ON) && !token.equals(AT) && !token.equals(FROM) && !token.equals(TO)
+ && !TaskDate.isValidDate(token) && !TaskTime.isValidTime(token) && !token.startsWith(Tag.PREFIX)
+ && !token.startsWith(TaskPriority.PREFIX)) {
+ tempToken = flushQueue(byQueue, onQueue, atQueue, fromQueue, toQueue);
+ if (!tempToken.isEmpty()) {
+ descriptionQueue.offer(tempToken);
+ }
+ descriptionQueue.offer(token);
+ continue;
+ } else if (token.equals(BY)) {
+ tempToken = flushQueue(byQueue, onQueue, atQueue, fromQueue, toQueue);
+ if (!tempToken.isEmpty()) {
+ descriptionQueue.offer(tempToken);
+ }
+ byQueue.offer(token);
+ continue;
+ } else if (token.equals(ON)) {
+ tempToken = flushQueue(byQueue, onQueue, atQueue, fromQueue, toQueue);
+ if (!tempToken.isEmpty()) {
+ descriptionQueue.offer(tempToken);
+ }
+ onQueue.offer(token);
+ continue;
+ } else if (token.equals(AT)) {
+ tempToken = flushQueue(byQueue, onQueue, atQueue, fromQueue, toQueue);
+ if (!tempToken.isEmpty()) {
+ descriptionQueue.offer(tempToken);
+ }
+ atQueue.offer(token);
+ continue;
+ } else if (token.equals(FROM)) {
+ tempToken = flushQueue(byQueue, onQueue, atQueue, fromQueue, toQueue);
+ if (!tempToken.isEmpty()) {
+ descriptionQueue.offer(tempToken);
+ }
+ fromQueue.offer(token);
+ continue;
+ } else if (token.equals(TO)) {
+ tempToken = flushQueue(byQueue, onQueue, atQueue, fromQueue, toQueue);
+ if (!tempToken.isEmpty()) {
+ descriptionQueue.offer(tempToken);
+ }
+ toQueue.offer(token);
+ continue;
+ } else if (token.startsWith(Tag.PREFIX)) {
+ tempToken = flushQueue(byQueue, onQueue, atQueue, fromQueue, toQueue);
+ if (!tempToken.isEmpty()) {
+ descriptionQueue.offer(tempToken);
+ }
+ tagString += " " + token;
+ continue;
+ } else if (token.startsWith(TaskPriority.PREFIX)) {
+ tempToken = flushQueue(byQueue, onQueue, atQueue, fromQueue, toQueue);
+ if (!tempToken.isEmpty()) {
+ descriptionQueue.offer(tempToken);
+ }
+ if (priorityCount > 0) {
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+ } else {
+ taskPriority = token.substring(token.indexOf(TaskPriority.PREFIX) + 2);
+ priorityCount++;
+ }
+ continue;
+ } else if (TaskDate.isValidDate(token)) {
+ if (byQueue.isEmpty() && onQueue.isEmpty() && atQueue.isEmpty() && fromQueue.isEmpty()
+ && toQueue.isEmpty()) {
+ descriptionQueue.offer(token);
+ } else if (!onQueue.isEmpty()) {
+ if (!hasStartDate) {
+ onQueue.poll();
+ startDate = token;
+ hasStartDate = true;
+ } else {
+ descriptionQueue.offer(onQueue.poll());
+ descriptionQueue.offer(token);
+ }
+ } else if (!byQueue.isEmpty()) {
+ if (!hasEndDate) {
+ byQueue.poll();
+ endDate = token;
+ hasEndDate = true;
+ } else {
+ descriptionQueue.offer(byQueue.poll());
+ descriptionQueue.offer(token);
+ }
+ } else if (!atQueue.isEmpty()) {
+ descriptionQueue.offer(atQueue.poll());
+ descriptionQueue.offer(token);
+ } else if (!fromQueue.isEmpty()) {
+ if (!hasStartDate) {
+ fromQueue.poll();
+ startDate = token;
+ hasStartDate = true;
+ } else {
+ descriptionQueue.offer(fromQueue.poll());
+ descriptionQueue.offer(token);
+ }
+ } else if (!toQueue.isEmpty()) {
+ if (!hasEndDate) {
+ toQueue.poll();
+ endDate = token;
+ hasEndDate = true;
+ } else {
+ descriptionQueue.offer(toQueue.poll());
+ descriptionQueue.offer(token);
+ }
+ }
+ } else if (TaskTime.isValidTime(token)) {
+ if (byQueue.isEmpty() && onQueue.isEmpty() && atQueue.isEmpty() && fromQueue.isEmpty()
+ && toQueue.isEmpty()) {
+ descriptionQueue.offer(token);
+ } else if (!byQueue.isEmpty()) {
+ if (!hasEndTime) {
+ byQueue.poll();
+ endTime = token;
+ hasEndTime = true;
+ } else {
+ descriptionQueue.offer(byQueue.poll());
+ descriptionQueue.offer(token);
+ }
+ } else if (!atQueue.isEmpty()) {
+ if (!hasStartTime) {
+ atQueue.poll();
+ startTime = token;
+ hasStartTime = true;
+ } else {
+ descriptionQueue.offer(atQueue.poll());
+ descriptionQueue.offer(token);
+ }
+ } else if (!fromQueue.isEmpty()) {
+ if (!hasStartTime) {
+ fromQueue.poll();
+ startTime = token;
+ hasStartTime = true;
+ } else {
+ descriptionQueue.offer(fromQueue.poll());
+ descriptionQueue.offer(token);
+ }
+ } else if (!toQueue.isEmpty()) {
+ if (!hasEndTime) {
+ toQueue.poll();
+ endTime = token;
+ hasEndTime = true;
+ } else {
+ descriptionQueue.offer(toQueue.poll());
+ descriptionQueue.offer(token);
+ }
+ } else if (!onQueue.isEmpty()) {
+ descriptionQueue.offer(onQueue.poll());
+ descriptionQueue.offer(token);
+ }
+ }
+ }
+
+ String tempToken = flushQueue(byQueue, onQueue, atQueue, fromQueue, toQueue);
+ if (!tempToken.isEmpty()) {
+ descriptionQueue.offer(tempToken);
+ }
+
+ while (!descriptionQueue.isEmpty()) {
+ description += descriptionQueue.poll() + " ";
+ }
+ description.trim();
+
+ if (!hasEndDate) {
+ endDate = startDate;
+ }
+
+ if ((TaskDate.isValidToday(startDate) && !hasStartTime) || startDate.equals(TaskDate.DEFAULT_DATE) && !hasStartTime) {
+ startTime = TaskTime.getTimeNow().toString();
+ }
+
+ if (hasStartDate || hasEndDate || hasStartTime || hasEndTime) {
+ try {
+ return new AddCommand(description, Task.EVENT_TASK, startDate, endDate, startTime, endTime,
+ taskPriority, getTagsFromArgs(tagString));
+ } catch (IllegalValueException ive) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(ive.getMessage());
+ }
+ } else {
+ try {
+ return new AddCommand(description, Task.FLOATING_TASK, startDate, endDate, startTime, endTime,
+ taskPriority, getTagsFromArgs(tagString));
+ } catch (IllegalValueException ive) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(ive.getMessage());
+ }
+ }
+
+ }
+
+ private String flushQueue(Queue byQueue, Queue onQueue, Queue atQueue,
+ Queue fromQueue, Queue toQueue) {
+ String token = "";
+
+ if (!byQueue.isEmpty()) {
+ token = byQueue.poll();
+ } else if (!onQueue.isEmpty()) {
+ token = onQueue.poll();
+ } else if (!atQueue.isEmpty()) {
+ token = atQueue.poll();
+ } else if (!fromQueue.isEmpty()) {
+ token = fromQueue.poll();
+ } else if (!toQueue.isEmpty()) {
+ token = toQueue.poll();
+ }
+
+ return token;
+ }
+
+ private Queue initialiseArgQueue(ArrayList argsList) {
+ Queue argsQueue = new LinkedList();
+ for (String arg : argsList) {
+ argsQueue.offer(arg);
+ }
+ return argsQueue;
+ }
+
+ private ArrayList tokenizeArguments(String args) {
+ ArrayList argsList = new ArrayList();
+ StringTokenizer st = new StringTokenizer(args, " ");
+ while (st.hasMoreTokens()) {
+ argsList.add(st.nextToken());
+ }
+ return argsList;
+ }
+ //@@author
+
+ /**
+ * Extracts the new task's tags from the add command's tag arguments string.
+ * Merges duplicate tag strings.
+ */
+ private static Set getTagsFromArgs(String tagArguments) throws IllegalValueException {
+ // no tags
+ if (tagArguments.isEmpty()) {
+ return Collections.emptySet();
+ }
+ // replace first delimiter prefix, then split
+ final Collection tagStrings = Arrays
+ .asList(tagArguments.replaceFirst(" " + Tag.PREFIX, "").split(" " + Tag.PREFIX));
+ return new HashSet<>(tagStrings);
+ }
+
+ /**
+ * Parses arguments in the context of the delete task command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareDelete(String args) {
+
+ Optional index = parseIndex(args);
+ if (!index.isPresent()) {
+ UndoCommand.deletePreviousCommand();
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
+ }
+
+ return new DeleteCommand(index.get());
+ }
+
+ /**
+ * Parses arguments in the context of the select task command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareSelect(String args) {
+ Optional index = parseIndex(args);
+ if (!index.isPresent()) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, SelectCommand.MESSAGE_USAGE));
+ }
+
+ return new SelectCommand(index.get());
+ }
+
+ /**
+ * Returns the specified index in the {@code command} IF a positive unsigned
+ * integer is given as the index. Returns an {@code Optional.empty()}
+ * otherwise.
+ */
+ private Optional parseIndex(String command) {
+ final Matcher matcher = TASK_INDEX_ARGS_FORMAT.matcher(command.trim());
+ if (!matcher.matches()) {
+ return Optional.empty();
+ }
+
+ String index = matcher.group("targetIndex");
+ if (!StringUtil.isUnsignedInteger(index)) {
+ return Optional.empty();
+ }
+ return Optional.of(Integer.parseInt(index));
+
+ }
+
+ /**
+ * Parses arguments in the context of the find task command.
+ *
+ * @param args
+ * string
+ * @return the prepared command
+ */
+ private Command prepareFind(String args) {
+ final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim());
+ if (!matcher.matches()) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+
+ // keywords delimited by whitespace
+ final String[] keywords = matcher.group("keywords").split("\\s+");
+ final Set keywordSet = new HashSet<>(Arrays.asList(keywords));
+ return new FindCommand(keywordSet);
+ }
+
+ /** @@author A0142130A **/
+
+ /**
+ * Parses arguments in the context of undo command.
+ *
+ */
+ private Command prepareUndo(String args) {
+ Optional index = parseIndex(args);
+ if (!index.isPresent()) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, UndoCommand.MESSAGE_USAGE));
+ }
+ return new UndoCommand(index.get());
+ }
+
+ /**
+ * Parses arguments in the context of the find task by tags command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareFindByTag(String args) {
+ final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim());
+ if (!matcher.matches()) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindTagCommand.MESSAGE_USAGE));
+ }
+
+ // keywords delimited by whitespace
+ final String[] keywords = matcher.group("keywords").split("\\s+");
+ final Set keywordSet = new HashSet<>(Arrays.asList(keywords));
+ return new FindTagCommand(keywordSet);
+
+ }
+
+ /**
+ * Parses arguments in the context of the save storage location command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareSaveStorageLocation(String args) {
+ if (args.isEmpty()) {
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, SaveStorageLocationCommand.MESSAGE_USAGE));
+ }
+ return new SaveStorageLocationCommand(args);
+ }
+ /** @@author **/
+
+ //@@author A0148004R
+ /**
+ * Parses arguments in the context of the done task command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareDone(String args) {
+ Optional index = parseIndex(args);
+ if (!index.isPresent()) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DoneCommand.MESSAGE_USAGE));
+ }
+
+ return new DoneCommand(index.get());
+ }
+ //@@author
+
+ //@@author A0142073R
+ private static boolean isInt(String s) {
+ try {
+ int i = Integer.parseInt(s);
+ return true;
+ }
+
+ catch (NumberFormatException er) {
+ return false;
+ }
+ }
+ //@@author
+}
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/model/CommandHistory.java b/src/main/java/seedu/taskell/model/CommandHistory.java
new file mode 100644
index 000000000000..c0560dbb3b45
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/CommandHistory.java
@@ -0,0 +1,77 @@
+/** @@author A0142130A **/
+package seedu.taskell.model;
+
+import seedu.taskell.model.task.Task;
+
+/** Stores the relevant details of a command so it can be undone via UndoCommand
+ * each Add/Delete/Edit Command executed should correspond to a CommandHistory
+ * stored in UndoCommand's list of CommandHistory
+ * */
+public class CommandHistory {
+ private String commandText, commandType;
+ private Task task; //relevent task to be added, deleted or edited
+ private Task oldTask; //oldTask needed for EditCommands
+ private boolean toRedo;
+
+ public CommandHistory() {
+ commandText = "default command text";
+ commandType = "default command type";
+ task = null;
+ toRedo = false;
+ }
+
+ public CommandHistory(String commandText, String commandType) {
+ assert commandText != null;
+ assert commandType != null;
+ assert !commandText.trim().isEmpty();
+ assert !commandType.trim().isEmpty();
+
+ this.commandText = commandText.trim();
+ this.commandType = commandType.trim();
+ this.task = null;
+ toRedo = false;
+ }
+
+ public String getCommandText() {
+ return commandText;
+ }
+
+ public String getCommandType() {
+ return commandType;
+ }
+
+ public Task getTask() {
+ return task;
+ }
+
+ public Task getOldTask() {
+ return oldTask;
+ }
+
+ public boolean isRedoTrue() {
+ return toRedo;
+ }
+
+ /**** Setter methods ****/
+
+ public void setCommandText(String text) {
+ this.commandText = text;
+ }
+
+ public void setTask(Task task) {
+ assert task != null;
+ this.task = task;
+ if (commandType.equals("delete")) {
+ commandText = "delete " + this.task.getAsText();
+ }
+ }
+
+ public void setOldTask(Task task) {
+ this.oldTask = task;
+ }
+
+ public void setToRedoToTrue() {
+ toRedo = true;
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/model/Model.java b/src/main/java/seedu/taskell/model/Model.java
new file mode 100644
index 000000000000..1a004d27597f
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/Model.java
@@ -0,0 +1,54 @@
+package seedu.taskell.model;
+
+import java.util.Set;
+
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * The API of the Model component.
+ */
+public interface Model {
+ /** Clears existing backing model and replaces with the provided new data. */
+ void resetData(ReadOnlyTaskManager newData);
+
+ /** Returns the TaskManager */
+ ReadOnlyTaskManager getTaskManager();
+
+ /** Deletes the given task. */
+ void deleteTask(ReadOnlyTask target) throws UniqueTaskList.TaskNotFoundException;
+
+ /** Adds the given task */
+ void addTask(Task task) throws UniqueTaskList.DuplicateTaskException;
+
+ /** Edits the given task
+ * @throws TaskNotFoundException */
+ void editTask(ReadOnlyTask task,Task newTask) throws UniqueTaskList.DuplicateTaskException, TaskNotFoundException;
+
+ /** Returns the filtered task list as an {@code UnmodifiableObservableList} */
+ UnmodifiableObservableList getFilteredTaskList();
+
+ /** Updates the filter of the filtered task list to show all tasks */
+ void updateFilteredListToShowAll();
+
+ /** Updates the filter of the filtered task list to filter by priority*/
+ void updateFilteredTaskListPriority(Set keywords);
+
+ /** Updates the filter of the filtered task list to filter by the given keywords (AND operation)*/
+ void updateFilteredTaskList(Set keywords);
+
+ /** Updates the filter of the filtered task list to filter by the given date*/
+ void updateFilteredtaskListDate(Set keywords);
+
+ /** Updates the filter of the filtered task list to filter by the any of given keywords (OR operation)*/
+ void updateFilteredTaskListByAnyKeyword(Set keywords);
+
+ /** Updates the filter of the filtered task list to filter by the given taskStatus keywords*/
+ void updateFilteredtaskListCompleted(Set keywords);
+
+ /** Checks if task is present in manager */
+ boolean isTaskPresent(Task task);
+}
diff --git a/src/main/java/seedu/taskell/model/ModelManager.java b/src/main/java/seedu/taskell/model/ModelManager.java
new file mode 100644
index 000000000000..fa07d2e2154c
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/ModelManager.java
@@ -0,0 +1,286 @@
+package seedu.taskell.model;
+
+import javafx.collections.transformation.FilteredList;
+import seedu.taskell.commons.core.ComponentManager;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.core.UnmodifiableObservableList;
+import seedu.taskell.commons.events.model.TaskManagerChangedEvent;
+import seedu.taskell.commons.util.StringUtil;
+import seedu.taskell.logic.commands.UndoCommand;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.DuplicateTaskException;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * Represents the in-memory model of the task manager data. All changes to any
+ * model should be synchronized.
+ */
+public class ModelManager extends ComponentManager implements Model {
+ private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
+
+ private final TaskManager taskManager;
+ private final FilteredList filteredTasks;
+
+ /**
+ * Initializes a ModelManager with the given TaskManager TaskManager and its
+ * variables should not be null
+ */
+ public ModelManager(TaskManager src, UserPrefs userPrefs) {
+ super();
+ assert src != null;
+ assert userPrefs != null;
+
+ logger.fine("Initializing with task manager: " + src + " and user prefs " + userPrefs);
+
+ taskManager = new TaskManager(src);
+ filteredTasks = new FilteredList<>(taskManager.getTasks());
+ }
+
+ public ModelManager() {
+ this(new TaskManager(), new UserPrefs());
+ }
+
+ public ModelManager(ReadOnlyTaskManager initialData, UserPrefs userPrefs) {
+ taskManager = new TaskManager(initialData);
+ filteredTasks = new FilteredList<>(taskManager.getTasks());
+ }
+
+ @Override
+ public void resetData(ReadOnlyTaskManager newData) {
+ taskManager.resetData(newData);
+ indicateTaskManagerChanged();
+ }
+
+ @Override
+ public ReadOnlyTaskManager getTaskManager() {
+ return taskManager;
+ }
+
+ /** Raises an event to indicate the model has changed */
+ private void indicateTaskManagerChanged() {
+ raise(new TaskManagerChangedEvent(taskManager));
+ }
+ //@@author A0142073R
+ @Override
+ public synchronized void editTask(ReadOnlyTask old, Task toEdit)
+ throws DuplicateTaskException, TaskNotFoundException {
+ taskManager.editTask(old, toEdit);
+ indicateTaskManagerChanged();
+ }
+ //@@author
+
+ @Override
+ public void deleteTask(ReadOnlyTask target) throws TaskNotFoundException {
+ taskManager.removeTask(target);
+ // UndoCommand.updateMostRecentDeletedTask(target);
+ indicateTaskManagerChanged();
+ }
+
+ @Override
+ public synchronized void addTask(Task task) throws UniqueTaskList.DuplicateTaskException {
+ taskManager.addTask(task);
+ // UndoCommand.updateMostRecentAddedTask(task);
+ updateFilteredListToShowAll();
+ indicateTaskManagerChanged();
+ }
+
+ @Override
+ public boolean isTaskPresent(Task task) {
+ assert task != null;
+ return taskManager.isTaskPresent(task);
+ }
+
+ // =========== Filtered Task List Accessors
+ // ===============================================================
+
+ @Override
+ public UnmodifiableObservableList getFilteredTaskList() {
+ return new UnmodifiableObservableList<>(filteredTasks);
+ }
+
+ @Override
+ public void updateFilteredListToShowAll() {
+ filteredTasks.setPredicate(null);
+ }
+
+ @Override
+ public void updateFilteredTaskList(Set keywords) {
+ updateFilteredTaskList(new PredicateExpression(new NameQualifier(keywords)));
+ }
+
+ //@@author A0142073R
+
+ @Override
+ public void updateFilteredtaskListDate(Set keywords) {
+ updateFilteredTaskList(new PredicateExpression(new DateQualifier(keywords)));
+ }
+
+ public void updateFilteredTaskListPriority(Set keywords) {
+ updateFilteredTaskList(new PredicateExpression(new PriorityQualifier(keywords)));
+
+ }
+ //@@author
+ /** @@author A0142130A **/
+ @Override
+ public void updateFilteredTaskListByAnyKeyword(Set keywords) {
+ updateFilteredTaskList(new PredicateExpression(new TagsQualifier(keywords)));
+ }
+
+ /** @@author **/
+ @Override
+ public void updateFilteredtaskListCompleted(Set keywords) {
+ updateFilteredTaskList(new PredicateExpression(new CompleteQualifier(keywords)));
+ }
+
+ private void updateFilteredTaskList(Expression expression) {
+ filteredTasks.setPredicate(expression::satisfies);
+ }
+
+ // ========== Inner classes/interfaces used for filtering
+ // ==================================================
+
+ interface Expression {
+ boolean satisfies(ReadOnlyTask task);
+
+ String toString();
+ }
+
+ private class PredicateExpression implements Expression {
+
+ private final Qualifier qualifier;
+
+ PredicateExpression(Qualifier qualifier) {
+ this.qualifier = qualifier;
+ }
+
+ @Override
+ public boolean satisfies(ReadOnlyTask task) {
+ return qualifier.run(task);
+ }
+
+ @Override
+ public String toString() {
+ return qualifier.toString();
+ }
+ }
+
+ interface Qualifier {
+ boolean run(ReadOnlyTask task);
+
+ String toString();
+ }
+
+ private class NameQualifier implements Qualifier {
+ private Set nameKeyWords;
+
+ NameQualifier(Set nameKeyWords) {
+ this.nameKeyWords = nameKeyWords;
+ }
+
+ /** @@author A0142130A **/
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ String searchString = task.getDescription().description + " " + task.tagsSimpleString();
+ return nameKeyWords.stream().allMatch(keyword -> StringUtil.containsIgnoreCase(searchString, keyword));
+ }
+
+ /** @@author **/
+
+ @Override
+ public String toString() {
+ return "name=" + String.join(", ", nameKeyWords);
+ }
+ }
+
+ /** @@author A0142130A **/
+ private class TagsQualifier implements Qualifier {
+ private Set tagsKeyWords;
+
+ TagsQualifier(Set keyWords) {
+ this.tagsKeyWords = keyWords;
+ }
+
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ return tagsKeyWords.stream()
+ .filter(keyword -> StringUtil.containsIgnoreCase(task.tagsSimpleString(), keyword)).findAny()
+ .isPresent();
+ }
+
+ @Override
+ public String toString() {
+ return "name=" + String.join(", ", tagsKeyWords);
+ }
+ }
+
+ /** @@author **/
+ //@@author A0148004R
+ private class CompleteQualifier implements Qualifier {
+ private Set CompleteKeyWords;
+
+ CompleteQualifier(Set CompleteKeyWords) {
+ this.CompleteKeyWords = CompleteKeyWords;
+ }
+
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ String searchString = task.getTaskStatus().taskStatus + " " + task.tagsSimpleString();
+ return CompleteKeyWords.stream().allMatch(keyword -> StringUtil.containsIgnoreCase(searchString, keyword));
+ }
+
+ @Override
+ public String toString() {
+ return "complete=" + String.join(", ", CompleteKeyWords);
+ }
+ }
+ //@@author
+ //@@author A0142073R
+ private class DateQualifier implements Qualifier {
+ private Set DateKeyWords;
+
+ DateQualifier(Set dateKeyWords) {
+ this.DateKeyWords = dateKeyWords;
+ }
+
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ String searchString = task.getStartDate().taskDate + " " + task.getTaskType();
+ return DateKeyWords.stream().allMatch(keyword -> StringUtil.containsIgnoreCase(searchString, keyword));
+ }
+
+ @Override
+ public String toString() {
+ return "date=" + String.join(", ", DateKeyWords);
+ }
+ }
+
+ private class PriorityQualifier implements Qualifier {
+ private Set PriorityKeyWords;
+
+ PriorityQualifier(Set keyWords) {
+ this.PriorityKeyWords = keyWords;
+ }
+
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ String searchString = task.getTaskPriority().taskPriority;
+ return PriorityKeyWords.stream().allMatch(keyword -> StringUtil.containsIgnoreCase(searchString, keyword));
+ }
+
+
+ @Override
+ public String toString() {
+ return "prioritye=" + String.join(", ", PriorityKeyWords);
+ }
+
+ }
+ //@@author
+}
diff --git a/src/main/java/seedu/taskell/model/ReadOnlyTaskManager.java b/src/main/java/seedu/taskell/model/ReadOnlyTaskManager.java
new file mode 100644
index 000000000000..a4a369644f99
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/ReadOnlyTaskManager.java
@@ -0,0 +1,30 @@
+package seedu.taskell.model;
+
+
+import java.util.List;
+
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.UniqueTaskList;
+
+/**
+ * Unmodifiable view of an task manager
+ */
+public interface ReadOnlyTaskManager {
+
+ UniqueTagList getUniqueTagList();
+
+ UniqueTaskList getUniqueTaskList();
+
+ /**
+ * Returns an unmodifiable view of tasks list
+ */
+ List getTaskList();
+
+ /**
+ * Returns an unmodifiable view of tags list
+ */
+ List getTagList();
+
+}
diff --git a/src/main/java/seedu/taskell/model/TaskManager.java b/src/main/java/seedu/taskell/model/TaskManager.java
new file mode 100644
index 000000000000..76d40c2f681a
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/TaskManager.java
@@ -0,0 +1,186 @@
+package seedu.taskell.model;
+
+import javafx.collections.ObservableList;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.UniqueTaskList;
+import seedu.taskell.model.task.UniqueTaskList.TaskNotFoundException;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Wraps all data at the task-manager level Duplicates are not allowed (by
+ * .equals comparison)
+ */
+public class TaskManager implements ReadOnlyTaskManager {
+
+ private final UniqueTaskList tasks;
+ private final UniqueTagList tags;
+
+ {
+ tasks = new UniqueTaskList();
+ tags = new UniqueTagList();
+ }
+
+ public TaskManager() {
+ }
+
+ /**
+ * Tasks and Tags are copied into this taskmanager
+ */
+ public TaskManager(ReadOnlyTaskManager toBeCopied) {
+ this(toBeCopied.getUniqueTaskList(), toBeCopied.getUniqueTagList());
+ }
+
+ /**
+ * Tasks and Tags are copied into this taskmanager
+ */
+ public TaskManager(UniqueTaskList tasks, UniqueTagList tags) {
+ resetData(tasks.getInternalList(), tags.getInternalList());
+ }
+
+ public static ReadOnlyTaskManager getEmptyTaskManager() {
+ return new TaskManager();
+ }
+
+ //// list overwrite operations
+
+ public ObservableList getTasks() {
+ return tasks.getInternalList();
+ }
+
+ public void setTasks(List tasks) {
+ this.tasks.getInternalList().setAll(tasks);
+ }
+
+ public void setTags(Collection tags) {
+ this.tags.getInternalList().setAll(tags);
+ }
+
+ public void resetData(Collection extends ReadOnlyTask> newTasks, Collection newTags) {
+ setTasks(newTasks.stream().map(Task::new).collect(Collectors.toList()));
+ setTags(newTags);
+ }
+
+ public void resetData(ReadOnlyTaskManager newData) {
+ resetData(newData.getTaskList(), newData.getTagList());
+ }
+
+ //// task-level operations
+
+ /**
+ * Adds a task to the task manager. Also checks the new task's tags and
+ * updates {@link #tags} with any new tags found, and updates the Tag
+ * objects in the task to point to those in {@link #tags}.
+ *
+ * @throws UniqueTaskList.DuplicateTaskException
+ * if an equivalent task already exists.
+ */
+ public void addTask(Task p) throws UniqueTaskList.DuplicateTaskException {
+ syncTagsWithMasterList(p);
+ tasks.add(p);
+ }
+
+ //@@author A0142073R
+ /**
+ * Edits a task in task manager.
+ *
+ * @throws UniqueTaskList.DuplicateTaskException
+ * if an equivalent task already exists.
+ * @throws TaskNotFoundException
+ */
+ public boolean editTask(ReadOnlyTask old, Task p) throws UniqueTaskList.DuplicateTaskException, TaskNotFoundException {
+ if (tasks.edit(old, p)) {
+ return true;
+ } else {
+ throw new UniqueTaskList.TaskNotFoundException();
+ }
+ }
+ //@@author
+
+ /**
+ * Ensures that every tag in this task: - exists in the master list
+ * {@link #tags} - points to a Tag object in the master list
+ */
+ private void syncTagsWithMasterList(Task task) {
+ final UniqueTagList taskTags = task.getTags();
+ tags.mergeFrom(taskTags);
+
+ // Create map with values = tag object references in the master list
+ final Map masterTagObjects = new HashMap<>();
+ for (Tag tag : tags) {
+ masterTagObjects.put(tag, tag);
+ }
+
+ // Rebuild the list of task tags using references from the master list
+ final Set commonTagReferences = new HashSet<>();
+ for (Tag tag : taskTags) {
+ commonTagReferences.add(masterTagObjects.get(tag));
+ }
+ task.setTags(new UniqueTagList(commonTagReferences));
+ }
+
+ public boolean removeTask(ReadOnlyTask key) throws UniqueTaskList.TaskNotFoundException {
+ if (tasks.remove(key)) {
+ return true;
+ } else {
+ throw new UniqueTaskList.TaskNotFoundException();
+ }
+ }
+
+ //// tag-level operations
+
+ public void addTag(Tag t) throws UniqueTagList.DuplicateTagException {
+ tags.add(t);
+ }
+
+ //// util methods
+
+ @Override
+ public String toString() {
+ return tasks.getInternalList().size() + " tasks, " + tags.getInternalList().size() + " tags";
+ // TODO: refine later
+ }
+
+ @Override
+ public List getTaskList() {
+ return Collections.unmodifiableList(tasks.getInternalList());
+ }
+
+ @Override
+ public List getTagList() {
+ return Collections.unmodifiableList(tags.getInternalList());
+ }
+
+ @Override
+ public UniqueTaskList getUniqueTaskList() {
+ return this.tasks;
+ }
+
+ @Override
+ public UniqueTagList getUniqueTagList() {
+ return this.tags;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TaskManager // instanceof handles nulls
+ && this.tasks.equals(((TaskManager) other).tasks)
+ && this.tags.equals(((TaskManager) other).tags));
+ }
+
+ @Override
+ public int hashCode() {
+ // use this method for custom fields hashing instead of implementing
+ // your own
+ return Objects.hash(tasks, tags);
+ }
+
+ public boolean isTaskPresent(Task task) {
+ return tasks.contains(task);
+ }
+}
diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/taskell/model/UserPrefs.java
similarity index 93%
rename from src/main/java/seedu/address/model/UserPrefs.java
rename to src/main/java/seedu/taskell/model/UserPrefs.java
index da9c8037f495..15887a84e149 100644
--- a/src/main/java/seedu/address/model/UserPrefs.java
+++ b/src/main/java/seedu/taskell/model/UserPrefs.java
@@ -1,9 +1,9 @@
-package seedu.address.model;
-
-import seedu.address.commons.core.GuiSettings;
+package seedu.taskell.model;
import java.util.Objects;
+import seedu.taskell.commons.core.GuiSettings;
+
/**
* Represents User's preferences.
*/
diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/seedu/taskell/model/tag/Tag.java
similarity index 84%
rename from src/main/java/seedu/address/model/tag/Tag.java
rename to src/main/java/seedu/taskell/model/tag/Tag.java
index 5bcffdb5ddf1..ab17eafbff57 100644
--- a/src/main/java/seedu/address/model/tag/Tag.java
+++ b/src/main/java/seedu/taskell/model/tag/Tag.java
@@ -1,16 +1,17 @@
-package seedu.address.model.tag;
+package seedu.taskell.model.tag;
-import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.taskell.commons.exceptions.IllegalValueException;
/**
- * Represents a Tag in the address book.
+ * Represents a Tag in the task manager.
* Guarantees: immutable; name is valid as declared in {@link #isValidTagName(String)}
*/
public class Tag {
public static final String MESSAGE_TAG_CONSTRAINTS = "Tags names should be alphanumeric";
public static final String TAG_VALIDATION_REGEX = "\\p{Alnum}+";
+ public static final String PREFIX = "#";
public String tagName;
@@ -56,5 +57,9 @@ public int hashCode() {
public String toString() {
return '[' + tagName + ']';
}
+
+ public String toSimpleString() {
+ return tagName;
+ }
}
diff --git a/src/main/java/seedu/address/model/tag/UniqueTagList.java b/src/main/java/seedu/taskell/model/tag/UniqueTagList.java
similarity index 96%
rename from src/main/java/seedu/address/model/tag/UniqueTagList.java
rename to src/main/java/seedu/taskell/model/tag/UniqueTagList.java
index 76fb7ff3dc5d..22c310084eb4 100644
--- a/src/main/java/seedu/address/model/tag/UniqueTagList.java
+++ b/src/main/java/seedu/taskell/model/tag/UniqueTagList.java
@@ -1,9 +1,9 @@
-package seedu.address.model.tag;
+package seedu.taskell.model.tag;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
-import seedu.address.commons.util.CollectionUtil;
-import seedu.address.commons.exceptions.DuplicateDataException;
+import seedu.taskell.commons.exceptions.DuplicateDataException;
+import seedu.taskell.commons.util.CollectionUtil;
import java.util.*;
diff --git a/src/main/java/seedu/taskell/model/task/Description.java b/src/main/java/seedu/taskell/model/task/Description.java
new file mode 100644
index 000000000000..0855955f2a8b
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/Description.java
@@ -0,0 +1,58 @@
+package seedu.taskell.model.task;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+
+//@@author A0139257X
+/**
+ * Represents a Task's description in the task manager.
+ * Guarantees: immutable; is valid as declared in {@link #isValidDescription(String)}
+ */
+public class Description {
+
+ public static final String MESSAGE_DESCRIPTION_CONSTRAINTS = "Task description should be spaces or alphanumeric characters";
+
+ public String description;
+
+ /**
+ * Validates given description.
+ *
+ * @throws IllegalValueException if given description string is invalid.
+ */
+ public Description(String description) throws IllegalValueException {
+ assert description != null;
+ description = description.trim();
+ if (!isValidDescription(description)) {
+ throw new IllegalValueException(MESSAGE_DESCRIPTION_CONSTRAINTS);
+ }
+ this.description = description;
+ }
+
+ /**
+ * Returns true if a given string is a valid task description.
+ */
+ public static boolean isValidDescription(String test) {
+ return !test.isEmpty();
+ }
+
+ public void setDescription(String description){
+ this.description = description;
+ }
+
+ @Override
+ public String toString() {
+ return description;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Description // instanceof handles nulls
+ && this.description.equals(((Description) other).description)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return description.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/model/task/EventTask.java b/src/main/java/seedu/taskell/model/task/EventTask.java
new file mode 100644
index 000000000000..bd8dba7a35e8
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/EventTask.java
@@ -0,0 +1,87 @@
+package seedu.taskell.model.task;
+
+import java.util.Objects;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.commons.util.CollectionUtil;
+import seedu.taskell.model.tag.UniqueTagList;
+
+//@@author A0139257X
+/**
+ * Represents an Event task in the task manager.
+ * Guarantees: details are present and not null, field values are validated.
+ */
+public class EventTask extends Task {
+ public static final String MESSAGE_EVENT_CONSTRAINTS = "Start date and time must be before end date and time"
+ + "\nAll date and time should not before current time";
+
+ public EventTask(String description, String startDate, String endDate, String startTime, String endTime, String taskPriority, String taskStatus, UniqueTagList tags) throws IllegalValueException {
+ this(new Description(description),
+ EVENT_TASK,
+ new TaskDate(startDate),
+ new TaskDate(endDate),
+ new TaskTime(startTime),
+ new TaskTime(endTime),
+ new TaskPriority(taskPriority),
+ new TaskStatus(taskStatus),
+ tags);
+ }
+ /**
+ * Every field must be present and not null.
+ * @throws IllegalValueException
+ */
+ public EventTask(Description description, String taskType, TaskDate startDate, TaskDate endDate, TaskTime startTime, TaskTime endTime, TaskPriority taskPriority, TaskStatus taskStatus, UniqueTagList tags) throws IllegalValueException {
+ endDate = autoAdjustEndDate(startDate, endDate, startTime, endTime);
+
+ if (!isValidEventDuration(startDate, endDate, startTime, endTime)) {
+ throw new IllegalValueException(MESSAGE_EVENT_CONSTRAINTS);
+ }
+
+ this.description = description;
+ this.taskType = EVENT_TASK;
+ this.startDate = startDate;
+ this.endDate = endDate;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.taskPriority = taskPriority;
+ this.taskStatus = taskStatus;
+ this.tags = tags;
+ }
+
+ private boolean isValidEventDuration(TaskDate startDate, TaskDate endDate, TaskTime startTime, TaskTime endTime) {
+ TaskDate today = TaskDate.getTodayDate();
+ TaskTime currentTime = TaskTime.getTimeNow();
+
+ if (startDate.isBefore(today) || endDate.isBefore(today)) {
+ return false;
+ } else if (startDate.isAfter(endDate)) {
+ return false;
+ } if (startDate.equals(today) && startTime.isBefore(currentTime)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Adjust the endDate such that it fits into the real-world context
+ * @throws IllegalValueException
+ */
+ private TaskDate autoAdjustEndDate(TaskDate startDate, TaskDate endDate, TaskTime startTime, TaskTime endTime) throws IllegalValueException {
+ TaskDate today = TaskDate.getTodayDate();
+ if (startDate.equals(endDate) && startTime.isAfter(endTime)) {
+ endDate = endDate.getNextDay();
+ } else if (startDate.getDayNameInWeek().equals(today.getDayNameInWeek())
+ && !endDate.getDayNameInWeek().equals(today.getDayNameInWeek())) {
+ endDate = endDate.getNextWeek();
+ }
+ return endDate;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof ReadOnlyTask // instanceof handles nulls
+ && this.isSameStateAs((ReadOnlyTask) other));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/model/task/FloatingTask.java b/src/main/java/seedu/taskell/model/task/FloatingTask.java
new file mode 100644
index 000000000000..dfc7dff5426a
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/FloatingTask.java
@@ -0,0 +1,40 @@
+package seedu.taskell.model.task;
+
+import java.util.Objects;
+
+import seedu.taskell.model.task.Description;
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.commons.util.CollectionUtil;
+import seedu.taskell.model.tag.UniqueTagList;
+
+//@@author A0139257X
+/**
+ * Represents a Floating Task in the task manager.
+ * Guarantees: details are present and not null, field values are validated.
+ */
+public class FloatingTask extends Task {
+
+ public FloatingTask(String description, String taskPriority, String taskStatus, UniqueTagList tags) throws IllegalValueException {
+ this(new Description(description),
+ FLOATING_TASK,
+ new TaskDate(TaskDate.DEFAULT_DATE),
+ new TaskDate(TaskDate.DEFAULT_DATE),
+ new TaskTime(TaskTime.DEFAULT_START_TIME),
+ new TaskTime(TaskTime.DEFAULT_END_TIME),
+ new TaskPriority(taskPriority),
+ new TaskStatus(taskStatus),
+ tags);
+ }
+
+ public FloatingTask(Description description, String taskType, TaskDate startDate, TaskDate endDate, TaskTime startTime, TaskTime endTime, TaskPriority taskPriority, TaskStatus taskStatus, UniqueTagList tags) {
+ super(description, taskType, startDate, endDate, startTime, endTime, taskPriority, taskStatus, tags);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof ReadOnlyTask // instanceof handles nulls
+ && this.isSameStateAs((ReadOnlyTask) other));
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/model/task/ReadOnlyTask.java b/src/main/java/seedu/taskell/model/task/ReadOnlyTask.java
new file mode 100644
index 000000000000..ecfce173fd88
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/ReadOnlyTask.java
@@ -0,0 +1,117 @@
+package seedu.taskell.model.task;
+
+import seedu.taskell.model.tag.UniqueTagList;
+
+/**
+ * A read-only immutable interface for a Task in the taskmanager.
+ * Implementations should guarantee: details are present and not null, field values are validated.
+ */
+public interface ReadOnlyTask {
+ Description getDescription();
+ String getTaskType();
+ TaskDate getStartDate();
+ TaskDate getEndDate();
+ TaskTime getStartTime();
+ TaskTime getEndTime();
+ TaskPriority getTaskPriority();
+ TaskStatus getTaskStatus();
+
+ /**
+ * The returned TagList is a deep copy of the internal TagList,
+ * changes on the returned list will not affect the task's internal tags.
+ */
+ UniqueTagList getTags();
+
+ /**
+ * Returns true if both have the same state. (interfaces cannot override .equals)
+ */
+ default boolean isSameStateAs(ReadOnlyTask other) {
+ return other == this // short circuit if same object
+ || (other != null // this is first to avoid NPE below
+ && other.getDescription().equals(this.getDescription()) // state checks here onwards
+ && other.getTaskType().equals(this.getTaskType())
+ && other.getStartDate().equals(this.getStartDate())
+ && other.getEndDate().equals(this.getEndDate())
+ && other.getStartTime().equals(this.getStartTime())
+ && other.getEndTime().equals(this.getEndTime())
+ && other.getTaskPriority().equals(this.getTaskPriority())
+ && other.getTaskStatus().equals(this.getTaskStatus()));
+ }
+
+ /**
+ * Formats the task as text, showing all contact details.
+ */
+ default String getAsText() {
+ if (getTaskType().equals(Task.FLOATING_TASK)) {
+ return getAsTextFloatingTask();
+ } else {
+ return getAsTextEventTask();
+ }
+ }
+
+ /**
+ * Formats the floating task as text, showing all contact details.
+ */
+ default String getAsTextFloatingTask() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(getDescription())
+ .append(" TaskPriority: ")
+ .append(getTaskPriority())
+ .append(" Tags: ");
+ getTags().forEach(builder::append);
+ return builder.toString();
+ }
+
+ /**
+ * Formats the event task as text, showing all contact details.
+ */
+ default String getAsTextEventTask() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(getDescription())
+ .append(" StartDate: ")
+ .append(getStartDate())
+ .append(" EndDate: ")
+ .append(getEndDate())
+ .append(" StartTime: ")
+ .append(getStartTime())
+ .append(" EndTime: ")
+ .append(getEndTime())
+ .append(" TaskPriority: ")
+ .append(getTaskPriority())
+ .append(" TaskComplete: ")
+ .append(getTaskStatus())
+ .append(" Tags: ");
+ getTags().forEach(builder::append);
+ return builder.toString();
+ }
+
+ /**
+ * Returns a string representation of this Task's tags
+ */
+ default String tagsString() {
+ final StringBuffer buffer = new StringBuffer();
+ final String separator = " ";
+ getTags().forEach(tag -> buffer.append(tag).append(separator));
+ if (buffer.length() == 0) {
+ return "";
+ } else {
+ return buffer.substring(0, buffer.length() - separator.length());
+ }
+ }
+
+ /**
+ * @return a simple string representation of this Task's tags
+ * with each tag separated by a whitespace
+ */
+ default String tagsSimpleString() {
+ final StringBuffer buffer = new StringBuffer();
+ final String separator = " ";
+ getTags().forEach(tag -> buffer.append(tag.toSimpleString()).append(separator));
+ if (buffer.length() == 0) {
+ return "";
+ } else {
+ return buffer.substring(0, buffer.length() - separator.length());
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/model/task/Task.java b/src/main/java/seedu/taskell/model/task/Task.java
new file mode 100644
index 000000000000..f52a4c42fc4e
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/Task.java
@@ -0,0 +1,129 @@
+package seedu.taskell.model.task;
+
+import java.util.Objects;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.commons.util.CollectionUtil;
+import seedu.taskell.model.tag.UniqueTagList;
+
+/**
+ * Represents a Task in the task manager.
+ * Guarantees: details are present and not null, field values are validated.
+ */
+public class Task implements ReadOnlyTask {
+ public static final String FLOATING_TASK = "FLOATING";
+ public static final String EVENT_TASK = "EVENT";
+
+ protected Description description;
+ protected String taskType;
+ protected TaskDate startDate;
+ protected TaskDate endDate;
+ protected TaskTime startTime;
+ protected TaskTime endTime;
+ protected TaskPriority taskPriority;
+ protected TaskStatus taskStatus;
+
+ protected UniqueTagList tags;
+
+ public Task() {
+ //Not applicable
+ }
+
+ /**
+ * Every field must be present and not null.
+ */
+ public Task(Description description, String taskType, TaskDate startDate, TaskDate endDate, TaskTime startTime, TaskTime endTime, TaskPriority taskPriority, TaskStatus taskStatus, UniqueTagList tags) {
+ assert !CollectionUtil.isAnyNull(description, taskType, startDate, startTime, endTime, taskPriority, taskStatus, tags);
+ this.description = description;
+ this.taskType = taskType;
+ this.startDate = startDate;
+ this.endDate = endDate;
+ this.endDate = endDate;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.taskPriority = taskPriority;
+ this.taskStatus = taskStatus;
+ this.tags = new UniqueTagList(tags); // protect internal tags from changes in the arg list
+ }
+
+ public Task(String description) throws IllegalValueException{
+ this.description = new Description(description);
+ }
+ /**
+ * Copy constructor.
+ */
+ public Task(ReadOnlyTask source) {
+ this(source.getDescription(), source.getTaskType(), source.getStartDate(), source.getEndDate(), source.getStartTime(), source.getEndTime(), source.getTaskPriority(), source.getTaskStatus(), source.getTags());
+ }
+
+ @Override
+ public Description getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getTaskType() {
+ return taskType;
+ }
+
+ @Override
+ public TaskDate getStartDate() {
+ return startDate;
+ }
+
+ @Override
+ public TaskDate getEndDate() {
+ return endDate;
+ }
+
+ @Override
+ public TaskTime getStartTime() {
+ return startTime;
+ }
+
+ @Override
+ public TaskTime getEndTime() {
+ return endTime;
+ }
+
+ @Override
+ public TaskPriority getTaskPriority() {
+ return taskPriority;
+ }
+
+ @Override
+ public TaskStatus getTaskStatus() {
+ return taskStatus;
+ }
+
+ @Override
+ public UniqueTagList getTags() {
+ return new UniqueTagList(tags);
+ }
+
+ /**
+ * Replaces this task's tags with the tags in the argument tag list.
+ */
+ public void setTags(UniqueTagList replacement) {
+ tags.setTags(replacement);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof ReadOnlyTask // instanceof handles nulls
+ && this.isSameStateAs((ReadOnlyTask) other));
+ }
+
+ @Override
+ public int hashCode() {
+ // use this method for custom fields hashing instead of implementing your own
+ return Objects.hash(description, startDate, startTime, endTime, taskPriority, taskStatus, tags);
+ }
+
+ @Override
+ public String toString() {
+ return getAsText();
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/model/task/TaskDate.java b/src/main/java/seedu/taskell/model/task/TaskDate.java
new file mode 100644
index 000000000000..25a962ee936e
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/TaskDate.java
@@ -0,0 +1,615 @@
+package seedu.taskell.model.task;
+
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+
+import java.util.Locale;
+import java.util.Date;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.DateTimeException;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.TextStyle;
+
+//@@author A0139257X
+/**
+ * Represents a Task's taskDate in the task manager.
+ * Guarantees: is valid as declared in {@link #isValidDate(String)}
+ */
+public class TaskDate {
+ public static final int JANUARY = 1;
+ public static final int FEBRUARY = 2;
+ public static final int MARCH = 3;
+ public static final int APRIL = 4;
+ public static final int MAY = 5;
+ public static final int JUNE = 6;
+ public static final int JULY = 7;
+ public static final int AUGUST = 8;
+ public static final int SEPTEMBER = 9;
+ public static final int OCTOBER = 10;
+ public static final int NOVEMBER = 11;
+ public static final int DECEMBER = 12;
+
+ public static final int MONDAY = 1;
+ public static final int TUESDAY = 2;
+ public static final int WEDNESDAY = 3;
+ public static final int THURSDAY = 4;
+ public static final int FRIDAY = 5;
+ public static final int SATURDAY = 6;
+ public static final int SUNDAY = 7;
+
+ public static final int NUM_DAYS_IN_A_WEEK = 7;
+ public static final int NUM_MONTHS_IN_A_YEAR = 12;
+
+ public static final int NOT_A_VALID_MONTH = 0;
+ public static final int NOT_A_VALID_DAY_OF_THE_WEEK = 0;
+
+ public static final int FIRST_DAY_OF_THE_MONTH = 1;
+
+ public static final String DATE_DELIMITER = " .-/";
+
+ public static final String DEFAULT_DATE = getDefaultDate();
+
+ public static final Pattern TASK_DATE_ARGS_FORMAT = Pattern
+ .compile("(?(3[0-1]|2[0-9]|1[0-9]|[1-9]))" + "(-)(?(1[0-2]|[1-9]))" + "(-)(?([0-9]{4}))");
+ private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEEE, d MMMM yyyy");
+ private static final DateTimeFormatter standardFormat = DateTimeFormatter.ofPattern("d-MM-yyyy");
+ SimpleDateFormat sdf = new SimpleDateFormat("d M yyyy");
+
+ public static final String MESSAGE_TASK_DATE_CONSTRAINTS =
+ "Task dates should be separated by '-' or '.' or '/'"
+ + "\nSpelling of month should be in full or 3-letters"
+ + "\nYear should only be 4-digits";
+
+ public String taskDate;
+
+ /**
+ * Initialize the different fields given taskDate in the format of
+ * DAY-MONTH-YEAR, separated by DATE_DELIMITER
+ * @throws IllegalValueException
+ */
+ public TaskDate(String dateToAdd) throws IllegalValueException {
+ if (isValidFullDate(dateToAdd)) {
+ setDateGivenFullDate(dateToAdd);
+ } else if (isValidDayAndMonth(dateToAdd)) {
+ setDateGivenDayMonth(dateToAdd);
+ } else if (isValidMonthAndYear(dateToAdd)) {
+ setDateGivenMonthYear(dateToAdd);
+ } else if (isValidMonth(dateToAdd)) {
+ setDateGivenMonth(dateToAdd);
+ } else if (isValidDayOfWeek(dateToAdd)) {
+ setDateGivenDayNameOfWeek(dateToAdd);
+ } else if (isValidToday(dateToAdd)) {
+ setDateGivenToday(dateToAdd);
+ } else if (isValidTomorrow(dateToAdd)) {
+ setDateGivenTomorrow(dateToAdd);
+ } else {
+ throw new IllegalValueException(MESSAGE_TASK_DATE_CONSTRAINTS);
+ }
+ }
+
+ /**
+ * Extract the different fields from taskDate having the format of
+ * DAY-MONTH-YEAR, separated by DATE_DELIMITER
+ * @throws DateTimeException
+ * @throws IllegalValueException
+ */
+ private void setDateGivenFullDate(String dateToConvert) throws DateTimeException, IllegalValueException {
+ StringTokenizer st = new StringTokenizer(dateToConvert, DATE_DELIMITER);
+ String[] tokenArr = new String[3];
+ int i = 0;
+ while (st.hasMoreTokens()) {
+ tokenArr[i] = st.nextToken();
+ i++;
+ }
+
+ int day = Integer.valueOf(tokenArr[0]);
+ String monthStr = tokenArr[1];
+ int month;
+ try {
+ month = Integer.valueOf(tokenArr[1]);
+ } catch (NumberFormatException nfe) {
+ month = convertMonthIntoInteger(monthStr);
+ }
+ int year = Integer.valueOf(tokenArr[2]);
+
+ try {
+ setDate(day, month, year);
+ getYear();
+ } catch (IllegalValueException ive) {
+ throw ive;
+ }
+ }
+
+ private void setDateGivenDayMonth(String dateToConvert) throws IllegalValueException {
+ StringTokenizer st = new StringTokenizer(dateToConvert, DATE_DELIMITER);
+ String[] tokenArr = new String[3];
+ int i = 0;
+ while (st.hasMoreTokens()) {
+ tokenArr[i] = st.nextToken();
+ i++;
+ }
+
+ int day = Integer.valueOf(tokenArr[0]);
+ String monthStr = tokenArr[1];
+ int month;
+ try {
+ month = Integer.valueOf(tokenArr[1]);
+ } catch (NumberFormatException nfe) {
+ month = convertMonthIntoInteger(monthStr);
+ }
+ int year = Integer.valueOf(getThisYear());
+
+ try {
+ setDate(day, month, year);
+ getYear();
+ } catch (IllegalValueException ive) {
+ throw ive;
+ }
+ }
+
+ private void setDateGivenMonthYear(String dateToConvert) throws IllegalValueException {
+ StringTokenizer st = new StringTokenizer(dateToConvert, DATE_DELIMITER);
+ String[] tokenArr = new String[3];
+ int i = 0;
+ while (st.hasMoreTokens()) {
+ tokenArr[i] = st.nextToken();
+ i++;
+ }
+
+ int day = FIRST_DAY_OF_THE_MONTH;
+ String monthStr = tokenArr[0];
+ int month;
+ try {
+ month = Integer.valueOf(tokenArr[0]);
+ } catch (NumberFormatException nfe) {
+ month = convertMonthIntoInteger(monthStr);
+ }
+ int year = Integer.valueOf(tokenArr[1]);
+
+ try {
+ setDate(day, month, year);
+ getYear();
+ } catch (IllegalValueException ive) {
+ throw ive;
+ }
+ }
+
+ private void setDateGivenMonth(String monthToConvert) {
+ int day = FIRST_DAY_OF_THE_MONTH;
+ int month = convertMonthIntoInteger(monthToConvert);
+ int year = Integer.valueOf(getThisYear());
+
+ try {
+ setDate(day, month, year);
+ } catch (DateTimeException dte) {
+ throw dte;
+ }
+ }
+
+ private void setDateGivenDayNameOfWeek(String dayName) {
+ int day = convertDayOfWeekIntoInteger(dayName);
+ LocalDate today = LocalDate.now();
+ String todayDayNameInWeek = today.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.US);
+ int todayDayInWeek = convertDayOfWeekIntoInteger(todayDayNameInWeek);
+ int daysToAdd = day - todayDayInWeek;
+ if (daysToAdd <= 0) {
+ daysToAdd += NUM_DAYS_IN_A_WEEK;
+ }
+ LocalDate finalDate = today.plusDays(daysToAdd);
+ setDate(finalDate.getDayOfMonth(), finalDate.getMonthValue(), finalDate.getYear());
+ }
+
+ private void setDateGivenToday(String taskDate) {
+ LocalDate today = LocalDate.now();
+ setDate(today.getDayOfMonth(), today.getMonthValue(), today.getYear());
+ }
+
+ private void setDateGivenTomorrow(String taskDate) {
+ LocalDate today = LocalDate.now();
+ LocalDate tomorrow = today.plusDays(1);
+ setDate(tomorrow.getDayOfMonth(), tomorrow.getMonthValue(), tomorrow.getYear());
+ }
+
+ /**
+ * Extract the different fields of a given valid taskDate
+ * @throws DateTimeException
+ */
+ public void setDate(int day, int month, int year) {
+ this.taskDate = convertToStandardFormat(day, month, year);
+ }
+
+ /**
+ * Convert this TaskDate to the format of
+ * DAY_MONTH-YEAR
+ */
+ public static String convertToStandardFormat(int day, int month, int year) {
+ return day + "-" + month + "-" + year;
+ }
+
+ /**
+ * Returns true if a given string is a valid task taskDate.
+ */
+ public static boolean isValidDate(String dateToValidate) {
+ if (dateToValidate == null || dateToValidate.isEmpty()) {
+ return false;
+ }
+
+ return isValidFullDate(dateToValidate) || isValidMonthAndYear(dateToValidate)
+ || isValidDayAndMonth(dateToValidate) || isValidMonth(dateToValidate) || isValidToday(dateToValidate)
+ || isValidTomorrow(dateToValidate) || isValidDayOfWeek(dateToValidate);
+ }
+
+ public static boolean isValidDayOfWeek(String dateToValidate) {
+ if (convertDayOfWeekIntoInteger(dateToValidate) == NOT_A_VALID_DAY_OF_THE_WEEK) {
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean isValidMonthAndYear(String dateToValidate) {
+ if (isValidFormat(dateToValidate, "MMM yyyy") || isValidFormat(dateToValidate, "MMM-yyyy")
+ || isValidFormat(dateToValidate, "MMM.yyyy")
+ || isValidFormat(dateToValidate, "MMM/yyyy")) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isValidDayAndMonth(String dateToValidate) {
+ if (isValidFormat(dateToValidate, "d MMM") || isValidFormat(dateToValidate, "d-MMM")
+ || isValidFormat(dateToValidate, "d.MMM")
+ || isValidFormat(dateToValidate, "d/MMM")) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isValidFullDate(String dateToValidate) {
+ if (isValidFormat(dateToValidate, "d M yyyy") || isValidFormat(dateToValidate, "d MMM yyyy")
+ || isValidFormat(dateToValidate, "d-M-yyyy") || isValidFormat(dateToValidate, "d-MMM-yyyy")
+ || isValidFormat(dateToValidate, "d.M.yyyy") || isValidFormat(dateToValidate, "d.MMM.yyyy")
+ || isValidFormat(dateToValidate, "d.M-yyyy") || isValidFormat(dateToValidate, "d.MMM-yyyy")
+ || isValidFormat(dateToValidate, "d-M.yyyy") || isValidFormat(dateToValidate, "d-MMM.yyyy")
+ || isValidFormat(dateToValidate, "d/M/yyyy") || isValidFormat(dateToValidate, "d/MMM/yyyy")
+ || isValidFormat(dateToValidate, "d-M/yyyy") || isValidFormat(dateToValidate, "d-MMM/yyyy")
+ || isValidFormat(dateToValidate, "d/M-yyyy") || isValidFormat(dateToValidate, "d/MMM-yyyy")
+ || isValidFormat(dateToValidate, "d.M/yyyy") || isValidFormat(dateToValidate, "d.MMM/yyyy")
+ || isValidFormat(dateToValidate, "d/M.yyyy") || isValidFormat(dateToValidate, "d/MMM.yyyy")) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if a given string has a valid format supported by SimpleDateFormat.
+ */
+ public static boolean isValidFormat(String dateToValidate, String acceptedFormat) {
+ if (dateToValidate == null) {
+ return false;
+ }
+
+ SimpleDateFormat sdf = new SimpleDateFormat(acceptedFormat);
+ sdf.setLenient(false);
+
+ try {
+ // if not valid, it will throw ParseException
+ Date taskDate = sdf.parse(dateToValidate);
+ } catch (ParseException e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static boolean isValidToday(String dateToValidate) {
+ assert (dateToValidate != null);
+ dateToValidate = dateToValidate.toLowerCase();
+
+ switch (dateToValidate) {
+ case "today":
+ // Fallthrough
+ case "tdy":
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static boolean isValidTomorrow(String dateToValidate) {
+ assert (dateToValidate != null);
+ dateToValidate = dateToValidate.toLowerCase();
+
+ switch (dateToValidate) {
+ case "tomorrow":
+ // Fallthrough
+ case "tmr":
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static boolean isValidMonth(String month) {
+ if (convertMonthIntoInteger(month) == NOT_A_VALID_MONTH) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Returns an integer representing the day in a week
+ */
+ private static int convertDayOfWeekIntoInteger(String day) {
+ assert (day != null);
+ day = day.toLowerCase();
+
+ switch (day) {
+ case "mon":
+ // Fallthrough
+ case "monday":
+ return MONDAY;
+ case "tue":
+ // Fallthrough
+ case "tues":
+ // Fallthrough
+ case "tuesday":
+ return TUESDAY;
+ case "wed":
+ // Fallthrough
+ case "wednesday":
+ return WEDNESDAY;
+ case "thu":
+ // Fallthrough
+ case "thur":
+ // Fallthrough
+ case "thurs":
+ // Fallthrough
+ case "thursday":
+ return THURSDAY;
+ case "fri":
+ // Fallthrough
+ case "friday":
+ return FRIDAY;
+ case "sat":
+ // Fallthrough
+ case "saturday":
+ return SATURDAY;
+ case "sun":
+ // Fallthrough
+ case "sunday":
+ return SUNDAY;
+ default:
+ return NOT_A_VALID_DAY_OF_THE_WEEK;
+ }
+ }
+
+ /**
+ * Returns an integer representing the month of a year.
+ */
+ private static int convertMonthIntoInteger(String month) {
+ assert (month!= null);
+ if (Character.isLetter(month.charAt(0))) {
+ month = month.toLowerCase();
+ }
+
+ switch (month) {
+ case "jan":
+ // Fallthrough
+ case "january":
+ return JANUARY;
+ case "feb":
+ // Fallthrough
+ case "february":
+ return FEBRUARY;
+ case "mar":
+ // Fallthrough
+ case "march":
+ return MARCH;
+ case "apr":
+ // Fallthrough
+ case "april":
+ return APRIL;
+ case "may":
+ return MAY;
+ case "jun":
+ // Fallthrough
+ case "june":
+ return JUNE;
+ case "jul":
+ // Fallthrough
+ case "july":
+ return JULY;
+ case "aug":
+ // Fallthrough
+ case "august":
+ return AUGUST;
+ case "sep":
+ // Fallthrough
+ case "sept":
+ // Fallthrough
+ case "september":
+ return SEPTEMBER;
+ case "oct":
+ // Fallthrough
+ case "october":
+ return OCTOBER;
+ case "nov":
+ // Fallthrough
+ case "november":
+ return NOVEMBER;
+ case "dec":
+ // Fallthrough
+ case "december":
+ return DECEMBER;
+ default:
+ return NOT_A_VALID_MONTH;
+ }
+ }
+
+ /**
+ * Get today's taskDate in the format of
+ * DAY-MONTH-YEAR
+ */
+ public static TaskDate getTodayDate() {
+ try {
+ return new TaskDate(LocalDate.now().format(standardFormat));
+ } catch (IllegalValueException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Get tomorrow's taskDate in the format of
+ * DAY-MONTH-YEAR
+ */
+ public static TaskDate getTomorrowDate() {
+ try {
+ return new TaskDate(LocalDate.now().plusDays(1).format(standardFormat));
+ } catch (IllegalValueException e) {
+ return null;
+ }
+ }
+
+ public TaskDate getNextDay() throws IllegalValueException {
+ try {
+ LocalDate localDate = LocalDate.of(Integer.valueOf(getYear()), Integer.valueOf(getMonth()), Integer.valueOf(getDay()));
+ LocalDate nextDay = localDate.plusDays(1);
+ return new TaskDate(nextDay.format(standardFormat));
+ } catch (IllegalValueException e) {
+ throw new IllegalValueException(MESSAGE_TASK_DATE_CONSTRAINTS);
+ }
+ }
+
+ public TaskDate getNextWeek() throws IllegalValueException {
+ try {
+ LocalDate localDate = LocalDate.of(Integer.valueOf(getYear()), Integer.valueOf(getMonth()), Integer.valueOf(getDay()));
+ LocalDate nextWeek = localDate.plusWeeks(1);
+ return new TaskDate(nextWeek.format(standardFormat));
+ } catch (IllegalValueException e) {
+ throw new IllegalValueException(MESSAGE_TASK_DATE_CONSTRAINTS);
+ }
+ }
+
+ /**
+ * Returns a string representing the integer value of this year
+ */
+ public static String getThisYear() {
+ return LocalDate.now().getYear() + "";
+ }
+
+ public String getDay() throws IllegalValueException {
+ assert taskDate != null;
+
+ final Matcher matcherFullArg = TASK_DATE_ARGS_FORMAT.matcher(taskDate.trim());
+ if (matcherFullArg.matches()) {
+ return matcherFullArg.group("day");
+ } else {
+ throw new IllegalValueException(MESSAGE_TASK_DATE_CONSTRAINTS);
+ }
+ }
+
+ public String getMonth() throws IllegalValueException {
+ assert taskDate != null;
+
+ final Matcher matcherFullArg = TASK_DATE_ARGS_FORMAT.matcher(taskDate.trim());
+ if (matcherFullArg.matches()) {
+ return matcherFullArg.group("month");
+ } else {
+ throw new IllegalValueException(MESSAGE_TASK_DATE_CONSTRAINTS);
+ }
+ }
+
+ public String getYear() throws IllegalValueException {
+ assert taskDate != null;
+
+ final Matcher matcherFullArg = TASK_DATE_ARGS_FORMAT.matcher(taskDate.trim());
+ if (matcherFullArg.matches()) {
+ return matcherFullArg.group("year");
+ } else {
+ throw new IllegalValueException(MESSAGE_TASK_DATE_CONSTRAINTS);
+ }
+ }
+
+ public String getDayNameInWeek() throws IllegalValueException {
+ try {
+ LocalDate localDate = LocalDate.of(Integer.valueOf(getYear()), Integer.valueOf(getMonth()), Integer.valueOf(getDay()));
+ String dayNameInWeek = localDate.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.US);
+ return dayNameInWeek;
+ } catch (IllegalValueException ive) {
+ throw ive;
+ }
+ }
+
+ public String getMonthName() throws IllegalValueException {
+ try {
+ LocalDate localDate = LocalDate.of(Integer.valueOf(getYear()), Integer.valueOf(getMonth()), Integer.valueOf(getDay()));
+ String month = localDate.getMonth().getDisplayName(TextStyle.FULL, Locale.US);
+ return month;
+ } catch (IllegalValueException ive) {
+ throw ive;
+ }
+ }
+
+ public String getDisplayDate() {
+ try {
+ return getDayNameInWeek() + ", " + getDay() + " " + getMonthName() + " " + getYear();
+ } catch (IllegalValueException e) {
+ return "";
+ }
+ }
+
+ public static String getDefaultDate() {
+ int day = LocalDate.now().getDayOfMonth();
+ int month = LocalDate.now().getMonthValue();
+ int year = LocalDate.now().getYear();
+ return convertToStandardFormat(day, month, year);
+ }
+
+ public boolean isBefore(TaskDate date) {
+ try {
+ LocalDate thisDate = LocalDate.of(Integer.valueOf(this.getYear()), Integer.valueOf(this.getMonth()), Integer.valueOf(this.getDay()));
+ LocalDate dateToComapare = LocalDate.of(Integer.valueOf(date.getYear()), Integer.valueOf(date.getMonth()), Integer.valueOf(date.getDay()));
+ return thisDate.isBefore(dateToComapare);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public boolean isAfter(TaskDate date) {
+ try {
+ LocalDate thisDate = LocalDate.of(Integer.valueOf(this.getYear()), Integer.valueOf(this.getMonth()), Integer.valueOf(this.getDay()));
+ LocalDate dateToComapare = LocalDate.of(Integer.valueOf(date.getYear()), Integer.valueOf(date.getMonth()), Integer.valueOf(date.getDay()));
+ return thisDate.isAfter(dateToComapare);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns a string with the format of
+ * DAY-MONTH-YEAR
+ */
+ @Override
+ public String toString() {
+ return taskDate;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TaskDate // instanceof handles nulls
+ && this.taskDate.equals(((TaskDate)other).taskDate));
+ }
+
+ @Override
+ public int hashCode() {
+ return taskDate.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/taskell/model/task/TaskPriority.java b/src/main/java/seedu/taskell/model/task/TaskPriority.java
new file mode 100644
index 000000000000..6dfccb7eb856
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/TaskPriority.java
@@ -0,0 +1,71 @@
+package seedu.taskell.model.task;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+
+//@@author A0139257X
+/**
+ * Represents a Task's priority in the task manager.
+ * Guarantees: immutable; is valid as declared in {@link #isValidPriority(String)}
+ */
+public class TaskPriority {
+
+ public static final String MESSAGE_TASK_PRIORITY_CONSTRAINTS = "Task priority should range from 0-3"
+ + "\nThere should not be more than 1 priority level for a task";
+ public static final String TASK_PRIORITY_VALIDATION_REGEX = ".+";
+
+ public static final String PREFIX = "p/";
+
+ public static final String NO_PRIORITY = "0";
+ public static final String LOW_PRIORITY = "1";
+ public static final String MEDIUM_PRIORITY = "2";
+ public static final String HIGH_PRIORITY = "3";
+
+ public static final String DEFAULT_PRIORITY = NO_PRIORITY;
+
+ public static final String LOW_PRIORITY_BACKGROUND = "-fx-background-color:#4ca64c";
+ public static final String MEDIUM_PRIORITY_BACKGROUND = "-fx-background-color:#ffff4c";
+ public static final String HIGH_PRIORITY_BACKGROUND = "-fx-background-color:#ff4c4c";
+
+ public final String taskPriority;
+
+ /**
+ * Validates given priority.
+ *
+ * @throws IllegalValueException if given priority string is invalid.
+ */
+ public TaskPriority(String priority) throws IllegalValueException {
+ assert priority != null;
+ if (!isValidPriority(priority)) {
+ throw new IllegalValueException(MESSAGE_TASK_PRIORITY_CONSTRAINTS);
+ }
+ this.taskPriority = priority;
+ }
+
+ /**
+ * Returns true if a given string is a valid task taskTime.
+ */
+ public static boolean isValidPriority(String priority) {
+ return priority.equals(NO_PRIORITY)
+ || priority.equals(LOW_PRIORITY)
+ || priority.equals(MEDIUM_PRIORITY)
+ || priority.equals(HIGH_PRIORITY);
+ }
+
+ @Override
+ public String toString() {
+ return taskPriority;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TaskPriority // instanceof handles nulls
+ && this.taskPriority.equals(((TaskPriority) other).taskPriority)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return taskPriority.hashCode();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/seedu/taskell/model/task/TaskStatus.java b/src/main/java/seedu/taskell/model/task/TaskStatus.java
new file mode 100644
index 000000000000..f0110fc2b31b
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/TaskStatus.java
@@ -0,0 +1,39 @@
+//@@author A0148004R
+package seedu.taskell.model.task;
+
+import java.util.Objects;
+
+public class TaskStatus {
+ public static final String FINISHED = "finished";
+ public static final String INCOMPLETE = "incomplete";
+ public final String taskStatus;
+
+ public TaskStatus(String taskStatus) {
+ this.taskStatus = taskStatus;
+ }
+
+ public String taskStatus() {
+ return taskStatus;
+ }
+
+ public static boolean isValidTaskComplete(String taskToValidate) {
+ return taskToValidate.equals(FINISHED) || taskToValidate.equals(INCOMPLETE);
+ }
+
+ @Override
+ public String toString() {
+ return taskStatus;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TaskStatus // instanceof handles nulls
+ && this.taskStatus.equals(((TaskStatus)other).taskStatus)); // state check
+ }
+ @Override
+ public int hashCode() {
+ return taskStatus.hashCode();
+ }
+}
+//@@author
diff --git a/src/main/java/seedu/taskell/model/task/TaskTime.java b/src/main/java/seedu/taskell/model/task/TaskTime.java
new file mode 100644
index 000000000000..f06ac8327047
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/TaskTime.java
@@ -0,0 +1,245 @@
+package seedu.taskell.model.task;
+
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+
+//@@author A0139257X
+/**
+ * Represents a Task's taskTime in the task manager.
+ */
+public class TaskTime {
+
+ public static final String ZERO_MINUTE = "00";
+ public static final String NOON = "12:00PM";
+ public static final String MIDNIGHT = "12:00AM";
+
+ public static final String AM = "AM";
+ public static final String PM = "PM";
+
+ public static final int TIME_OFFSET = 12;
+
+ public static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("h:mma");
+
+ public static final String DEFAULT_START_TIME = MIDNIGHT;
+ public static final String DEFAULT_END_TIME = "11:59PM";
+
+ public static final Pattern TASK_TIME_ARGS_FORMAT = Pattern
+ .compile("(?(1[0-2]|[1-9]))" + "(.|-|:)(?([0-5][0-9]))" + "(?(am|pm|AM|PM|Am|Pm|aM|pM))");
+ public static final Pattern TASK_TIME_HOUR_ONLY_FORMAT = Pattern
+ .compile("(?(1[0-2]|[1-9]))" + "(?(am|pm|AM|PM|Am|Pm|aM|pM))");
+ final static String FULL_TIME_REGEX = "^(1[0-2]|[1-9])(.|-|:)([0-5][0-9])(am|pm|AM|PM|Am|Pm|aM|pM)$";
+ final static String HOUR_ONLY_TIME_REGEX = "^(1[0-2]|[1-9])(am|pm|AM|PM|Am|Pm|aM|pM)$";
+
+ public static final String MESSAGE_TASK_TIME_CONSTRAINTS =
+ "Time should be in 12hour clock format."
+ + "\nHour and Minute are separated by '.' or ':'"
+ + "\nEg. 9.30am or 12:50pm";
+
+ public String taskTime; //Standard format
+
+ public TaskTime(String time) throws IllegalValueException {
+ if (isValidTime(time)) {
+ setTime(time);
+ } else {
+ throw new IllegalValueException(MESSAGE_TASK_TIME_CONSTRAINTS);
+ }
+ }
+
+ public static boolean isValidTime(String time) {
+ assert time != null;
+ if (time.isEmpty()) {
+ return false;
+ }
+
+ if (time.matches(HOUR_ONLY_TIME_REGEX) || time.matches(FULL_TIME_REGEX)) {
+ return true;
+ } else if (isValidNow(time)) {
+ return true;
+ } else if (isValidNoon(time)) {
+ return true;
+ } else if (isValidMidnight(time)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private static boolean isValidNow(String time) {
+ time = time.toLowerCase();
+ switch (time) {
+ case "now":
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static boolean isValidNoon(String time) {
+ time = time.toLowerCase();
+ switch (time) {
+ case "afternoon":
+ //Fallthrough
+ case "noon":
+ //Fallthrough
+ case "12noon":
+ //Fallthrough
+ case "12-noon":
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static boolean isValidMidnight(String time) {
+ time = time.toLowerCase();
+ switch (time) {
+ case "midnight":
+ //Fallthrough
+ case "mid-night":
+ //Fallthrough
+ case "12midnight":
+ //Fallthrough
+ case "12-midnight":
+ //Fallthrough
+ case "12mid-night":
+ //Fallthrough
+ case "12-mid-night":
+ //Fallthrough
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Checks if this time is before the specified time
+ */
+ public boolean isBefore(TaskTime time) {
+ int timeHour = Integer.valueOf(time.getHour());
+ if (time.getAntePost().equals(PM) && (timeHour != TIME_OFFSET)) {
+ timeHour += TIME_OFFSET;
+ } else if (time.getAntePost().equals(AM) && (timeHour == TIME_OFFSET)) {
+ timeHour -= TIME_OFFSET;
+ }
+ LocalTime timeToCompare = LocalTime.of(timeHour, Integer.valueOf(time.getMinute()));
+
+ //TaskTime thisTimeTaskTime = new TaskTime(this.taskTime);
+ int thisTimeHour = Integer.valueOf(this.getHour());
+ if (this.getAntePost().equals(PM) && (thisTimeHour != TIME_OFFSET)) {
+ thisTimeHour += TIME_OFFSET;
+ } else if (this.getAntePost().equals(AM) && (thisTimeHour == TIME_OFFSET)) {
+ thisTimeHour -= TIME_OFFSET;
+ }
+ LocalTime thisTimeLocalTime = LocalTime.of(thisTimeHour, Integer.valueOf(this.getMinute()));
+ return thisTimeLocalTime.isBefore(timeToCompare);
+ }
+
+ /**
+ * Checks if this time is after the specified time
+ */
+ public boolean isAfter(TaskTime time) {
+ int timeHour = Integer.valueOf(time.getHour());
+ if (time.getAntePost().equals(PM) && (timeHour != TIME_OFFSET)) {
+ timeHour += TIME_OFFSET;
+ } else if (time.getAntePost().equals(AM) && (timeHour == TIME_OFFSET)) {
+ timeHour -= TIME_OFFSET;
+ }
+ LocalTime timeToCompare = LocalTime.of(timeHour, Integer.valueOf(time.getMinute()));
+
+ //TaskTime thisTimeTaskTime = new TaskTime(this.taskTime);
+ int thisTimeHour = Integer.valueOf(this.getHour());
+ if (this.getAntePost().equals(PM) && (thisTimeHour != TIME_OFFSET)) {
+ thisTimeHour += TIME_OFFSET;
+ } else if (this.getAntePost().equals(AM) && (thisTimeHour == TIME_OFFSET)) {
+ thisTimeHour -= TIME_OFFSET;
+ }
+ LocalTime thisTimeLocalTime = LocalTime.of(thisTimeHour, Integer.valueOf(this.getMinute()));
+ return thisTimeLocalTime.isAfter(timeToCompare);
+ }
+
+ public void setTime(String time) throws IllegalValueException {
+ final Matcher matcherFullArg = TASK_TIME_ARGS_FORMAT.matcher(time.trim());
+ final Matcher matcherHourOnly = TASK_TIME_HOUR_ONLY_FORMAT.matcher(time.trim());
+ if (matcherFullArg.matches()) {
+ this.taskTime = setTime(matcherFullArg.group("hour"), matcherFullArg.group("minute"), matcherFullArg.group("antePost"));
+ } else if (matcherHourOnly.matches()) {
+ this.taskTime = setTime(matcherHourOnly.group("hour"), ZERO_MINUTE, matcherHourOnly.group("antePost"));
+ } else if (isValidNow(time)) {
+ this.taskTime = getTimeNow().toString();
+ } else if (isValidNoon(time)) {
+ this.taskTime = NOON;
+ } else if (isValidMidnight(time)) {
+ this.taskTime = MIDNIGHT;
+ } else {
+ throw new IllegalValueException(MESSAGE_TASK_TIME_CONSTRAINTS);
+ }
+ }
+
+ public String setTime(String hour, String minute, String antePost) {
+ this.taskTime = hour + ":" + minute + antePost.toUpperCase();
+ return taskTime;
+ }
+
+ public static TaskTime getTimeNow() {
+ LocalTime currTime = LocalTime.now();
+ try {
+ return new TaskTime(LocalTime.of(currTime.getHour(), currTime.getMinute()).format(dtf));
+ } catch (IllegalValueException e) {
+ return null;
+ }
+ }
+
+ public String getHour() {
+ assert taskTime != null;
+
+ final Matcher matcherFullArg = TASK_TIME_ARGS_FORMAT.matcher(taskTime.trim());
+ if (matcherFullArg.matches()) {
+ return matcherFullArg.group("hour");
+ }
+
+ return "";
+ }
+
+ public String getMinute() {
+ assert taskTime != null;
+
+ final Matcher matcherFullArg = TASK_TIME_ARGS_FORMAT.matcher(taskTime.trim());
+ if (matcherFullArg.matches()) {
+ return matcherFullArg.group("minute");
+ }
+
+ return "";
+ }
+
+ public String getAntePost() {
+ assert taskTime != null;
+
+ final Matcher matcherFullArg = TASK_TIME_ARGS_FORMAT.matcher(taskTime.trim());
+ if (matcherFullArg.matches()) {
+ return matcherFullArg.group("antePost");
+ }
+
+ return "";
+ }
+
+ @Override
+ public String toString() {
+ return taskTime;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TaskTime // instanceof handles nulls
+ && this.taskTime.equals(((TaskTime) other).taskTime)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return (taskTime).hashCode();
+ }
+}
diff --git a/src/main/java/seedu/taskell/model/task/UniqueTaskList.java b/src/main/java/seedu/taskell/model/task/UniqueTaskList.java
new file mode 100644
index 000000000000..5d4290cc8710
--- /dev/null
+++ b/src/main/java/seedu/taskell/model/task/UniqueTaskList.java
@@ -0,0 +1,113 @@
+package seedu.taskell.model.task;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.taskell.commons.exceptions.DuplicateDataException;
+import seedu.taskell.commons.util.CollectionUtil;
+
+import java.util.*;
+
+/**
+ * A list of tasks that enforces uniqueness between its elements and does not allow nulls.
+ *
+ * Supports a minimal set of list operations.
+ *
+ * @see Task#equals(Object)
+ * @see CollectionUtil#elementsAreUnique(Collection)
+ */
+public class UniqueTaskList implements Iterable {
+
+ /**
+ * Signals that an operation would have violated the 'no duplicates' property of the list.
+ */
+ public static class DuplicateTaskException extends DuplicateDataException {
+ protected DuplicateTaskException() {
+ super("Operation would result in duplicate tasks");
+ }
+ }
+
+ /**
+ * Signals that an operation targeting a specified task in the list would fail because
+ * there is no such matching task in the list.
+ */
+ public static class TaskNotFoundException extends Exception {}
+
+ private final ObservableList internalList = FXCollections.observableArrayList();
+
+ /**
+ * Constructs empty TaskList.
+ */
+ public UniqueTaskList() {}
+
+ /**
+ * Returns true if the list contains an equivalent task as the given argument.
+ */
+ public boolean contains(ReadOnlyTask toCheck) {
+ assert toCheck != null;
+ return internalList.contains(toCheck);
+ }
+
+ /**
+ * Adds a task to the list.
+ *
+ * @throws DuplicateTaskException if the task to add is a duplicate of an existing task in the list.
+ */
+ public void add(Task toAdd) throws DuplicateTaskException {
+ assert toAdd != null;
+ if (contains(toAdd)) {
+ throw new DuplicateTaskException();
+ }
+ internalList.add(toAdd);
+ }
+
+ /**
+ * Removes the equivalent task from the list.
+ *
+ * @throws TaskNotFoundException if no such task could be found in the list.
+ */
+ public boolean remove(ReadOnlyTask toRemove) throws TaskNotFoundException {
+ assert toRemove != null;
+ final boolean taskFoundAndDeleted = internalList.remove(toRemove);
+ if (!taskFoundAndDeleted) {
+ throw new TaskNotFoundException();
+ }
+ return taskFoundAndDeleted;
+ }
+
+ public ObservableList getInternalList() {
+ return internalList;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return internalList.iterator();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof UniqueTaskList // instanceof handles nulls
+ && this.internalList.equals(
+ ((UniqueTaskList) other).internalList));
+ }
+ //@@author A0142073R
+ /**
+ * Edits the equivalent task from the list.
+ *
+ * @throws TaskNotFoundException if no such task could be found in the list.
+ */
+ public boolean edit(ReadOnlyTask old, Task edit) throws TaskNotFoundException {
+ assert old != null;
+ final boolean taskFoundAndUpdated = internalList.contains(old);
+ if (!taskFoundAndUpdated) {
+ throw new TaskNotFoundException();
+ }
+ internalList.set(internalList.indexOf(old), edit);
+ return taskFoundAndUpdated;
+ }
+ //@@author
+ @Override
+ public int hashCode() {
+ return internalList.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/taskell/storage/ConfigStorage.java b/src/main/java/seedu/taskell/storage/ConfigStorage.java
new file mode 100644
index 000000000000..81e0ec9fff9a
--- /dev/null
+++ b/src/main/java/seedu/taskell/storage/ConfigStorage.java
@@ -0,0 +1,28 @@
+/** @@author A0142130A-reused**/
+package seedu.taskell.storage;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import seedu.taskell.commons.core.Config;
+import seedu.taskell.commons.exceptions.DataConversionException;
+
+/**
+ * Represents a storage for {@link seedu.taskell.commons.core.Config}.
+ */
+public interface ConfigStorage {
+ /**
+ * Returns Config data from storage.
+ * 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 readConfigFile() throws DataConversionException, IOException;
+
+ /**
+ * Saves the given {@link seedu.taskell.commons.core.Config} to the storage.
+ * @param config cannot be null.
+ * @throws IOException if there was any problem writing to the file.
+ */
+ void saveConfigFile(Config config) throws IOException;
+}
diff --git a/src/main/java/seedu/taskell/storage/JsonConfigStorage.java b/src/main/java/seedu/taskell/storage/JsonConfigStorage.java
new file mode 100644
index 000000000000..d63202836593
--- /dev/null
+++ b/src/main/java/seedu/taskell/storage/JsonConfigStorage.java
@@ -0,0 +1,77 @@
+/** @@author A0142130A **/
+package seedu.taskell.storage;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import seedu.taskell.commons.core.Config;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.exceptions.DataConversionException;
+import seedu.taskell.commons.util.FileUtil;
+
+/**
+ * A class to access Config stored in the hard disk as a json file
+ */
+
+public class JsonConfigStorage implements ConfigStorage {
+
+ private static final Logger logger = LogsCenter.getLogger(JsonConfigStorage.class);
+
+ private String filePath;
+
+ public JsonConfigStorage(String filePath) {
+ this.filePath = filePath;
+ }
+
+ @Override
+ public Optional readConfigFile() throws DataConversionException, IOException {
+ return readConfig(filePath);
+ }
+
+ @Override
+ public void saveConfigFile(Config config) throws IOException {
+ saveConfig(config, filePath);
+ }
+
+ /**
+ * Similar to {@link #readConfigFile()}
+ * @param configFilePath location of the data. Cannot be null.
+ * @throws DataConversionException if the file format is not as expected.
+ */
+ public Optional readConfig(String configFilePath) throws DataConversionException {
+ assert configFilePath != null;
+
+ File configFile = new File(configFilePath);
+
+ if (!configFile.exists()) {
+ logger.info("Config file " + configFile + " not found");
+ return Optional.empty();
+ }
+
+ Config config;
+
+ try {
+ config = FileUtil.deserializeObjectFromJsonFile(configFile, Config.class);
+ } catch (IOException e) {
+ logger.warning("Error reading from config file " + configFile + ": " + e);
+ throw new DataConversionException(e);
+ }
+
+ return Optional.of(config);
+ }
+
+ /**
+ * Similar to {@link #saveConfigFile(Config)}
+ * @param configFilePath location of the data. Cannot be null.
+ */
+ private void saveConfig(Config config, String configFilePath) throws IOException {
+ assert config != null;
+ assert configFilePath != null;
+ assert !configFilePath.isEmpty();
+
+ FileUtil.serializeObjectToJsonFile(new File(configFilePath), config);
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java b/src/main/java/seedu/taskell/storage/JsonUserPrefsStorage.java
similarity index 90%
rename from src/main/java/seedu/address/storage/JsonUserPrefsStorage.java
rename to src/main/java/seedu/taskell/storage/JsonUserPrefsStorage.java
index 1efa8288e4f6..8fcff2051e36 100644
--- a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java
+++ b/src/main/java/seedu/taskell/storage/JsonUserPrefsStorage.java
@@ -1,15 +1,15 @@
-package seedu.address.storage;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.util.FileUtil;
-import seedu.address.model.UserPrefs;
+package seedu.taskell.storage;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
import java.util.logging.Logger;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.exceptions.DataConversionException;
+import seedu.taskell.commons.util.FileUtil;
+import seedu.taskell.model.UserPrefs;
+
/**
* A class to access UserPrefs stored in the hard disk as a json file
*/
diff --git a/src/main/java/seedu/taskell/storage/Storage.java b/src/main/java/seedu/taskell/storage/Storage.java
new file mode 100644
index 000000000000..cdbe32dee7df
--- /dev/null
+++ b/src/main/java/seedu/taskell/storage/Storage.java
@@ -0,0 +1,39 @@
+package seedu.taskell.storage;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Optional;
+
+import seedu.taskell.commons.events.model.TaskManagerChangedEvent;
+import seedu.taskell.commons.events.storage.DataSavingExceptionEvent;
+import seedu.taskell.commons.exceptions.DataConversionException;
+import seedu.taskell.model.ReadOnlyTaskManager;
+import seedu.taskell.model.UserPrefs;
+
+/**
+ * API of the Storage component
+ */
+public interface Storage extends TaskManagerStorage, UserPrefsStorage {
+
+ @Override
+ Optional readUserPrefs() throws DataConversionException, IOException;
+
+ @Override
+ void saveUserPrefs(UserPrefs userPrefs) throws IOException;
+
+ @Override
+ String getTaskManagerFilePath();
+
+ @Override
+ Optional readTaskManager() throws DataConversionException, IOException;
+
+ @Override
+ void saveTaskManager(ReadOnlyTaskManager taskManager) throws IOException;
+
+ /**
+ * Saves the current version of the Task Manager to the hard disk.
+ * Creates the data file if it is missing.
+ * Raises {@link DataSavingExceptionEvent} if there was an error during saving.
+ */
+ void handleTaskManagerChangedEvent(TaskManagerChangedEvent abce);
+}
diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/taskell/storage/StorageManager.java
similarity index 50%
rename from src/main/java/seedu/address/storage/StorageManager.java
rename to src/main/java/seedu/taskell/storage/StorageManager.java
index ba1f72f15c27..765bfb216cf0 100644
--- a/src/main/java/seedu/address/storage/StorageManager.java
+++ b/src/main/java/seedu/taskell/storage/StorageManager.java
@@ -1,37 +1,37 @@
-package seedu.address.storage;
+package seedu.taskell.storage;
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;
-
-import java.io.FileNotFoundException;
+
+import seedu.taskell.commons.core.ComponentManager;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.events.model.TaskManagerChangedEvent;
+import seedu.taskell.commons.events.storage.DataSavingExceptionEvent;
+import seedu.taskell.commons.exceptions.DataConversionException;
+import seedu.taskell.model.ReadOnlyTaskManager;
+import seedu.taskell.model.UserPrefs;
+
import java.io.IOException;
import java.util.Optional;
import java.util.logging.Logger;
/**
- * Manages storage of AddressBook data in local storage.
+ * Manages storage of TaskManager data in local storage.
*/
public class StorageManager extends ComponentManager implements Storage {
private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
- private AddressBookStorage addressBookStorage;
+ private TaskManagerStorage taskManagerStorage;
private UserPrefsStorage userPrefsStorage;
- public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) {
+ public StorageManager(TaskManagerStorage taskManagerStorage, UserPrefsStorage userPrefsStorage) {
super();
- this.addressBookStorage = addressBookStorage;
+ this.taskManagerStorage = taskManagerStorage;
this.userPrefsStorage = userPrefsStorage;
}
- public StorageManager(String addressBookFilePath, String userPrefsFilePath) {
- this(new XmlAddressBookStorage(addressBookFilePath), new JsonUserPrefsStorage(userPrefsFilePath));
+ public StorageManager(String taskManagerFilePath, String userPrefsFilePath) {
+ this(new XmlTaskManagerStorage(taskManagerFilePath), new JsonUserPrefsStorage(userPrefsFilePath));
}
// ================ UserPrefs methods ==============================
@@ -47,42 +47,42 @@ public void saveUserPrefs(UserPrefs userPrefs) throws IOException {
}
- // ================ AddressBook methods ==============================
+ // ================ TaskManager methods ==============================
@Override
- public String getAddressBookFilePath() {
- return addressBookStorage.getAddressBookFilePath();
+ public String getTaskManagerFilePath() {
+ return taskManagerStorage.getTaskManagerFilePath();
}
@Override
- public Optional readAddressBook() throws DataConversionException, IOException {
- return readAddressBook(addressBookStorage.getAddressBookFilePath());
+ public Optional readTaskManager() throws DataConversionException, IOException {
+ return readTaskManager(taskManagerStorage.getTaskManagerFilePath());
}
@Override
- public Optional readAddressBook(String filePath) throws DataConversionException, IOException {
+ public Optional readTaskManager(String filePath) throws DataConversionException, IOException {
logger.fine("Attempting to read data from file: " + filePath);
- return addressBookStorage.readAddressBook(filePath);
+ return taskManagerStorage.readTaskManager(filePath);
}
@Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath());
+ public void saveTaskManager(ReadOnlyTaskManager taskManager) throws IOException {
+ saveTaskManager(taskManager, taskManagerStorage.getTaskManagerFilePath());
}
@Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) throws IOException {
+ public void saveTaskManager(ReadOnlyTaskManager taskManager, String filePath) throws IOException {
logger.fine("Attempting to write to data file: " + filePath);
- addressBookStorage.saveAddressBook(addressBook, filePath);
+ taskManagerStorage.saveTaskManager(taskManager, filePath);
}
@Override
@Subscribe
- public void handleAddressBookChangedEvent(AddressBookChangedEvent event) {
+ public void handleTaskManagerChangedEvent(TaskManagerChangedEvent event) {
logger.info(LogsCenter.getEventHandlingLogMessage(event, "Local data changed, saving to file"));
try {
- saveAddressBook(event.data);
+ saveTaskManager(event.data);
} catch (IOException e) {
raise(new DataSavingExceptionEvent(e));
}
diff --git a/src/main/java/seedu/taskell/storage/TaskManagerStorage.java b/src/main/java/seedu/taskell/storage/TaskManagerStorage.java
new file mode 100644
index 000000000000..8eabc19917fe
--- /dev/null
+++ b/src/main/java/seedu/taskell/storage/TaskManagerStorage.java
@@ -0,0 +1,44 @@
+package seedu.taskell.storage;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import seedu.taskell.commons.exceptions.DataConversionException;
+import seedu.taskell.model.ReadOnlyTaskManager;
+
+/**
+ * Represents a storage for {@link seedu.taskell.model.TaskManager}.
+ */
+public interface TaskManagerStorage {
+
+ /**
+ * Returns the file path of the data file.
+ */
+ String getTaskManagerFilePath();
+
+ /**
+ * Returns TaskManager data as a {@link ReadOnlyTaskManager}.
+ * 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 readTaskManager() throws DataConversionException, IOException;
+
+ /**
+ * @see #getTaskManagerFilePath()
+ */
+ Optional readTaskManager(String filePath) throws DataConversionException, IOException;
+
+ /**
+ * Saves the given {@link ReadOnlyTaskManager} to the storage.
+ * @param taskManager cannot be null.
+ * @throws IOException if there was any problem writing to the file.
+ */
+ void saveTaskManager(ReadOnlyTaskManager taskManager) throws IOException;
+
+ /**
+ * @see #saveTaskManager(ReadOnlyTaskManager)
+ */
+ void saveTaskManager(ReadOnlyTaskManager taskManager, String filePath) throws IOException;
+
+}
diff --git a/src/main/java/seedu/address/storage/UserPrefsStorage.java b/src/main/java/seedu/taskell/storage/UserPrefsStorage.java
similarity index 73%
rename from src/main/java/seedu/address/storage/UserPrefsStorage.java
rename to src/main/java/seedu/taskell/storage/UserPrefsStorage.java
index ad2dc935187c..913201e1539f 100644
--- a/src/main/java/seedu/address/storage/UserPrefsStorage.java
+++ b/src/main/java/seedu/taskell/storage/UserPrefsStorage.java
@@ -1,13 +1,13 @@
-package seedu.address.storage;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.UserPrefs;
+package seedu.taskell.storage;
import java.io.IOException;
import java.util.Optional;
+import seedu.taskell.commons.exceptions.DataConversionException;
+import seedu.taskell.model.UserPrefs;
+
/**
- * Represents a storage for {@link seedu.address.model.UserPrefs}.
+ * Represents a storage for {@link seedu.taskell.model.UserPrefs}.
*/
public interface UserPrefsStorage {
@@ -20,7 +20,7 @@ public interface UserPrefsStorage {
Optional readUserPrefs() throws DataConversionException, IOException;
/**
- * Saves the given {@link seedu.address.model.UserPrefs} to the storage.
+ * Saves the given {@link seedu.taskell.model.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/XmlAdaptedTag.java b/src/main/java/seedu/taskell/storage/XmlAdaptedTag.java
similarity index 77%
rename from src/main/java/seedu/address/storage/XmlAdaptedTag.java
rename to src/main/java/seedu/taskell/storage/XmlAdaptedTag.java
index b9723fafbc67..4e4d3fd22578 100644
--- a/src/main/java/seedu/address/storage/XmlAdaptedTag.java
+++ b/src/main/java/seedu/taskell/storage/XmlAdaptedTag.java
@@ -1,11 +1,11 @@
-package seedu.address.storage;
-
-import seedu.address.commons.util.CollectionUtil;
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.tag.Tag;
+package seedu.taskell.storage;
import javax.xml.bind.annotation.XmlValue;
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.commons.util.CollectionUtil;
+import seedu.taskell.model.tag.Tag;
+
/**
* JAXB-friendly adapted version of the Tag.
*/
@@ -31,7 +31,7 @@ public XmlAdaptedTag(Tag source) {
/**
* Converts this jaxb-friendly adapted tag object into the model's Tag object.
*
- * @throws IllegalValueException if there were any data constraints violated in the adapted person
+ * @throws IllegalValueException if there were any data constraints violated in the adapted task
*/
public Tag toModelType() throws IllegalValueException {
return new Tag(tagName);
diff --git a/src/main/java/seedu/taskell/storage/XmlAdaptedTask.java b/src/main/java/seedu/taskell/storage/XmlAdaptedTask.java
new file mode 100644
index 000000000000..9f5da142343d
--- /dev/null
+++ b/src/main/java/seedu/taskell/storage/XmlAdaptedTask.java
@@ -0,0 +1,86 @@
+package seedu.taskell.storage;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * JAXB-friendly version of the Task.
+ */
+public class XmlAdaptedTask {
+
+ @XmlElement(required = true)
+ private String description;
+ @XmlElement(required = true)
+ private String taskType;
+ @XmlElement(required = true)
+ private String startDate;
+ @XmlElement(required = true)
+ private String endDate;
+ @XmlElement(required = true)
+ private String startTime;
+ @XmlElement(required = true)
+ private String endTime;
+ @XmlElement(required = true)
+ private String taskPriority;
+ @XmlElement(required = true)
+ private String taskStatus;
+
+ @XmlElement
+ private List tagged = new ArrayList<>();
+
+ /**
+ * No-arg constructor for JAXB use.
+ */
+ public XmlAdaptedTask() {}
+
+
+ /**
+ * Converts a given Task into this class for JAXB use.
+ *
+ * @param source future changes to this will not affect the created XmlAdaptedTask
+ */
+ public XmlAdaptedTask(ReadOnlyTask source) {
+ description = source.getDescription().description;
+ taskType = source.getTaskType();
+ startDate = source.getStartDate().taskDate;
+ endDate = source.getEndDate().taskDate;
+ startTime = source.getStartTime().taskTime;
+ endTime = source.getEndTime().taskTime;
+ taskPriority = source.getTaskPriority().taskPriority;
+ taskStatus = source.getTaskStatus().taskStatus;
+ tagged = new ArrayList<>();
+ for (Tag tag : source.getTags()) {
+ tagged.add(new XmlAdaptedTag(tag));
+ }
+
+ }
+
+ /**
+ * Converts this jaxb-friendly adapted task object into the model's Task object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated in the adapted task
+ */
+ public Task toModelType() throws IllegalValueException {
+ final List taskTags = new ArrayList<>();
+ for (XmlAdaptedTag tag : tagged) {
+ taskTags.add(tag.toModelType());
+ }
+ final Description description = new Description(this.description);
+ final String taskType = this.taskType;
+ final TaskDate startDate = new TaskDate(this.startDate);
+ final TaskDate endDate = new TaskDate(this.endDate);
+ final TaskTime startTime= new TaskTime(this.startTime);
+ final TaskTime endTime = new TaskTime(this.endTime);
+ final TaskPriority taskPriority = new TaskPriority(this.taskPriority);
+ final TaskStatus taskStatus = new TaskStatus(this.taskStatus);
+ final UniqueTagList tags = new UniqueTagList(taskTags);
+ return new Task(description, taskType, startDate, endDate, startTime, endTime, taskPriority, taskStatus, tags);
+ }
+}
diff --git a/src/main/java/seedu/address/storage/XmlFileStorage.java b/src/main/java/seedu/taskell/storage/XmlFileStorage.java
similarity index 61%
rename from src/main/java/seedu/address/storage/XmlFileStorage.java
rename to src/main/java/seedu/taskell/storage/XmlFileStorage.java
index 27a5210cadaf..4b910d8e425d 100644
--- a/src/main/java/seedu/address/storage/XmlFileStorage.java
+++ b/src/main/java/seedu/taskell/storage/XmlFileStorage.java
@@ -1,35 +1,36 @@
-package seedu.address.storage;
-
-import seedu.address.commons.util.XmlUtil;
-import seedu.address.commons.exceptions.DataConversionException;
+package seedu.taskell.storage;
import javax.xml.bind.JAXBException;
+
+import seedu.taskell.commons.exceptions.DataConversionException;
+import seedu.taskell.commons.util.XmlUtil;
+
import java.io.File;
import java.io.FileNotFoundException;
/**
- * Stores addressbook data in an XML file
+ * Stores taskmanager data in an XML file
*/
public class XmlFileStorage {
/**
- * Saves the given addressbook data to the specified file.
+ * Saves the given taskmanager data to the specified file.
*/
- public static void saveDataToFile(File file, XmlSerializableAddressBook addressBook)
+ public static void saveDataToFile(File file, XmlSerializableTaskManager taskManager)
throws FileNotFoundException {
try {
- XmlUtil.saveDataToFile(file, addressBook);
+ XmlUtil.saveDataToFile(file, taskManager);
} catch (JAXBException e) {
assert false : "Unexpected exception " + e.getMessage();
}
}
/**
- * Returns address book in the file or an empty address book
+ * Returns task manager in the file or an empty task manager
*/
- public static XmlSerializableAddressBook loadDataFromSaveFile(File file) throws DataConversionException,
+ public static XmlSerializableTaskManager loadDataFromSaveFile(File file) throws DataConversionException,
FileNotFoundException {
try {
- return XmlUtil.getDataFromFile(file, XmlSerializableAddressBook.class);
+ return XmlUtil.getDataFromFile(file, XmlSerializableTaskManager.class);
} catch (JAXBException e) {
throw new DataConversionException(e);
}
diff --git a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java b/src/main/java/seedu/taskell/storage/XmlSerializableTaskManager.java
similarity index 57%
rename from src/main/java/seedu/address/storage/XmlSerializableAddressBook.java
rename to src/main/java/seedu/taskell/storage/XmlSerializableTaskManager.java
index b7ec533a3a1e..891ffacfe6ef 100644
--- a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java
+++ b/src/main/java/seedu/taskell/storage/XmlSerializableTaskManager.java
@@ -1,45 +1,46 @@
-package seedu.address.storage;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.tag.Tag;
-import seedu.address.model.tag.UniqueTagList;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.ReadOnlyPerson;
-import seedu.address.model.person.UniquePersonList;
+package seedu.taskell.storage;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+
+import seedu.taskell.commons.exceptions.IllegalValueException;
+import seedu.taskell.model.ReadOnlyTaskManager;
+import seedu.taskell.model.tag.Tag;
+import seedu.taskell.model.tag.UniqueTagList;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.UniqueTaskList;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
- * An Immutable AddressBook that is serializable to XML format
+ * An Immutable TaskManager that is serializable to XML format
*/
-@XmlRootElement(name = "addressbook")
-public class XmlSerializableAddressBook implements ReadOnlyAddressBook {
+@XmlRootElement(name = "taskmanager")
+public class XmlSerializableTaskManager implements ReadOnlyTaskManager {
@XmlElement
- private List persons;
+ private List tasks;
@XmlElement
private List tags;
{
- persons = new ArrayList<>();
+ tasks = new ArrayList<>();
tags = new ArrayList<>();
}
/**
* Empty constructor required for marshalling
*/
- public XmlSerializableAddressBook() {}
+ public XmlSerializableTaskManager() {}
/**
* Conversion
*/
- public XmlSerializableAddressBook(ReadOnlyAddressBook src) {
- persons.addAll(src.getPersonList().stream().map(XmlAdaptedPerson::new).collect(Collectors.toList()));
+ public XmlSerializableTaskManager(ReadOnlyTaskManager src) {
+ tasks.addAll(src.getTaskList().stream().map(XmlAdaptedTask::new).collect(Collectors.toList()));
tags = src.getTagList();
}
@@ -55,9 +56,9 @@ public UniqueTagList getUniqueTagList() {
}
@Override
- public UniquePersonList getUniquePersonList() {
- UniquePersonList lists = new UniquePersonList();
- for (XmlAdaptedPerson p : persons) {
+ public UniqueTaskList getUniqueTaskList() {
+ UniqueTaskList lists = new UniqueTaskList();
+ for (XmlAdaptedTask p : tasks) {
try {
lists.add(p.toModelType());
} catch (IllegalValueException e) {
@@ -68,8 +69,8 @@ public UniquePersonList getUniquePersonList() {
}
@Override
- public List getPersonList() {
- return persons.stream().map(p -> {
+ public List getTaskList() {
+ return tasks.stream().map(p -> {
try {
return p.toModelType();
} catch (IllegalValueException e) {
diff --git a/src/main/java/seedu/taskell/storage/XmlTaskManagerStorage.java b/src/main/java/seedu/taskell/storage/XmlTaskManagerStorage.java
new file mode 100644
index 000000000000..f07ef813f1d7
--- /dev/null
+++ b/src/main/java/seedu/taskell/storage/XmlTaskManagerStorage.java
@@ -0,0 +1,73 @@
+package seedu.taskell.storage;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.exceptions.DataConversionException;
+import seedu.taskell.commons.util.FileUtil;
+import seedu.taskell.model.ReadOnlyTaskManager;
+
+/**
+ * A class to access TaskManager data stored as an xml file on the hard disk.
+ */
+public class XmlTaskManagerStorage implements TaskManagerStorage {
+
+ private static final Logger logger = LogsCenter.getLogger(XmlTaskManagerStorage.class);
+
+ private String filePath;
+
+ public XmlTaskManagerStorage(String filePath){
+ this.filePath = filePath;
+ }
+
+ public String getTaskManagerFilePath(){
+ return filePath;
+ }
+
+ /**
+ * Similar to {@link #readTaskManager()}
+ * @param filePath location of the data. Cannot be null
+ * @throws DataConversionException if the file is not in the correct format.
+ */
+ public Optional readTaskManager(String filePath) throws DataConversionException, FileNotFoundException {
+ assert filePath != null;
+
+ File taskManagerFile = new File(filePath);
+
+ if (!taskManagerFile.exists()) {
+ logger.info("TaskManager file " + taskManagerFile + " not found");
+ return Optional.empty();
+ }
+
+ ReadOnlyTaskManager taskManagerOptional = XmlFileStorage.loadDataFromSaveFile(new File(filePath));
+
+ return Optional.of(taskManagerOptional);
+ }
+
+ /**
+ * Similar to {@link #saveTaskManager(ReadOnlyTaskManager)}
+ * @param filePath location of the data. Cannot be null
+ */
+ public void saveTaskManager(ReadOnlyTaskManager taskManager, String filePath) throws IOException {
+ assert taskManager != null;
+ assert filePath != null;
+
+ File file = new File(filePath);
+ FileUtil.createIfMissing(file);
+ XmlFileStorage.saveDataToFile(file, new XmlSerializableTaskManager(taskManager));
+ }
+
+ @Override
+ public Optional readTaskManager() throws DataConversionException, IOException {
+ return readTaskManager(filePath);
+ }
+
+ @Override
+ public void saveTaskManager(ReadOnlyTaskManager taskManager) throws IOException {
+ saveTaskManager(taskManager, filePath);
+ }
+}
diff --git a/src/main/java/seedu/taskell/ui/CalendarView.java b/src/main/java/seedu/taskell/ui/CalendarView.java
new file mode 100644
index 000000000000..de62e339cd93
--- /dev/null
+++ b/src/main/java/seedu/taskell/ui/CalendarView.java
@@ -0,0 +1,21 @@
+/** @@author A0142130A **/
+package seedu.taskell.ui;
+
+import jfxtras.scene.control.agenda.Agenda;
+
+/** This class holds the necessary elements to display calendar UI via Agenda API from jfxtras
+ * */
+
+public class CalendarView {
+
+ private Agenda agenda;
+
+ public CalendarView() {
+ agenda = new Agenda();
+ }
+
+ public Agenda getAgenda() {
+ return agenda;
+ }
+
+}
diff --git a/src/main/java/seedu/address/ui/CommandBox.java b/src/main/java/seedu/taskell/ui/CommandBox.java
similarity index 93%
rename from src/main/java/seedu/address/ui/CommandBox.java
rename to src/main/java/seedu/taskell/ui/CommandBox.java
index 2e1409a3016c..56cefcf30c60 100644
--- a/src/main/java/seedu/address/ui/CommandBox.java
+++ b/src/main/java/seedu/taskell/ui/CommandBox.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.taskell.ui;
import com.google.common.eventbus.Subscribe;
import javafx.fxml.FXML;
@@ -7,11 +7,11 @@
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
-import seedu.address.commons.events.ui.IncorrectCommandAttemptedEvent;
-import seedu.address.logic.Logic;
-import seedu.address.logic.commands.*;
-import seedu.address.commons.util.FxViewUtil;
-import seedu.address.commons.core.LogsCenter;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.events.ui.IncorrectCommandAttemptedEvent;
+import seedu.taskell.commons.util.FxViewUtil;
+import seedu.taskell.logic.Logic;
+import seedu.taskell.logic.commands.*;
import java.util.logging.Logger;
diff --git a/src/main/java/seedu/taskell/ui/DisplayPanel.java b/src/main/java/seedu/taskell/ui/DisplayPanel.java
new file mode 100644
index 000000000000..7df604dc6e38
--- /dev/null
+++ b/src/main/java/seedu/taskell/ui/DisplayPanel.java
@@ -0,0 +1,99 @@
+/** @@author A0142130A **/
+package seedu.taskell.ui;
+
+import javafx.scene.Node;
+import javafx.scene.control.TextArea;
+import javafx.scene.layout.AnchorPane;
+import jfxtras.scene.control.agenda.Agenda;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.util.FxViewUtil;
+
+import java.util.ArrayList;
+import java.util.logging.Logger;
+
+/**
+ * The Display Panel of the App.
+ */
+public class DisplayPanel extends UiPart{
+
+ private static Logger logger = LogsCenter.getLogger(DisplayPanel.class);
+
+ public static final String RESULT_DISPLAY_ID = "resultDisplay";
+ private static final String STATUS_BAR_STYLE_SHEET = "result-display";
+
+ private TextArea display;
+ private CalendarView calendarView;
+
+ /**
+ * Constructor is kept private as {@link #load(AnchorPane)} is the only way to create a DisplayPanel.
+ */
+ private DisplayPanel() {
+ calendarView = new CalendarView();
+ display = new TextArea();
+ }
+
+ @Override
+ public void setNode(Node node) {
+ //not applicable
+ }
+
+ @Override
+ public String getFxmlPath() {
+ return null; //not applicable
+ }
+
+ /**
+ * This method should be called after the FX runtime is initialized and in FX application thread.
+ * @param placeholder The AnchorPane where the DisplayPanel must be inserted
+ */
+ public static DisplayPanel load(AnchorPane placeholder){
+ logger.info("Initializing display panel");
+ DisplayPanel displayPanel = new DisplayPanel();
+
+ //displayPanel.display = new TextArea();
+ displayPanel.display.setEditable(false);
+ displayPanel.display.setId(RESULT_DISPLAY_ID);
+ displayPanel.display.getStyleClass().removeAll();
+ displayPanel.display.getStyleClass().add(STATUS_BAR_STYLE_SHEET);
+
+ FxViewUtil.applyAnchorBoundaryParameters(displayPanel.display, 0.0, 0.0, 0.0, 0.0);
+ placeholder.getChildren().add(displayPanel.display);
+
+ displayPanel.display.setText("Welcome to Taskell!\n"
+ + "Enter 'add' in command box to add a task.\n"
+ + "Enter 'list-undo' for list of commands to undo.\n"
+ + "Enter 'help' for more information about commands.\n"
+ + "Enter 'calendar' to view calendar.");
+
+ return displayPanel;
+ }
+
+ public void loadList(AnchorPane placeholder, ArrayList list) {
+ placeholder.getChildren().clear();
+ placeholder.getChildren().add(display);
+
+ display.setText("");
+ if (list.isEmpty()) {
+ display.setText("No commands available for undo.");
+ }
+ else {
+ for (int i=0; i list) {
+ displayPanel.loadList(displayPanelPlaceholder, list);
}
-
- public void releaseResources() {
- browserPanel.freeResources();
+
+ public void loadCalendarView() {
+ displayPanel.loadCalendar(displayPanelPlaceholder);
}
+
+ /** @@author **/
+
}
diff --git a/src/main/java/seedu/address/ui/ResultDisplay.java b/src/main/java/seedu/taskell/ui/ResultDisplay.java
similarity index 96%
rename from src/main/java/seedu/address/ui/ResultDisplay.java
rename to src/main/java/seedu/taskell/ui/ResultDisplay.java
index 37284ee6c696..56b2dc2cfad7 100644
--- a/src/main/java/seedu/address/ui/ResultDisplay.java
+++ b/src/main/java/seedu/taskell/ui/ResultDisplay.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.taskell.ui;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
@@ -6,7 +6,7 @@
import javafx.scene.control.TextArea;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
-import seedu.address.commons.util.FxViewUtil;
+import seedu.taskell.commons.util.FxViewUtil;
/**
* 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/seedu/taskell/ui/StatusBarFooter.java
similarity index 84%
rename from src/main/java/seedu/address/ui/StatusBarFooter.java
rename to src/main/java/seedu/taskell/ui/StatusBarFooter.java
index f74f66be6fc9..1dcc0f347caf 100644
--- a/src/main/java/seedu/address/ui/StatusBarFooter.java
+++ b/src/main/java/seedu/taskell/ui/StatusBarFooter.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.taskell.ui;
import com.google.common.eventbus.Subscribe;
import javafx.fxml.FXML;
@@ -6,10 +6,12 @@
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.events.model.TaskManagerChangedEvent;
+import seedu.taskell.commons.events.storage.StorageLocationChangedEvent;
+import seedu.taskell.commons.util.FxViewUtil;
+
import org.controlsfx.control.StatusBar;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.events.model.AddressBookChangedEvent;
-import seedu.address.commons.util.FxViewUtil;
import java.util.Date;
import java.util.logging.Logger;
@@ -90,9 +92,14 @@ public String getFxmlPath() {
}
@Subscribe
- public void handleAddressBookChangedEvent(AddressBookChangedEvent abce) {
+ public void handleTaskManagerChangedEvent(TaskManagerChangedEvent abce) {
String lastUpdated = (new Date()).toString();
logger.info(LogsCenter.getEventHandlingLogMessage(abce, "Setting last updated status to " + lastUpdated));
setSyncStatus("Last Updated: " + lastUpdated);
}
+
+ @Subscribe
+ public void handleStorageLocationChangedEvent(StorageLocationChangedEvent event) {
+ setSaveLocation(event.getConfig().getTaskManagerFilePath());
+ }
}
diff --git a/src/main/java/seedu/taskell/ui/TaskCard.java b/src/main/java/seedu/taskell/ui/TaskCard.java
new file mode 100644
index 000000000000..b1af50d23c09
--- /dev/null
+++ b/src/main/java/seedu/taskell/ui/TaskCard.java
@@ -0,0 +1,103 @@
+package seedu.taskell.ui;
+
+import javafx.fxml.FXML;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import seedu.taskell.model.task.ReadOnlyTask;
+import seedu.taskell.model.task.Task;
+import seedu.taskell.model.task.TaskPriority;
+
+public class TaskCard extends UiPart{
+
+ private static final String FXML = "TaskListCard.fxml";
+
+ @FXML
+ private HBox cardPane;
+ @FXML
+ private Label description;
+ @FXML
+ private Label id;
+ @FXML
+ private Label startDate;
+ @FXML
+ private Label endDate;
+ @FXML
+ private Label startTime;
+ @FXML
+ private Label endTime;
+ @FXML
+ private Label taskStatus;
+ @FXML
+ private Label tags;
+
+ private ReadOnlyTask task;
+ private int displayedIndex;
+
+ public TaskCard(){
+
+ }
+
+ public static TaskCard load(ReadOnlyTask task, int displayedIndex){
+ TaskCard card = new TaskCard();
+ card.task = task;
+ card.displayedIndex = displayedIndex;
+ return UiPartLoader.loadUiPart(card);
+ }
+
+//@@author A0139257X
+ @FXML
+ public void initialize() {
+ id.setText(displayedIndex + ". ");
+ description.setText(task.getDescription().description);
+ tags.setText(task.tagsString());
+ taskStatus.setText(task.getTaskStatus().taskStatus);
+
+ setDateTime();
+ setDateTimeVisibility();
+ setCardPaneBackground();
+ }
+
+ private void setDateTime() {
+ startDate.setText(task.getStartDate().getDisplayDate());
+ endDate.setText(task.getEndDate().getDisplayDate());
+ startTime.setText(task.getStartTime().taskTime);
+ endTime.setText(task.getEndTime().taskTime);
+
+ }
+
+ private void setDateTimeVisibility() {
+ if (task.getTaskType().equals(Task.FLOATING_TASK)) {
+ startDate.setVisible(false);
+ endDate.setVisible(false);
+ startTime.setVisible(false);
+ endTime.setVisible(false);
+ }
+
+ }
+
+ private void setCardPaneBackground() {
+ if (task.getTaskPriority().taskPriority.equals(TaskPriority.HIGH_PRIORITY)) {
+ cardPane.setStyle(TaskPriority.HIGH_PRIORITY_BACKGROUND);
+ } else if (task.getTaskPriority().taskPriority.equals(TaskPriority.MEDIUM_PRIORITY)) {
+ cardPane.setStyle(TaskPriority.MEDIUM_PRIORITY_BACKGROUND);
+ } else if (task.getTaskPriority().taskPriority.equals(TaskPriority.LOW_PRIORITY)) {
+ cardPane.setStyle(TaskPriority.LOW_PRIORITY_BACKGROUND);
+ }
+ }
+//@@author
+
+ public HBox getLayout() {
+ return cardPane;
+ }
+
+ @Override
+ public void setNode(Node node) {
+ cardPane = (HBox)node;
+ }
+
+ @Override
+ public String getFxmlPath() {
+ return FXML;
+ }
+}
diff --git a/src/main/java/seedu/taskell/ui/TaskListPanel.java b/src/main/java/seedu/taskell/ui/TaskListPanel.java
new file mode 100644
index 000000000000..91e484e63dca
--- /dev/null
+++ b/src/main/java/seedu/taskell/ui/TaskListPanel.java
@@ -0,0 +1,108 @@
+package seedu.taskell.ui;
+
+import javafx.application.Platform;
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.scene.Node;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.control.SplitPane;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.VBox;
+import javafx.stage.Stage;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.events.ui.TaskPanelSelectionChangedEvent;
+import seedu.taskell.model.task.ReadOnlyTask;
+
+import java.util.logging.Logger;
+
+/**
+ * Panel containing the list of tasks.
+ */
+public class TaskListPanel extends UiPart {
+ private final Logger logger = LogsCenter.getLogger(TaskListPanel.class);
+ private static final String FXML = "TaskListPanel.fxml";
+ private VBox panel;
+ private AnchorPane placeHolderPane;
+
+ @FXML
+ private ListView taskListView;
+
+ public TaskListPanel() {
+ super();
+ }
+
+ @Override
+ public void setNode(Node node) {
+ panel = (VBox) node;
+ }
+
+ @Override
+ public String getFxmlPath() {
+ return FXML;
+ }
+
+ @Override
+ public void setPlaceholder(AnchorPane pane) {
+ this.placeHolderPane = pane;
+ }
+
+ public static TaskListPanel load(Stage primaryStage, AnchorPane taskListPlaceholder,
+ ObservableList taskList) {
+ TaskListPanel taskListPanel =
+ UiPartLoader.loadUiPart(primaryStage, taskListPlaceholder, new TaskListPanel());
+ taskListPanel.configure(taskList);
+ return taskListPanel;
+ }
+
+ private void configure(ObservableList taskList) {
+ setConnections(taskList);
+ addToPlaceholder();
+ }
+
+ private void setConnections(ObservableList taskList) {
+ taskListView.setItems(taskList);
+ taskListView.setCellFactory(listView -> new TaskListViewCell());
+ setEventHandlerForSelectionChangeEvent();
+ }
+
+ private void addToPlaceholder() {
+ SplitPane.setResizableWithParent(placeHolderPane, false);
+ placeHolderPane.getChildren().add(panel);
+ }
+
+ private void setEventHandlerForSelectionChangeEvent() {
+ taskListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
+ if (newValue != null) {
+ logger.fine("Selection in task list panel changed to : '" + newValue + "'");
+ raise(new TaskPanelSelectionChangedEvent(newValue));
+ }
+ });
+ }
+
+ public void scrollTo(int index) {
+ Platform.runLater(() -> {
+ taskListView.scrollTo(index);
+ taskListView.getSelectionModel().clearAndSelect(index);
+ });
+ }
+
+ class TaskListViewCell extends ListCell {
+
+ public TaskListViewCell() {
+ }
+
+ @Override
+ protected void updateItem(ReadOnlyTask task, boolean empty) {
+ super.updateItem(task, empty);
+
+ if (empty || task == null) {
+ setGraphic(null);
+ setText(null);
+ } else {
+ setGraphic(TaskCard.load(task, getIndex() + 1).getLayout());
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/ui/Ui.java b/src/main/java/seedu/taskell/ui/Ui.java
similarity index 88%
rename from src/main/java/seedu/address/ui/Ui.java
rename to src/main/java/seedu/taskell/ui/Ui.java
index e6a67fe8c027..409f419fa110 100644
--- a/src/main/java/seedu/address/ui/Ui.java
+++ b/src/main/java/seedu/taskell/ui/Ui.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.taskell.ui;
import javafx.stage.Stage;
diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/taskell/ui/UiManager.java
similarity index 72%
rename from src/main/java/seedu/address/ui/UiManager.java
rename to src/main/java/seedu/taskell/ui/UiManager.java
index 4a4dba3a2f6e..1e89e8de82fd 100644
--- a/src/main/java/seedu/address/ui/UiManager.java
+++ b/src/main/java/seedu/taskell/ui/UiManager.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.taskell.ui;
import com.google.common.eventbus.Subscribe;
import javafx.application.Platform;
@@ -6,17 +6,19 @@
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.events.ui.JumpToListRequestEvent;
-import seedu.address.commons.events.ui.PersonPanelSelectionChangedEvent;
-import seedu.address.commons.events.ui.ShowHelpRequestEvent;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.Logic;
-import seedu.address.model.UserPrefs;
+import seedu.taskell.MainApp;
+import seedu.taskell.commons.core.ComponentManager;
+import seedu.taskell.commons.core.Config;
+import seedu.taskell.commons.core.LogsCenter;
+import seedu.taskell.commons.events.storage.DataSavingExceptionEvent;
+import seedu.taskell.commons.events.ui.DisplayCalendarViewEvent;
+import seedu.taskell.commons.events.ui.DisplayListChangedEvent;
+import seedu.taskell.commons.events.ui.JumpToListRequestEvent;
+import seedu.taskell.commons.events.ui.TaskPanelSelectionChangedEvent;
+import seedu.taskell.commons.events.ui.ShowHelpRequestEvent;
+import seedu.taskell.commons.util.StringUtil;
+import seedu.taskell.logic.Logic;
+import seedu.taskell.model.UserPrefs;
import java.util.logging.Logger;
@@ -25,7 +27,7 @@
*/
public class UiManager extends ComponentManager implements Ui {
private static final Logger logger = LogsCenter.getLogger(UiManager.class);
- private static final String ICON_APPLICATION = "/images/address_book_32.png";
+ private static final String ICON_APPLICATION = "/images/task_manager_32.png";
private Logic logic;
private Config config;
@@ -62,7 +64,6 @@ public void start(Stage primaryStage) {
public void stop() {
prefs.updateLastUsedGuiSetting(mainWindow.getCurrentGuiSetting());
mainWindow.hide();
- mainWindow.releaseResources();
}
private void showFileOperationAlertAndWait(String description, String details, Throwable cause) {
@@ -81,7 +82,7 @@ void showAlertDialogAndWait(Alert.AlertType type, String title, String headerTex
private static void showAlertDialogAndWait(Stage owner, AlertType type, String title, String headerText,
String contentText) {
final Alert alert = new Alert(type);
- alert.getDialogPane().getStylesheets().add("view/DarkTheme.css");
+ alert.getDialogPane().getStylesheets().add("view/TaskellCyanTheme.css");
alert.initOwner(owner);
alert.setTitle(title);
alert.setHeaderText(headerText);
@@ -114,13 +115,25 @@ private void handleShowHelpEvent(ShowHelpRequestEvent event) {
@Subscribe
private void handleJumpToListRequestEvent(JumpToListRequestEvent event) {
logger.info(LogsCenter.getEventHandlingLogMessage(event));
- mainWindow.getPersonListPanel().scrollTo(event.targetIndex);
+ mainWindow.getTaskListPanel().scrollTo(event.targetIndex);
}
-
+
+ /** @@author A0142130A **/
+
+ @Subscribe
+ private void handleDisplayList(DisplayListChangedEvent event) {
+ logger.info(LogsCenter.getEventHandlingLogMessage(event));
+ logger.info("Displaying list...");
+ mainWindow.loadList(event.getList());
+ }
+
@Subscribe
- private void handlePersonPanelSelectionChangedEvent(PersonPanelSelectionChangedEvent event){
+ private void handleShowCalendarView(DisplayCalendarViewEvent event) {
logger.info(LogsCenter.getEventHandlingLogMessage(event));
- mainWindow.loadPersonPage(event.getNewSelection());
+ logger.info("Displaying calendar view...");
+ mainWindow.loadCalendarView();
}
+
+ /** @@author **/
}
diff --git a/src/main/java/seedu/address/ui/UiPart.java b/src/main/java/seedu/taskell/ui/UiPart.java
similarity index 94%
rename from src/main/java/seedu/address/ui/UiPart.java
rename to src/main/java/seedu/taskell/ui/UiPart.java
index 0a4ceb33e9b7..f5c7c4343d43 100644
--- a/src/main/java/seedu/address/ui/UiPart.java
+++ b/src/main/java/seedu/taskell/ui/UiPart.java
@@ -1,13 +1,13 @@
-package seedu.address.ui;
+package seedu.taskell.ui;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
-import seedu.address.commons.core.EventsCenter;
-import seedu.address.commons.events.BaseEvent;
-import seedu.address.commons.util.AppUtil;
+import seedu.taskell.commons.core.EventsCenter;
+import seedu.taskell.commons.events.BaseEvent;
+import seedu.taskell.commons.util.AppUtil;
/**
* Base class for UI parts.
diff --git a/src/main/java/seedu/address/ui/UiPartLoader.java b/src/main/java/seedu/taskell/ui/UiPartLoader.java
similarity index 97%
rename from src/main/java/seedu/address/ui/UiPartLoader.java
rename to src/main/java/seedu/taskell/ui/UiPartLoader.java
index f880685a5b15..471b1e2c1145 100644
--- a/src/main/java/seedu/address/ui/UiPartLoader.java
+++ b/src/main/java/seedu/taskell/ui/UiPartLoader.java
@@ -1,10 +1,10 @@
-package seedu.address.ui;
+package seedu.taskell.ui;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
-import seedu.address.MainApp;
+import seedu.taskell.MainApp;
/**
* A utility class to load UiParts from FXML files.
diff --git a/src/main/resources/images/address_book_32.png b/src/main/resources/images/task_manager_32.png
similarity index 100%
rename from src/main/resources/images/address_book_32.png
rename to src/main/resources/images/task_manager_32.png
diff --git a/src/main/resources/view/CommandBox.fxml b/src/main/resources/view/CommandBox.fxml
index 575de420b994..330fca331809 100644
--- a/src/main/resources/view/CommandBox.fxml
+++ b/src/main/resources/view/CommandBox.fxml
@@ -3,7 +3,7 @@
+ fx:controller="seedu.taskell.ui.CommandBox" stylesheets="@TaskellCyanTheme.css">
diff --git a/src/main/resources/view/HelpWindow.fxml b/src/main/resources/view/HelpWindow.fxml
index c4cbd84cac28..80da7949614f 100644
--- a/src/main/resources/view/HelpWindow.fxml
+++ b/src/main/resources/view/HelpWindow.fxml
@@ -1,7 +1,7 @@
-
+
diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml
index 2f9235c621d8..675fcb826cc1 100644
--- a/src/main/resources/view/MainWindow.fxml
+++ b/src/main/resources/view/MainWindow.fxml
@@ -4,9 +4,9 @@
-
+
-
+
@@ -14,7 +14,7 @@
-
+
-
+
-
+
-
+
diff --git a/src/main/resources/view/ResultDisplay.fxml b/src/main/resources/view/ResultDisplay.fxml
index cc650d739e22..e876cb30e219 100644
--- a/src/main/resources/view/ResultDisplay.fxml
+++ b/src/main/resources/view/ResultDisplay.fxml
@@ -3,9 +3,9 @@
+ fx:controller="seedu.taskell.ui.ResultDisplay">
-
+
diff --git a/src/main/resources/view/StatusBarFooter.fxml b/src/main/resources/view/StatusBarFooter.fxml
index 2656558b6eb7..a3457bdff384 100644
--- a/src/main/resources/view/StatusBarFooter.fxml
+++ b/src/main/resources/view/StatusBarFooter.fxml
@@ -1,7 +1,7 @@
-
+
diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/TaskListCard.fxml
similarity index 70%
rename from src/main/resources/view/PersonListCard.fxml
rename to src/main/resources/view/TaskListCard.fxml
index 13d4b149651b..404487781c27 100644
--- a/src/main/resources/view/PersonListCard.fxml
+++ b/src/main/resources/view/TaskListCard.fxml
@@ -14,7 +14,7 @@