diff --git a/ImportInvalid.txt b/ImportInvalid.txt
new file mode 100644
index 000000000000..bb8e09141c7b
--- /dev/null
+++ b/ImportInvalid.txt
@@ -0,0 +1,19 @@
+John Doe
+98765432
+johnd@example.com
+311, Clementi Ave 2, #02-25
+owesMoney
+friends
+
+Alex Neo
+87438807
+alexyeoh@exampple.com
+Blk 30 Geylang Street 29, #06-40
+family
+
+Berinice Yu
+99272758
+berniceyu@example.com
+Blk 30 Lorong 3 Serangoon Gardens, #07-18
+colleagues
+friends
diff --git a/ImportValid.xml b/ImportValid.xml
new file mode 100644
index 000000000000..ddfe79175abb
--- /dev/null
+++ b/ImportValid.xml
@@ -0,0 +1,30 @@
+
+
+
+ John Doe
+ 98765432
+ johnd@example.com
+ 311, Clementi Ave 2, #02-25
+ owesMoney
+ friends
+
+
+ Alex Neo
+ 87438807
+ alexyeoh@exampple.com
+ Blk 30 Geylang Street 29, #06-40
+ family
+
+
+ Berinice Yu
+ 99272758
+ berniceyu@example.com
+ Blk 30 Lorong 3 Serangoon Gardens, #07-18
+ colleagues
+ friends
+
+ owesMoney
+ friends
+ family
+ colleagues
+
diff --git a/README.adoc b/README.adoc
index 03eff3a4d191..05ecce57eb43 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,9 +1,9 @@
-= Address Book (Level 4)
+= Your TA
ifdef::env-github,env-browser[:relfileprefix: docs/]
-https://travis-ci.org/se-edu/addressbook-level4[image:https://travis-ci.org/se-edu/addressbook-level4.svg?branch=master[Build Status]]
+https://travis-ci.org/CS2103JAN2018-F09-B1/main[image:https://travis-ci.org/CS2103JAN2018-F09-B1/main.svg?branch=master[Build Status]]
https://ci.appveyor.com/project/damithc/addressbook-level4[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]]
-https://coveralls.io/github/se-edu/addressbook-level4?branch=master[image:https://coveralls.io/repos/github/se-edu/addressbook-level4/badge.svg?branch=master[Coverage Status]]
+https://coveralls.io/github/CS2103JAN2018-F09-B1/main?branch=master[image:https://coveralls.io/repos/github/CS2103JAN2018-F09-B1/main/badge.svg?branch=master[Coverage Status]]
https://www.codacy.com/app/damith/addressbook-level4?utm_source=github.com&utm_medium=referral&utm_content=se-edu/addressbook-level4&utm_campaign=Badge_Grade[image:https://api.codacy.com/project/badge/Grade/fc0b7775cf7f4fdeaf08776f3d8e364a[Codacy Badge]]
https://gitter.im/se-edu/Lobby[image:https://badges.gitter.im/se-edu/Lobby.svg[Gitter chat]]
@@ -15,13 +15,10 @@ ifndef::env-github[]
image::images/Ui.png[width="600"]
endif::[]
-* This is a desktop Address Book application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface).
+* This is a desktop "Your TA" application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface).
+* It is an address book cum scheduler targeted at making tracking students for NUS lecturer's easier.
* It is a Java sample application intended for students learning Software Engineering while using Java as the main programming language.
* It is *written in OOP fashion*. It provides a *reasonably well-written* code example that is *significantly bigger* (around 6 KLoC)than what students usually write in beginner-level SE modules.
-* What's different from https://github.com/se-edu/addressbook-level3[level 3]:
-** A more sophisticated GUI that includes a list panel and an in-built Browser.
-** More test cases, including automated GUI testing.
-** Support for _Build Automation_ using Gradle and for _Continuous Integration_ using Travis CI.
== Site Map
@@ -33,6 +30,7 @@ endif::[]
== Acknowledgements
+* This application was adapted from https://github.com/nus-cs2103-AY1718S2/addressbook-level4[AddressBook Level-4]
* Some parts of this sample application were inspired by the excellent http://code.makery.ch/library/javafx-8-tutorial/[Java FX tutorial] by
_Marco Jakob_.
* Libraries used: https://github.com/TomasMikula/EasyBind[EasyBind], https://github.com/TestFX/TestFX[TextFX], https://bitbucket.org/controlsfx/controlsfx/[ControlsFX], https://github.com/FasterXML/jackson[Jackson], https://github.com/google/guava[Guava], https://github.com/junit-team/junit4[JUnit4]
diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc
index 0f0a8e7ab51e..d75ac2380077 100644
--- a/docs/AboutUs.adoc
+++ b/docs/AboutUs.adoc
@@ -3,53 +3,42 @@
:imagesDir: images
:stylesDir: stylesheets
-AddressBook - Level 4 was developed by the https://se-edu.github.io/docs/Team.html[se-edu] team. +
-_{The dummy content given below serves as a placeholder to be used by future forks of the project.}_ +
-{empty} +
+Your TA was developed by the https://github.com/CS2103JAN2018-F09-B1[F09-B1] team. +
+
We are a team based in the http://www.comp.nus.edu.sg[School of Computing, National University of Singapore].
== Project Team
-=== John Doe
-image::damithc.jpg[width="150", align="left"]
-{empty}[http://www.comp.nus.edu.sg/~damithch[homepage]] [https://github.com/damithc[github]] [<>]
-
-Role: Project Advisor
-
-'''
-
-=== John Roe
-image::lejolly.jpg[width="150", align="left"]
-{empty}[http://github.com/lejolly[github]] [<>]
+=== Wu Di
+image::wudi.jpg[width="150", align="left"]
+{empty}[https://github.com/WoodySIN[github]]
-Role: Team Lead +
-Responsibilities: UI
+Role: Developer +
+Responsibilities: Logic
'''
-
-=== Johnny Doe
-image::yijinl.jpg[width="150", align="left"]
-{empty}[http://github.com/yijinl[github]] [<>]
-
+=== Daniel Tan
+image::joonkai1995.png[width="150", align="left"]
+{empty}[http://github.com/JoonKai1995[github]]
Role: Developer +
-Responsibilities: Data
+Responsibilities: UI
'''
-=== Johnny Roe
-image::m133225.jpg[width="150", align="left"]
-{empty}[http://github.com/m133225[github]] [<>]
+=== Pearlissa Taim
+image::pearlissa.png[width="150", align="left"]
+{empty}[http://github.com/Pearlissa[github]]
Role: Developer +
-Responsibilities: Dev Ops + Threading
+Responsibilities: Model
'''
-=== Benson Meier
-image::yl_coder.jpg[width="150", align="left"]
-{empty}[http://github.com/yl-coder[github]] [<>]
+=== Ellery Chia
+image::ellery.jpg[width="150", align="left"]
+{empty}[http://github.com/Alaru[github]]
Role: Developer +
-Responsibilities: UI
+Responsibilities: Storage
'''
diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc
index 1733af113b29..2bfa9b58e827 100644
--- a/docs/DeveloperGuide.adoc
+++ b/docs/DeveloperGuide.adoc
@@ -1,4 +1,4 @@
-= AddressBook Level 4 - Developer Guide
+= Your TA - Developer Guide
:toc:
:toc-title:
:toc-placement: preamble
@@ -10,9 +10,9 @@ ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
endif::[]
-:repoURL: https://github.com/se-edu/addressbook-level4/tree/master
+:repoURL: https://github.com/CS2103JAN2018-F09-B1/main/tree/master
-By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT`
+By: `F09-B1` Since: `Jun 2016` Licence: `MIT`
== Setting up
@@ -169,6 +169,7 @@ 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.
+* Default tags have background colours to identify them as of v1.2.
[[Design-Logic]]
=== Logic component
@@ -196,6 +197,7 @@ image::DeletePersonSdForLogic.png[width="800"]
[[Design-Model]]
=== Model component
+(needs new image here that includes MatriculationNumber in person)
.Structure of the Model Component
image::ModelClassDiagram.png[width="800"]
@@ -203,10 +205,15 @@ image::ModelClassDiagram.png[width="800"]
The `Model`,
-* stores a `UserPref` object that represents the user's preferences.
-* stores the Address Book data.
-* exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
-* does not depend on any of the other three components.
+* Stores a `UserPref` object that represents the user's preferences.
+* Stores the Address Book data.
+* Exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
+* Does not depend on any of the other three components.
+
+The `Person` Class,
+
+* Stores the information of a specific person(student) in the AddressBook
+* Information includes: Name, Matriculation Number, Phone Number, Email, Address and different tags to associate with that person.
[[Design-Storage]]
=== Storage component
@@ -230,6 +237,13 @@ Classes used by multiple components are in the `seedu.addressbook.commons` packa
This section describes some noteworthy details on how certain features are implemented.
+=== Help feature
+==== Current Implementation
+
+The help command displays a list of all the possible commands the user can make, followed by an example on its use.
+
+[This section is to be expanded when the help command is reworked into the help window.]
+
// tag::undoredo[]
=== Undo/Redo feature
==== Current Implementation
@@ -780,15 +794,87 @@ See this https://github.com/se-edu/addressbook-level4/pull/599[PR] for the step-
[appendix]
== Product Scope
-*Target user profile*:
+*Target user profile*: Tech-Savvy University Teachers/Tutors
-* has a need to manage a significant number of contacts
+* have the need to manage a significant number of contacts
* prefer desktop apps over other types
* can type fast
-* prefers typing over mouse input
-* is reasonably comfortable using CLI apps
+* prefer typing over mouse input
+* are reasonably comfortable using CLI apps
+
+*Value proposition*: manage contacts faster than a typical mouse/GUI driven app, includes to-do
+ list features (with prioritization, etc.) and scheduling (with calendar and reminders)
+
+=== Feature contribution
+
+*Wu Di*
+
+* *Major*: Implement the todo list
+
+** Support adding, editing and deleting of tasks
+** Works with undo/redo functions
+
+This enables the tutor to view all tasks in one glance so that he/she is able to stay organized and productive.
+
+* *Minor*: Import feature to migrate data from an external file
+
+** Imports data anywhere in any OS
+
+This helps the tutor work on different devices with the unique data set.
+
+* *Minor*: add the alias feature to some of the commands
+
+** Support majority of commands
+
+This helps the tutor remember the commands intuitively and type them more efficiently.
+
+*Daniel*
+
+* *Major*: Calendar and Scheduler for user
+
+** Supports adding of new tasks that will be slotted into the calendar(if it has a deadline)
+** Also assigns a priority value to each task based on parameters keyed in when task is added
+
+This helps the tutor to keep track of what needs to be done and which task to focus on.
+
+* *Minor*: Person has new parameter - Matriculation number
+
+** Person now stores matriculation number of the person
+** Add command supports adding person with matriculation number(compulsory parameter)
+** Find command supports search by matriculation number
+
+This helps the tutor to easily search for a certain student by their unique matriculation number instead of just
+their names (e.g. easier than searching for a common name such as Daniel).
+
+*Pearlissa*
+
+* *Major*: Login feature
+
+** Implements new User package
+** [Not confirmed] Encryption of data files containing usernames and passwords
+
+This allows multiple tutors to store their data in separate accounts, which can only be accessed by them.
-*Value proposition*: manage contacts faster than a typical mouse/GUI driven app
+* *Minor*: Sorting of contacts based on selected parameters
+
+** Any number of parameters (at least 1), and in order of priority
+
+This allows tutors to be better able to go through their lists of students.
+
+*Ellery*
+
+* *Major*: Display picture for all students entered
+
+** Support adding, editing and deleting of picture
+** Also works with the redo/undo function
+
+This helps the tutor keep track of his students, and be able to easily remember them better.
+
+* *Minor*: Email feature to email students
+
+** Email multiple students quickly
+
+This helps the tutor to quickly bring up an email client to send an email to a student.
[appendix]
== User Stories
@@ -800,15 +886,41 @@ 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 |
+|`* * *` |new user |get error messages/prompts |better adapt to commands to use them properly
+
+|`* * *` |user |add a new person |better manage all my contacts at one go
|`* * *` |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 |find a person by matriculation number/email |identify people easily
+
+|`* * *` |user |sort contacts based on name/address/email/tags |work with specific groups of people
+
+|`* * *` |user |assign a to-do list to each person in address book |know what I need to do for them
+
+|`* * *` |user |add individual items to the to-do lists |update additional tasks
+
+|`* * *` |user |remove entire to-do lists or items in it |remove completed tasks
+
+|`* * *` |user |add events to the schedule |better manage work/students
+
+|`* * *` |user |add a deadline to tasks/items |know what needs to be done and by when
+
+|`* * *` |user |prioritize tasks/items |efficiently get tasks/items done on time
+
|`* *` |user |hide <> by default |minimize chance of someone else seeing them by accident
-|`*` |user with many persons in the address book |sort persons by name |locate a person easily
+|`* *` |user |import students/people from a text file |it is easier to enter large numbers of people
+
+|`* *` |user |add profile pictures |know who the people I am working with are
+
+|`* *` |user |mass email students/people based on a tag |easily email/inform a class of students of announcements
+
+|`* *` |user |set reminders for certain events |have an email sent to me before the actual event so that I don't forget
+
+|`*` |user with many persons in the address book |combine groups/tags |better work with people who have similar interests/work
|=======================================================================
_{More to be added}_
@@ -819,14 +931,14 @@ _{More to be added}_
(For all use cases below, the *System* is the `AddressBook` and the *Actor* is the `user`, unless specified otherwise)
[discrete]
-=== Use case: Delete person
+=== Use case: Delete student
*MSS*
-1. User requests to list persons
-2. AddressBook shows a list of persons
-3. User requests to delete a specific person in the list
-4. AddressBook deletes the person
+1. User requests to list students
+2. AddressBook shows a list of students
+3. User requests to delete a specific student in the list
+4. AddressBook deletes the student and all related entries (if any)
+
Use case ends.
@@ -844,6 +956,84 @@ Use case ends.
+
Use case resumes at step 2.
+[discrete]
+=== Use case: Find a student by name
+
+*MSS*
+
+1. User requests to find a student by name
+2. AddressBook shows a list of students that match the search query
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 2a. The list is empty.
++
+Use case ends.
+
+[discrete]
+=== Use case: Add event to schedule
+
+*MSS*
+
+1. User requests to add an event to a day
+2. AddressBook shows the current schedule for the day
+3. User requests to add the event to a timeslot for that day
+4. AddressBook confirms the addition to the timeslot
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 2a. The schedule for the day is full.
++
+[none]
+** 2a1. AddressBook will display an error message.
++
+Use case ends.
+* 3a. User tries to add it to a non-empty timeslot
+[none]
+** 3a1. AddressBook will display an error message.
++
+Use case resumes at step 2.
+
+[discrete]
+=== Use case: Edit lesson for a student
+
+*MSS*
+
+1. User requests to edit lesson for a student.
+2. AddressBook shows the current lessons for a student in a list.
+3. User enters the index of lesson to edit.
+4. AddressBook prompts the user to enter the new entry.
+5. User inputs the new entry.
+6. AddressBook confirms with user on the edit.
+7. User confirms.
+8. AddressBook replaces the old entry with the new entry.
++
+Use case ends.
+
+*Extensions*
+
+[none]
+* 2a. There are no lessons for the student.
++
+Use case ends.
+* 3a. User enters an invalid index
+[none]
+** 3a1. AddressBook will display an error message.
++
+Use case resumes at step 3.
+
+* 5a. User does not enter a valid lesson entry
+[none]
+** 5a1. AddressBook will display an error message.
++
+User case resumes at step 5.
+
_{More to be added}_
[appendix]
@@ -852,6 +1042,11 @@ _{More to be added}_
. Should work on any <> as long as it has Java `1.8.0_60` or higher installed.
. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
+. Should be intuitive or easily understood after reading the User Guide.
+. Should not exceed the size of 100 MB.
+. Should respond to any requests within 3 seconds.
+. Should not modify and copy any user's personal data on the computer.
+. A User's data should be password protected.
_{More to be added}_
@@ -864,6 +1059,43 @@ Windows, Linux, Unix, OS-X
[[private-contact-detail]] Private contact detail::
A contact detail that is not meant to be shared with others
+[[ui]] User interface::
+The visible interface that the user will be seeing when using the application
+
+[[logic]] Logic::
+The set of commands that can be executed by the application
+
+[[model]] Model::
+The internal memory used when application is running
+
+[[storage]] Storage::
+The set of instructions to store specific states and data of the application when application is not running so that it
+can be loaded back into the application when application is started again.
+
+[[feature]] Feature::
+A specific function of the program
+
+[[parser]] Parser::
+A converting function or class that takes in raw input and separates it into its usable components for other methods
+
+[[tasks]] Tasks::
+A command to be executed
+
+[[deadline]] Deadline::
+The date for which certain tasks are due to be done
+
+[[tags]] Tags::
+Keywords tied to categories og people
+
+[[to-do-list]]To-do list::
+A list of things to do
+
+[[import]] Import::
+Bring into the application from an external source
+
+User -
+ Developer -
+
[appendix]
== Product Survey
diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc
index 74248917e438..eb8bb6d5cac8 100644
--- a/docs/UserGuide.adoc
+++ b/docs/UserGuide.adoc
@@ -1,4 +1,4 @@
-= AddressBook Level 4 - User Guide
+= Your TA - User Guide
:toc:
:toc-title:
:toc-placement: preamble
@@ -11,9 +11,9 @@ ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
endif::[]
-:repoURL: https://github.com/se-edu/addressbook-level4
+:repoURL: https://github.com/CS2103JAN2018-F09-B1/main
-By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT`
+By: `F09-B1` Since: `Jun 2016` Licence: `MIT`
== Introduction
@@ -34,7 +34,7 @@ This app will not work with earlier versions of Java 8.
image::Ui.png[width="790"]
+
. Type the command in the command box and press kbd:[Enter] to execute it. +
-e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
+e.g. typing *`help`* and pressing kbd:[Enter] will list all possible commands and their formats.
. Some example commands you can try:
* *`list`* : lists all contacts
@@ -50,6 +50,7 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
====
*Command Format*
+* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe'
* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
* Items in square brackets are optional e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
* Items with `…` after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
@@ -58,30 +59,37 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
=== Viewing help : `help`
+Alias: `?` +
Format: `help`
=== Adding a person: `add`
Adds a person to the address book +
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...`
+Alias: `a` and `+` +
+Format: `add n/NAME m/MATRICULATION NUMBER p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...`
[TIP]
A person can have any number of tags (including 0)
+[NOTE]
+The tags "lecturer", "TA" "student" and "T1" will appear red, yellow, blue and green respectively.
+
Examples:
-* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
-* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+* `add n/John Doe m/A0111111X p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
+* `add n/Betsy Crowe t/friend m/A1234567C e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
=== Listing all persons : `list`
Shows a list of all persons in the address book. +
+Alias: `ls` +
Format: `list`
=== Editing a person : `edit`
Edits an existing person in the address book. +
-Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...`
+Alias: `e` +
+Format: `edit INDEX [n/NAME] [m/MATRICULATION NUMBER] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...`
****
* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ...
@@ -98,15 +106,40 @@ Edits the phone number and email address of the 1st person to be `91234567` and
* `edit 2 n/Betsy Crower t/` +
Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
+=== Emailing a person : `email`
+
+Email a person in the address book. This uses your default mail app to email. +
+Format: `email INDEX`
+
+****
+* Emails 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` +
+`email 2` +
+Emails the 2nd person in the address book.
+* `find Betsy` +
+`email 1` +
+Emails the 1st person in the results of the `find` command.
+
=== Locating persons by name: `find`
+=== Locating persons by name or by matriculation number: `find`
+
Finds persons whose names contain any of the given keywords. +
+Or, finds a person whose matriculation number corresponds to the given keyword. +
+
+Alias: `f` +
Format: `find KEYWORD [MORE_KEYWORDS]`
****
* The search is case insensitive. e.g `hans` will match `Hans`
* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
-* Only the name is searched.
+* Only the name and the matriculation number is searched.
* Only full words will be matched e.g. `Han` will not match `Hans`
* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
****
@@ -114,13 +147,16 @@ Format: `find KEYWORD [MORE_KEYWORDS]`
Examples:
* `find John` +
-Returns `john` and `John Doe`
+Returns `john` and `John Doe`.
* `find Betsy Tim John` +
-Returns any person having names `Betsy`, `Tim`, or `John`
+Returns any person having names `Betsy`, `Tim`, or `John`.
+* `find A0123456X` +
+Returns any person having the matriculation number A0123456X.
=== Deleting a person : `delete`
Deletes the specified person from the address book. +
+Alias: `d` and `-` +
Format: `delete INDEX`
****
@@ -141,6 +177,7 @@ Deletes the 1st person in the results of the `find` command.
=== Selecting a person : `select`
Selects the person identified by the index number used in the last person listing. +
+Alias: `s` +
Format: `select INDEX`
****
@@ -161,6 +198,7 @@ Selects the 1st person in the results of the `find` command.
=== Listing entered commands : `history`
Lists all the commands that you have entered in reverse chronological order. +
+Alias: `h` +
Format: `history`
[NOTE]
@@ -172,6 +210,7 @@ Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and
=== Undoing previous command : `undo`
Restores the address book to the state before the previous _undoable_ command was executed. +
+Alias: `u` +
Format: `undo`
[NOTE]
@@ -198,6 +237,7 @@ The `undo` command fails as there are no undoable commands executed previously.
=== Redoing the previously undone command : `redo`
Reverses the most recent `undo` command. +
+Alias: `r` +
Format: `redo`
Examples:
@@ -221,8 +261,25 @@ The `redo` command fails as there are no `undo` commands executed previously.
=== Clearing all entries : `clear`
Clears all entries from the address book. +
+Alias: `c` +
Format: `clear`
+=== Importing data from another file : `import`
+
+Extracting data from an xml formatted file and
+replaces the current stored data. +
+Format: `import FILEPATH`
+
+Examples:
+
+* `import ~/download/NewData.xml`
+
+=== Sorting all entries : `sort` `[coming in v2.0]`
+
+Sorts all entries from the address book in alphebatical order based on name. +
+Alias: `s` +
+Format: `sort`
+
=== Exiting the program : `exit`
Exits the program. +
diff --git a/docs/UserGuide_BACKUP_9900.adoc b/docs/UserGuide_BACKUP_9900.adoc
new file mode 100644
index 000000000000..710d4ab3607e
--- /dev/null
+++ b/docs/UserGuide_BACKUP_9900.adoc
@@ -0,0 +1,292 @@
+= Your TA - User Guide
+:toc:
+:toc-title:
+:toc-placement: preamble
+:sectnums:
+:imagesDir: images
+:stylesDir: stylesheets
+:xrefstyle: full
+:experimental:
+ifdef::env-github[]
+:tip-caption: :bulb:
+:note-caption: :information_source:
+endif::[]
+:repoURL: https://github.com/CS2103JAN2018-F09-B1/main
+
+By: `F09-B1` Since: `Jun 2016` Licence: `MIT`
+
+== Introduction
+
+AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy!
+
+== Quick Start
+
+. Ensure you have Java version `1.8.0_60` or later installed in your Computer.
++
+[NOTE]
+Having any Java 8 version is not enough. +
+This app will not work with earlier versions of Java 8.
++
+. Download the latest `addressbook.jar` link:{repoURL}/releases[here].
+. Copy the file to the folder you want to use as the home folder for your Address Book.
+. Double-click the file to start the app. The GUI should appear in a few seconds.
++
+image::Ui.png[width="790"]
++
+. Type the command in the command box and press kbd:[Enter] to execute it. +
+e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
+. Some example commands you can try:
+
+* *`list`* : lists all contacts
+* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book.
+* **`delete`**`3` : deletes the 3rd contact shown in the current list
+* *`exit`* : exits the app
+
+. Refer to <> for details of each command.
+
+[[Features]]
+== Features
+
+====
+*Command Format*
+
+* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe'
+* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
+* Items in square brackets are optional e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
+* Items with `…` after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
+* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
+====
+
+=== Viewing help : `help`
+
+Alias: `?` +
+Format: `help`
+
+=== Adding a person: `add`
+
+Adds a person to the address book +
+Alias: `a` and `+` +
+Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...`
+
+[TIP]
+A person can have any number of tags (including 0)
+
+Examples:
+
+* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
+* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+
+=== Listing all persons : `list`
+
+Shows a list of all persons in the address book. +
+Alias: `ls` +
+Format: `list`
+
+=== Editing a person : `edit`
+
+Edits an existing person in the address book. +
+Alias: `e` +
+Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...`
+
+****
+* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ...
+* At least one of the optional fields must be provided.
+* Existing values will be updated to the input values.
+* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
+* You can remove all the person's tags by typing `t/` without specifying any tags after it.
+****
+
+Examples:
+
+* `edit 1 p/91234567 e/johndoe@example.com` +
+Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
+* `edit 2 n/Betsy Crower t/` +
+Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
+
+=== Locating persons by name: `find`
+
+Finds persons whose names contain any of the given keywords. +
+Alias: `f` +
+Format: `find KEYWORD [MORE_KEYWORDS]`
+
+****
+* The search is case insensitive. e.g `hans` will match `Hans`
+* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
+* Only the name is searched.
+* Only full words will be matched e.g. `Han` will not match `Hans`
+* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+****
+
+Examples:
+
+* `find John` +
+Returns `john` and `John Doe`
+* `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. +
+Alias: `d` and `-` +
+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.
+
+=== Selecting a person : `select`
+
+Selects the person identified by the index number used in the last person listing. +
+Alias: `s` +
+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.
+
+=== Listing entered commands : `history`
+
+Lists all the commands that you have entered in reverse chronological order. +
+Alias: `h` +
+Format: `history`
+
+[NOTE]
+====
+Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and next input respectively in the command box.
+====
+
+// tag::undoredo[]
+=== Undoing previous command : `undo`
+
+Restores the address book to the state before the previous _undoable_ command was executed. +
+Alias: `u` +
+Format: `undo`
+
+[NOTE]
+====
+Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`).
+====
+
+Examples:
+
+* `delete 1` +
+`list` +
+`undo` (reverses the `delete 1` command) +
+
+* `select 1` +
+`list` +
+`undo` +
+The `undo` command fails as there are no undoable commands executed previously.
+
+* `delete 1` +
+`clear` +
+`undo` (reverses the `clear` command) +
+`undo` (reverses the `delete 1` command) +
+
+=== Redoing the previously undone command : `redo`
+
+Reverses the most recent `undo` command. +
+Alias: `r` +
+Format: `redo`
+
+Examples:
+
+* `delete 1` +
+`undo` (reverses the `delete 1` command) +
+`redo` (reapplies the `delete 1` command) +
+
+* `delete 1` +
+`redo` +
+The `redo` command fails as there are no `undo` commands executed previously.
+
+* `delete 1` +
+`clear` +
+`undo` (reverses the `clear` command) +
+`undo` (reverses the `delete 1` command) +
+`redo` (reapplies the `delete 1` command) +
+`redo` (reapplies the `clear` command) +
+// end::undoredo[]
+
+=== Clearing all entries : `clear`
+
+Clears all entries from the address book. +
+Alias: `c` +
+Format: `clear`
+
+=== Importing data from another file : `import`
+
+Extracting data from an xml formatted file and
+replaces the current stored data. +
+Format: `import FILEPATH`
+
+Examples:
+
+* `import ~/download/NewData.xml`
+
+=== Sorting all entries : `sort` `[coming in v2.0]`
+
+Sorts all entries from the address book in alphebatical order based on name. +
+Alias: `s` +
+Format: `sort`
+
+=== 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.
+
+// tag::dataencryption[]
+=== Encrypting data files `[coming in v2.0]`
+
+_{explain how the user can enable/disable data encryption}_
+// end::dataencryption[]
+
+== 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.
+
+== Command Summary
+
+* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +
+e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
+* *Clear* : `clear`
+* *Delete* : `delete INDEX` +
+e.g. `delete 3`
+* *Edit* : `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +
+e.g. `edit 2 n/James Lee e/jameslee@example.com`
+* *Find* : `find KEYWORD [MORE_KEYWORDS]` +
+e.g. `find James Jake`
+* *List* : `list`
+* *Help* : `help`
+* *Select* : `select INDEX` +
+e.g.`select 2`
+* *History* : `history`
+* *Undo* : `undo`
+* *Redo* : `redo`
diff --git a/docs/UserGuide_BASE_9900.adoc b/docs/UserGuide_BASE_9900.adoc
new file mode 100644
index 000000000000..0b497b2880b2
--- /dev/null
+++ b/docs/UserGuide_BASE_9900.adoc
@@ -0,0 +1,276 @@
+= Your TA - User Guide
+:toc:
+:toc-title:
+:toc-placement: preamble
+:sectnums:
+:imagesDir: images
+:stylesDir: stylesheets
+:xrefstyle: full
+:experimental:
+ifdef::env-github[]
+:tip-caption: :bulb:
+:note-caption: :information_source:
+endif::[]
+:repoURL: https://github.com/CS2103JAN2018-F09-B1/main
+
+By: `F09-B1` Since: `Jun 2016` Licence: `MIT`
+
+== Introduction
+
+AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy!
+
+== Quick Start
+
+. Ensure you have Java version `1.8.0_60` or later installed in your Computer.
++
+[NOTE]
+Having any Java 8 version is not enough. +
+This app will not work with earlier versions of Java 8.
++
+. Download the latest `addressbook.jar` link:{repoURL}/releases[here].
+. Copy the file to the folder you want to use as the home folder for your Address Book.
+. Double-click the file to start the app. The GUI should appear in a few seconds.
++
+image::Ui.png[width="790"]
++
+. Type the command in the command box and press kbd:[Enter] to execute it. +
+e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
+. Some example commands you can try:
+
+* *`list`* : lists all contacts
+* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book.
+* **`delete`**`3` : deletes the 3rd contact shown in the current list
+* *`exit`* : exits the app
+
+. Refer to <> for details of each command.
+
+[[Features]]
+== Features
+
+====
+*Command Format*
+
+* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe'
+* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
+* Items in square brackets are optional e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
+* Items with `…` after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
+* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
+====
+
+=== Viewing help : `help`
+
+Alias: `?` +
+Format: `help`
+
+=== Adding a person: `add`
+
+Adds a person to the address book +
+Alias: `a` and `+` +
+Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...`
+
+[TIP]
+A person can have any number of tags (including 0)
+
+Examples:
+
+* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
+* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+
+=== Listing all persons : `list`
+
+Shows a list of all persons in the address book. +
+Alias: `ls` +
+Format: `list`
+
+=== Editing a person : `edit`
+
+Edits an existing person in the address book. +
+Alias: `e` +
+Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...`
+
+****
+* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ...
+* At least one of the optional fields must be provided.
+* Existing values will be updated to the input values.
+* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
+* You can remove all the person's tags by typing `t/` without specifying any tags after it.
+****
+
+Examples:
+
+* `edit 1 p/91234567 e/johndoe@example.com` +
+Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
+* `edit 2 n/Betsy Crower t/` +
+Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
+
+=== Locating persons by name: `find`
+
+Finds persons whose names contain any of the given keywords. +
+Alias: `f` +
+Format: `find KEYWORD [MORE_KEYWORDS]`
+
+****
+* The search is case insensitive. e.g `hans` will match `Hans`
+* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
+* Only the name is searched.
+* Only full words will be matched e.g. `Han` will not match `Hans`
+* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+****
+
+Examples:
+
+* `find John` +
+Returns `john` and `John Doe`
+* `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. +
+Alias: `d` and `-` +
+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.
+
+=== Selecting a person : `select`
+
+Selects the person identified by the index number used in the last person listing. +
+Alias: `s` +
+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.
+
+=== Listing entered commands : `history`
+
+Lists all the commands that you have entered in reverse chronological order. +
+Alias: `h` +
+Format: `history`
+
+[NOTE]
+====
+Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and next input respectively in the command box.
+====
+
+// tag::undoredo[]
+=== Undoing previous command : `undo`
+
+Restores the address book to the state before the previous _undoable_ command was executed. +
+Alias: `u` +
+Format: `undo`
+
+[NOTE]
+====
+Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`).
+====
+
+Examples:
+
+* `delete 1` +
+`list` +
+`undo` (reverses the `delete 1` command) +
+
+* `select 1` +
+`list` +
+`undo` +
+The `undo` command fails as there are no undoable commands executed previously.
+
+* `delete 1` +
+`clear` +
+`undo` (reverses the `clear` command) +
+`undo` (reverses the `delete 1` command) +
+
+=== Redoing the previously undone command : `redo`
+
+Reverses the most recent `undo` command. +
+Alias: `r` +
+Format: `redo`
+
+Examples:
+
+* `delete 1` +
+`undo` (reverses the `delete 1` command) +
+`redo` (reapplies the `delete 1` command) +
+
+* `delete 1` +
+`redo` +
+The `redo` command fails as there are no `undo` commands executed previously.
+
+* `delete 1` +
+`clear` +
+`undo` (reverses the `clear` command) +
+`undo` (reverses the `delete 1` command) +
+`redo` (reapplies the `delete 1` command) +
+`redo` (reapplies the `clear` command) +
+// end::undoredo[]
+
+=== Clearing all entries : `clear`
+
+Clears all entries from the address book. +
+Alias: `c` +
+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.
+
+// tag::dataencryption[]
+=== Encrypting data files `[coming in v2.0]`
+
+_{explain how the user can enable/disable data encryption}_
+// end::dataencryption[]
+
+== 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.
+
+== Command Summary
+
+* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +
+e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
+* *Clear* : `clear`
+* *Delete* : `delete INDEX` +
+e.g. `delete 3`
+* *Edit* : `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +
+e.g. `edit 2 n/James Lee e/jameslee@example.com`
+* *Find* : `find KEYWORD [MORE_KEYWORDS]` +
+e.g. `find James Jake`
+* *List* : `list`
+* *Help* : `help`
+* *Select* : `select INDEX` +
+e.g.`select 2`
+* *History* : `history`
+* *Undo* : `undo`
+* *Redo* : `redo`
diff --git a/docs/UserGuide_LOCAL_9900.adoc b/docs/UserGuide_LOCAL_9900.adoc
new file mode 100644
index 000000000000..710d4ab3607e
--- /dev/null
+++ b/docs/UserGuide_LOCAL_9900.adoc
@@ -0,0 +1,292 @@
+= Your TA - User Guide
+:toc:
+:toc-title:
+:toc-placement: preamble
+:sectnums:
+:imagesDir: images
+:stylesDir: stylesheets
+:xrefstyle: full
+:experimental:
+ifdef::env-github[]
+:tip-caption: :bulb:
+:note-caption: :information_source:
+endif::[]
+:repoURL: https://github.com/CS2103JAN2018-F09-B1/main
+
+By: `F09-B1` Since: `Jun 2016` Licence: `MIT`
+
+== Introduction
+
+AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy!
+
+== Quick Start
+
+. Ensure you have Java version `1.8.0_60` or later installed in your Computer.
++
+[NOTE]
+Having any Java 8 version is not enough. +
+This app will not work with earlier versions of Java 8.
++
+. Download the latest `addressbook.jar` link:{repoURL}/releases[here].
+. Copy the file to the folder you want to use as the home folder for your Address Book.
+. Double-click the file to start the app. The GUI should appear in a few seconds.
++
+image::Ui.png[width="790"]
++
+. Type the command in the command box and press kbd:[Enter] to execute it. +
+e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
+. Some example commands you can try:
+
+* *`list`* : lists all contacts
+* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book.
+* **`delete`**`3` : deletes the 3rd contact shown in the current list
+* *`exit`* : exits the app
+
+. Refer to <> for details of each command.
+
+[[Features]]
+== Features
+
+====
+*Command Format*
+
+* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe'
+* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
+* Items in square brackets are optional e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
+* Items with `…` after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
+* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
+====
+
+=== Viewing help : `help`
+
+Alias: `?` +
+Format: `help`
+
+=== Adding a person: `add`
+
+Adds a person to the address book +
+Alias: `a` and `+` +
+Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...`
+
+[TIP]
+A person can have any number of tags (including 0)
+
+Examples:
+
+* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
+* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+
+=== Listing all persons : `list`
+
+Shows a list of all persons in the address book. +
+Alias: `ls` +
+Format: `list`
+
+=== Editing a person : `edit`
+
+Edits an existing person in the address book. +
+Alias: `e` +
+Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...`
+
+****
+* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ...
+* At least one of the optional fields must be provided.
+* Existing values will be updated to the input values.
+* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
+* You can remove all the person's tags by typing `t/` without specifying any tags after it.
+****
+
+Examples:
+
+* `edit 1 p/91234567 e/johndoe@example.com` +
+Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
+* `edit 2 n/Betsy Crower t/` +
+Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
+
+=== Locating persons by name: `find`
+
+Finds persons whose names contain any of the given keywords. +
+Alias: `f` +
+Format: `find KEYWORD [MORE_KEYWORDS]`
+
+****
+* The search is case insensitive. e.g `hans` will match `Hans`
+* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
+* Only the name is searched.
+* Only full words will be matched e.g. `Han` will not match `Hans`
+* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+****
+
+Examples:
+
+* `find John` +
+Returns `john` and `John Doe`
+* `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. +
+Alias: `d` and `-` +
+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.
+
+=== Selecting a person : `select`
+
+Selects the person identified by the index number used in the last person listing. +
+Alias: `s` +
+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.
+
+=== Listing entered commands : `history`
+
+Lists all the commands that you have entered in reverse chronological order. +
+Alias: `h` +
+Format: `history`
+
+[NOTE]
+====
+Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and next input respectively in the command box.
+====
+
+// tag::undoredo[]
+=== Undoing previous command : `undo`
+
+Restores the address book to the state before the previous _undoable_ command was executed. +
+Alias: `u` +
+Format: `undo`
+
+[NOTE]
+====
+Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`).
+====
+
+Examples:
+
+* `delete 1` +
+`list` +
+`undo` (reverses the `delete 1` command) +
+
+* `select 1` +
+`list` +
+`undo` +
+The `undo` command fails as there are no undoable commands executed previously.
+
+* `delete 1` +
+`clear` +
+`undo` (reverses the `clear` command) +
+`undo` (reverses the `delete 1` command) +
+
+=== Redoing the previously undone command : `redo`
+
+Reverses the most recent `undo` command. +
+Alias: `r` +
+Format: `redo`
+
+Examples:
+
+* `delete 1` +
+`undo` (reverses the `delete 1` command) +
+`redo` (reapplies the `delete 1` command) +
+
+* `delete 1` +
+`redo` +
+The `redo` command fails as there are no `undo` commands executed previously.
+
+* `delete 1` +
+`clear` +
+`undo` (reverses the `clear` command) +
+`undo` (reverses the `delete 1` command) +
+`redo` (reapplies the `delete 1` command) +
+`redo` (reapplies the `clear` command) +
+// end::undoredo[]
+
+=== Clearing all entries : `clear`
+
+Clears all entries from the address book. +
+Alias: `c` +
+Format: `clear`
+
+=== Importing data from another file : `import`
+
+Extracting data from an xml formatted file and
+replaces the current stored data. +
+Format: `import FILEPATH`
+
+Examples:
+
+* `import ~/download/NewData.xml`
+
+=== Sorting all entries : `sort` `[coming in v2.0]`
+
+Sorts all entries from the address book in alphebatical order based on name. +
+Alias: `s` +
+Format: `sort`
+
+=== 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.
+
+// tag::dataencryption[]
+=== Encrypting data files `[coming in v2.0]`
+
+_{explain how the user can enable/disable data encryption}_
+// end::dataencryption[]
+
+== 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.
+
+== Command Summary
+
+* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +
+e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
+* *Clear* : `clear`
+* *Delete* : `delete INDEX` +
+e.g. `delete 3`
+* *Edit* : `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +
+e.g. `edit 2 n/James Lee e/jameslee@example.com`
+* *Find* : `find KEYWORD [MORE_KEYWORDS]` +
+e.g. `find James Jake`
+* *List* : `list`
+* *Help* : `help`
+* *Select* : `select INDEX` +
+e.g.`select 2`
+* *History* : `history`
+* *Undo* : `undo`
+* *Redo* : `redo`
diff --git a/docs/UserGuide_REMOTE_9900.adoc b/docs/UserGuide_REMOTE_9900.adoc
new file mode 100644
index 000000000000..330c23eabd67
--- /dev/null
+++ b/docs/UserGuide_REMOTE_9900.adoc
@@ -0,0 +1,282 @@
+= Your TA - User Guide
+:toc:
+:toc-title:
+:toc-placement: preamble
+:sectnums:
+:imagesDir: images
+:stylesDir: stylesheets
+:xrefstyle: full
+:experimental:
+ifdef::env-github[]
+:tip-caption: :bulb:
+:note-caption: :information_source:
+endif::[]
+:repoURL: https://github.com/CS2103JAN2018-F09-B1/main
+
+By: `F09-B1` Since: `Jun 2016` Licence: `MIT`
+
+== Introduction
+
+AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy!
+
+== Quick Start
+
+. Ensure you have Java version `1.8.0_60` or later installed in your Computer.
++
+[NOTE]
+Having any Java 8 version is not enough. +
+This app will not work with earlier versions of Java 8.
++
+. Download the latest `addressbook.jar` link:{repoURL}/releases[here].
+. Copy the file to the folder you want to use as the home folder for your Address Book.
+. Double-click the file to start the app. The GUI should appear in a few seconds.
++
+image::Ui.png[width="790"]
++
+. Type the command in the command box and press kbd:[Enter] to execute it. +
+e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
+. Some example commands you can try:
+
+* *`list`* : lists all contacts
+* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book.
+* **`delete`**`3` : deletes the 3rd contact shown in the current list
+* *`exit`* : exits the app
+
+. Refer to <> for details of each command.
+
+[[Features]]
+== Features
+
+====
+*Command Format*
+
+* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe'
+* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
+* Items in square brackets are optional e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
+* Items with `…` after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
+* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
+====
+
+=== Viewing help : `help`
+
+Alias: `?` +
+Format: `help`
+
+=== Adding a person: `add`
+
+Adds a person to the address book +
+Alias: `a` and `+` +
+Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...`
+
+[TIP]
+A person can have any number of tags (including 0)
+
+Examples:
+
+* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
+* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+
+=== Listing all persons : `list`
+
+Shows a list of all persons in the address book. +
+Alias: `ls` +
+Format: `list`
+
+=== Editing a person : `edit`
+
+Edits an existing person in the address book. +
+Alias: `e` +
+Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...`
+
+****
+* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ...
+* At least one of the optional fields must be provided.
+* Existing values will be updated to the input values.
+* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
+* You can remove all the person's tags by typing `t/` without specifying any tags after it.
+****
+
+Examples:
+
+* `edit 1 p/91234567 e/johndoe@example.com` +
+Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
+* `edit 2 n/Betsy Crower t/` +
+Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
+
+=== Locating persons by name: `find`
+
+Finds persons whose names contain any of the given keywords. +
+Alias: `f` +
+Format: `find KEYWORD [MORE_KEYWORDS]`
+
+****
+* The search is case insensitive. e.g `hans` will match `Hans`
+* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
+* Only the name is searched.
+* Only full words will be matched e.g. `Han` will not match `Hans`
+* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+****
+
+Examples:
+
+* `find John` +
+Returns `john` and `John Doe`
+* `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. +
+Alias: `d` and `-` +
+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.
+
+=== Selecting a person : `select`
+
+Selects the person identified by the index number used in the last person listing. +
+Alias: `s` +
+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.
+
+=== Listing entered commands : `history`
+
+Lists all the commands that you have entered in reverse chronological order. +
+Alias: `h` +
+Format: `history`
+
+[NOTE]
+====
+Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and next input respectively in the command box.
+====
+
+// tag::undoredo[]
+=== Undoing previous command : `undo`
+
+Restores the address book to the state before the previous _undoable_ command was executed. +
+Alias: `u` +
+Format: `undo`
+
+[NOTE]
+====
+Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`).
+====
+
+Examples:
+
+* `delete 1` +
+`list` +
+`undo` (reverses the `delete 1` command) +
+
+* `select 1` +
+`list` +
+`undo` +
+The `undo` command fails as there are no undoable commands executed previously.
+
+* `delete 1` +
+`clear` +
+`undo` (reverses the `clear` command) +
+`undo` (reverses the `delete 1` command) +
+
+=== Redoing the previously undone command : `redo`
+
+Reverses the most recent `undo` command. +
+Alias: `r` +
+Format: `redo`
+
+Examples:
+
+* `delete 1` +
+`undo` (reverses the `delete 1` command) +
+`redo` (reapplies the `delete 1` command) +
+
+* `delete 1` +
+`redo` +
+The `redo` command fails as there are no `undo` commands executed previously.
+
+* `delete 1` +
+`clear` +
+`undo` (reverses the `clear` command) +
+`undo` (reverses the `delete 1` command) +
+`redo` (reapplies the `delete 1` command) +
+`redo` (reapplies the `clear` command) +
+// end::undoredo[]
+
+=== Clearing all entries : `clear`
+
+Clears all entries from the address book. +
+Alias: `c` +
+Format: `clear`
+
+=== Sorting all entries : `sort` `[coming in v2.0]`
+
+Sorts all entries from the address book in alphebatical order based on name. +
+Alias: `s` +
+Format: `sort`
+
+=== 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.
+
+// tag::dataencryption[]
+=== Encrypting data files `[coming in v2.0]`
+
+_{explain how the user can enable/disable data encryption}_
+// end::dataencryption[]
+
+== 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.
+
+== Command Summary
+
+* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +
+e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
+* *Clear* : `clear`
+* *Delete* : `delete INDEX` +
+e.g. `delete 3`
+* *Edit* : `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +
+e.g. `edit 2 n/James Lee e/jameslee@example.com`
+* *Find* : `find KEYWORD [MORE_KEYWORDS]` +
+e.g. `find James Jake`
+* *List* : `list`
+* *Help* : `help`
+* *Select* : `select INDEX` +
+e.g.`select 2`
+* *History* : `history`
+* *Undo* : `undo`
+* *Redo* : `redo`
diff --git a/docs/images/Ui.png b/docs/images/Ui.png
index 5ec9c527b49c..87a54079d6c9 100644
Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ
diff --git a/docs/images/ellery.jpg b/docs/images/ellery.jpg
new file mode 100644
index 000000000000..e56268c6ee0b
Binary files /dev/null and b/docs/images/ellery.jpg differ
diff --git a/docs/images/joonkai1995.png b/docs/images/joonkai1995.png
new file mode 100644
index 000000000000..86f0e0570c76
Binary files /dev/null and b/docs/images/joonkai1995.png differ
diff --git a/docs/images/pearlissa.png b/docs/images/pearlissa.png
new file mode 100644
index 000000000000..d30ae556995f
Binary files /dev/null and b/docs/images/pearlissa.png differ
diff --git a/docs/images/wudi.jpg b/docs/images/wudi.jpg
new file mode 100644
index 000000000000..042ce7672a82
Binary files /dev/null and b/docs/images/wudi.jpg differ
diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java
index 1deb3a1e4695..5aefa9b91221 100644
--- a/src/main/java/seedu/address/commons/core/Messages.java
+++ b/src/main/java/seedu/address/commons/core/Messages.java
@@ -9,5 +9,7 @@ public class Messages {
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 MAIL_APP_ERROR = "Error opening the default mail app on this system";
+ public static final String UNSUPPORTED_DESKTOP = "The client does not support desktop operations on this system";
}
diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java
index c334710c0ea3..4d613f1d24a9 100644
--- a/src/main/java/seedu/address/logic/commands/AddCommand.java
+++ b/src/main/java/seedu/address/logic/commands/AddCommand.java
@@ -3,6 +3,7 @@
import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
@@ -17,16 +18,20 @@
public class AddCommand extends UndoableCommand {
public static final String COMMAND_WORD = "add";
+ public static final String COMMAND_ALIAS = "a";
+ public static final String COMMAND_SIGN = "+";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. "
+ "Parameters: "
+ PREFIX_NAME + "NAME "
+ + PREFIX_MATRIC_NUMBER + "MATRIC_NUMBER "
+ PREFIX_PHONE + "PHONE "
+ PREFIX_EMAIL + "EMAIL "
+ PREFIX_ADDRESS + "ADDRESS "
+ "[" + PREFIX_TAG + "TAG]...\n"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_NAME + "John Doe "
+ + PREFIX_MATRIC_NUMBER + "A1234567J"
+ PREFIX_PHONE + "98765432 "
+ PREFIX_EMAIL + "johnd@example.com "
+ PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 "
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java
index ceeb7ba913c6..6d04efaf3295 100644
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java
@@ -10,6 +10,7 @@
public class ClearCommand extends UndoableCommand {
public static final String COMMAND_WORD = "clear";
+ public static final String COMMAND_ALIAS = "c";
public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
index b539d240001a..cb66589a0934 100644
--- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java
+++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
@@ -17,6 +17,8 @@
public class DeleteCommand extends UndoableCommand {
public static final String COMMAND_WORD = "delete";
+ public static final String COMMAND_ALIAS = "d";
+ public static final String COMMAND_SIGN = "-";
public static final String MESSAGE_USAGE = COMMAND_WORD
+ ": Deletes the person identified by the index number used in the last person listing.\n"
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java
index e6c3a3e034bc..9f2af99da340 100644
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ b/src/main/java/seedu/address/logic/commands/EditCommand.java
@@ -3,6 +3,7 @@
import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
@@ -21,6 +22,7 @@
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
@@ -34,12 +36,14 @@
public class EditCommand extends UndoableCommand {
public static final String COMMAND_WORD = "edit";
+ public static final String COMMAND_ALIAS = "e";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified "
+ "by the index number used in the last person listing. "
+ "Existing values will be overwritten by the input values.\n"
+ "Parameters: INDEX (must be a positive integer) "
+ "[" + PREFIX_NAME + "NAME] "
+ + "[" + PREFIX_MATRIC_NUMBER + "MATRICULATION NUMBER] "
+ "[" + PREFIX_PHONE + "PHONE] "
+ "[" + PREFIX_EMAIL + "EMAIL] "
+ "[" + PREFIX_ADDRESS + "ADDRESS] "
@@ -103,12 +107,14 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript
assert personToEdit != null;
Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName());
+ MatriculationNumber updatedMatricNumber =
+ editPersonDescriptor.getMatricNumber().orElse(personToEdit.getMatricNumber());
Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone());
Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail());
Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress());
Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags());
- return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags);
+ return new Person(updatedName, updatedMatricNumber, updatedPhone, updatedEmail, updatedAddress, updatedTags);
}
@Override
@@ -136,6 +142,7 @@ public boolean equals(Object other) {
*/
public static class EditPersonDescriptor {
private Name name;
+ private MatriculationNumber matricNumber;
private Phone phone;
private Email email;
private Address address;
@@ -149,6 +156,7 @@ public EditPersonDescriptor() {}
*/
public EditPersonDescriptor(EditPersonDescriptor toCopy) {
setName(toCopy.name);
+ setMatricNumber(toCopy.matricNumber);
setPhone(toCopy.phone);
setEmail(toCopy.email);
setAddress(toCopy.address);
@@ -159,7 +167,8 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) {
* Returns true if at least one field is edited.
*/
public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(this.name, this.phone, this.email, this.address, this.tags);
+ return CollectionUtil.isAnyNonNull(this.name, this.matricNumber, this.phone, this.email,
+ this.address, this.tags);
}
public void setName(Name name) {
@@ -170,6 +179,14 @@ public Optional getName() {
return Optional.ofNullable(name);
}
+ public void setMatricNumber(MatriculationNumber matricNumber) {
+ this.matricNumber = matricNumber;
+ }
+
+ public Optional getMatricNumber() {
+ return Optional.ofNullable(matricNumber);
+ }
+
public void setPhone(Phone phone) {
this.phone = phone;
}
@@ -227,6 +244,7 @@ public boolean equals(Object other) {
EditPersonDescriptor e = (EditPersonDescriptor) other;
return getName().equals(e.getName())
+ && getMatricNumber().equals(e.getMatricNumber())
&& getPhone().equals(e.getPhone())
&& getEmail().equals(e.getEmail())
&& getAddress().equals(e.getAddress())
diff --git a/src/main/java/seedu/address/logic/commands/EmailCommand.java b/src/main/java/seedu/address/logic/commands/EmailCommand.java
new file mode 100644
index 000000000000..6247c8a17853
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/EmailCommand.java
@@ -0,0 +1,68 @@
+package seedu.address.logic.commands;
+
+import java.awt.Desktop;
+import java.awt.HeadlessException;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.logic.commands.exceptions.UnsupportDesktopException;
+import seedu.address.model.person.Person;
+
+/**
+ * Emails a person identified using it's last displayed index from the address book.
+ */
+public class EmailCommand extends Command {
+
+ public static final String COMMAND_WORD = "email";
+ public static final String MAIL_SYNTAX = "mailto:";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Email 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_EMAIL_PERSON_SUCCESS = "Email Person: %1$s";
+
+ private final Index targetIndex;
+
+ public EmailCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute() throws CommandException {
+ List lastShownList = model.getFilteredPersonList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+ Person personToEmail = lastShownList.get(targetIndex.getZeroBased());
+
+ String emailAddress = personToEmail.getEmail().toString();
+ String emailName = personToEmail.getName().toString();
+
+ try {
+ Desktop.getDesktop().mail(new URI(MAIL_SYNTAX + emailAddress));
+ } catch (HeadlessException hlError) {
+ throw new UnsupportDesktopException(Messages.UNSUPPORTED_DESKTOP);
+ } catch (URISyntaxException Urierror) {
+ throw new CommandException(Messages.MAIL_APP_ERROR);
+ } catch (IOException e) {
+ throw new CommandException(Messages.MAIL_APP_ERROR);
+ }
+
+ return new CommandResult(String.format(MESSAGE_EMAIL_PERSON_SUCCESS, emailName));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof EmailCommand // instanceof handles nulls
+ && this.targetIndex.equals(((EmailCommand) other).targetIndex)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
index b1e671f633d2..21668568cddb 100644
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ b/src/main/java/seedu/address/logic/commands/FindCommand.java
@@ -1,25 +1,25 @@
package seedu.address.logic.commands;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.person.InfoContainsKeywordsPredicate;
/**
* Finds and lists all persons in address book whose name contains any of the argument keywords.
- * Keyword matching is case sensitive.
+ * Keyword matching is not case sensitive.
*/
public class FindCommand extends Command {
public static final String COMMAND_WORD = "find";
+ public static final String COMMAND_ALIAS = "f";
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"
+ + "the specified keywords (not 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 NameContainsKeywordsPredicate predicate;
+ private final InfoContainsKeywordsPredicate predicate;
- public FindCommand(NameContainsKeywordsPredicate predicate) {
- this.predicate = predicate;
- }
+ public FindCommand(InfoContainsKeywordsPredicate predicate) {
+ this.predicate = predicate; }
@Override
public CommandResult execute() {
diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java
index 10febf6d9136..fa2f5603cd91 100644
--- a/src/main/java/seedu/address/logic/commands/HelpCommand.java
+++ b/src/main/java/seedu/address/logic/commands/HelpCommand.java
@@ -9,6 +9,7 @@
public class HelpCommand extends Command {
public static final String COMMAND_WORD = "help";
+ public static final String COMMAND_SIGN = "?";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows program usage instructions.\n"
+ "Example: " + COMMAND_WORD;
diff --git a/src/main/java/seedu/address/logic/commands/HistoryCommand.java b/src/main/java/seedu/address/logic/commands/HistoryCommand.java
index f87abee5511d..a3a8f11563d0 100644
--- a/src/main/java/seedu/address/logic/commands/HistoryCommand.java
+++ b/src/main/java/seedu/address/logic/commands/HistoryCommand.java
@@ -15,6 +15,7 @@
public class HistoryCommand extends Command {
public static final String COMMAND_WORD = "history";
+ public static final String COMMAND_ALIAS = "h";
public static final String MESSAGE_SUCCESS = "Entered commands (from most recent to earliest):\n%1$s";
public static final String MESSAGE_NO_HISTORY = "You have not yet entered any commands.";
diff --git a/src/main/java/seedu/address/logic/commands/ImportCommand.java b/src/main/java/seedu/address/logic/commands/ImportCommand.java
new file mode 100644
index 000000000000..ad04b68c3f77
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/ImportCommand.java
@@ -0,0 +1,48 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.io.File;
+import java.io.IOException;
+
+import seedu.address.commons.exceptions.DataConversionException;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.ReadOnlyAddressBook;
+import seedu.address.storage.XmlFileStorage;
+
+/**
+ * Imports data from a xml file and overwrites the current data stored
+ */
+public class ImportCommand extends Command {
+
+ public static final String COMMAND_WORD = "import";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Imports data from an external xml data file with "
+ + "the provided path and overwrites the current data stored.\n"
+ + "Parameters: FILE_PATH\n"
+ + "Example: " + COMMAND_WORD + " ~/DOWNLOADS/NewDataSet.xml";
+
+ public static final String MESSAGE_SUCCESS = "Data imported successfully";
+ public static final String MESSAGE_INVALID_PATH = "File not found";
+ public static final String MESSAGE_INVALID_FILE = "Data configuration failed";
+
+ private final String filePath;
+
+ public ImportCommand(String filePath) {
+ this.filePath = filePath.trim();
+ }
+
+ @Override
+ public CommandResult execute() throws CommandException {
+ requireNonNull(model);
+ try {
+ ReadOnlyAddressBook newDataSet = XmlFileStorage.loadDataFromSaveFile(new File(filePath));
+ model.resetData(newDataSet);
+ return new CommandResult(MESSAGE_SUCCESS);
+ } catch (IOException e) {
+ throw new CommandException(MESSAGE_INVALID_PATH);
+ } catch (DataConversionException e) {
+ throw new CommandException(MESSAGE_INVALID_FILE);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java
index 7b6463780824..440f944d3a07 100644
--- a/src/main/java/seedu/address/logic/commands/ListCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ListCommand.java
@@ -8,6 +8,7 @@
public class ListCommand extends Command {
public static final String COMMAND_WORD = "list";
+ public static final String COMMAND_ALIAS = "ls";
public static final String MESSAGE_SUCCESS = "Listed all persons";
diff --git a/src/main/java/seedu/address/logic/commands/RedoCommand.java b/src/main/java/seedu/address/logic/commands/RedoCommand.java
index 7b99d0f372fc..311c95c1a1f2 100644
--- a/src/main/java/seedu/address/logic/commands/RedoCommand.java
+++ b/src/main/java/seedu/address/logic/commands/RedoCommand.java
@@ -13,6 +13,7 @@
public class RedoCommand extends Command {
public static final String COMMAND_WORD = "redo";
+ public static final String COMMAND_ALIAS = "r";
public static final String MESSAGE_SUCCESS = "Redo success!";
public static final String MESSAGE_FAILURE = "No more commands to redo!";
diff --git a/src/main/java/seedu/address/logic/commands/SelectCommand.java b/src/main/java/seedu/address/logic/commands/SelectCommand.java
index 9e3840a9dde6..0bc2e3e21485 100644
--- a/src/main/java/seedu/address/logic/commands/SelectCommand.java
+++ b/src/main/java/seedu/address/logic/commands/SelectCommand.java
@@ -15,6 +15,7 @@
public class SelectCommand extends Command {
public static final String COMMAND_WORD = "select";
+ public static final String COMMAND_ALIAS = "s";
public static final String MESSAGE_USAGE = COMMAND_WORD
+ ": Selects the person identified by the index number used in the last person listing.\n"
diff --git a/src/main/java/seedu/address/logic/commands/UndoCommand.java b/src/main/java/seedu/address/logic/commands/UndoCommand.java
index 1f3dcea8bbaa..7d62dcc53d38 100644
--- a/src/main/java/seedu/address/logic/commands/UndoCommand.java
+++ b/src/main/java/seedu/address/logic/commands/UndoCommand.java
@@ -13,6 +13,7 @@
public class UndoCommand extends Command {
public static final String COMMAND_WORD = "undo";
+ public static final String COMMAND_ALIAS = "u";
public static final String MESSAGE_SUCCESS = "Undo success!";
public static final String MESSAGE_FAILURE = "No more commands to undo!";
diff --git a/src/main/java/seedu/address/logic/commands/exceptions/UnsupportDesktopException.java b/src/main/java/seedu/address/logic/commands/exceptions/UnsupportDesktopException.java
new file mode 100644
index 000000000000..c520473016fa
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/exceptions/UnsupportDesktopException.java
@@ -0,0 +1,10 @@
+package seedu.address.logic.commands.exceptions;
+
+/**
+ * Represents an error which occurs during execution of a Desktop operation.
+ */
+public class UnsupportDesktopException extends CommandException {
+ public UnsupportDesktopException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java
index 3c729b388554..7e08c1fd0ee4 100644
--- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java
@@ -3,6 +3,7 @@
import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
@@ -15,6 +16,7 @@
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
@@ -32,21 +34,25 @@ public class AddCommandParser implements Parser {
*/
public AddCommand parse(String args) throws ParseException {
ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME,
+ PREFIX_MATRIC_NUMBER, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
- if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL)
+ if (!arePrefixesPresent(argMultimap, PREFIX_NAME,
+ PREFIX_MATRIC_NUMBER, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL)
|| !argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
}
try {
Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).get();
+ MatriculationNumber matricNumber =
+ ParserUtil.parseMatricNumber(argMultimap.getValue(PREFIX_MATRIC_NUMBER)).get();
Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE)).get();
Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL)).get();
Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS)).get();
Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));
- Person person = new Person(name, phone, email, address, tagList);
+ Person person = new Person(name, matricNumber, phone, email, address, tagList);
return new AddCommand(person);
} catch (IllegalValueException ive) {
diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
index b7d57f5db86a..81ba16731345 100644
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
@@ -11,10 +11,12 @@
import seedu.address.logic.commands.Command;
import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.commands.EditCommand;
+import seedu.address.logic.commands.EmailCommand;
import seedu.address.logic.commands.ExitCommand;
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.HistoryCommand;
+import seedu.address.logic.commands.ImportCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.commands.RedoCommand;
import seedu.address.logic.commands.SelectCommand;
@@ -49,41 +51,60 @@ public Command parseCommand(String userInput) throws ParseException {
switch (commandWord) {
case AddCommand.COMMAND_WORD:
+ case AddCommand.COMMAND_ALIAS:
+ case AddCommand.COMMAND_SIGN:
return new AddCommandParser().parse(arguments);
case EditCommand.COMMAND_WORD:
+ case EditCommand.COMMAND_ALIAS:
return new EditCommandParser().parse(arguments);
case SelectCommand.COMMAND_WORD:
+ case SelectCommand.COMMAND_ALIAS:
return new SelectCommandParser().parse(arguments);
case DeleteCommand.COMMAND_WORD:
+ case DeleteCommand.COMMAND_ALIAS:
+ case DeleteCommand.COMMAND_SIGN:
return new DeleteCommandParser().parse(arguments);
+ case EmailCommand.COMMAND_WORD:
+ return new EmailCommandParser().parse(arguments);
+
case ClearCommand.COMMAND_WORD:
+ case ClearCommand.COMMAND_ALIAS:
return new ClearCommand();
case FindCommand.COMMAND_WORD:
+ case FindCommand.COMMAND_ALIAS:
return new FindCommandParser().parse(arguments);
case ListCommand.COMMAND_WORD:
+ case ListCommand.COMMAND_ALIAS:
return new ListCommand();
case HistoryCommand.COMMAND_WORD:
+ case HistoryCommand.COMMAND_ALIAS:
return new HistoryCommand();
case ExitCommand.COMMAND_WORD:
return new ExitCommand();
case HelpCommand.COMMAND_WORD:
+ case HelpCommand.COMMAND_SIGN:
return new HelpCommand();
case UndoCommand.COMMAND_WORD:
+ case UndoCommand.COMMAND_ALIAS:
return new UndoCommand();
case RedoCommand.COMMAND_WORD:
+ case RedoCommand.COMMAND_ALIAS:
return new RedoCommand();
+ case ImportCommand.COMMAND_WORD:
+ return new ImportCommandParser().parse(arguments);
+
default:
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
}
diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java
index 75b1a9bf1190..7a598f83c1f7 100644
--- a/src/main/java/seedu/address/logic/parser/CliSyntax.java
+++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java
@@ -7,6 +7,7 @@ public class CliSyntax {
/* Prefix definitions */
public static final Prefix PREFIX_NAME = new Prefix("n/");
+ public static final Prefix PREFIX_MATRIC_NUMBER = new Prefix("m/");
public static final Prefix PREFIX_PHONE = new Prefix("p/");
public static final Prefix PREFIX_EMAIL = new Prefix("e/");
public static final Prefix PREFIX_ADDRESS = new Prefix("a/");
diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
index c9cdbed26cf1..4ba65c45908b 100644
--- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
@@ -4,6 +4,7 @@
import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
@@ -33,7 +34,8 @@ public class EditCommandParser implements Parser {
public EditCommand parse(String args) throws ParseException {
requireNonNull(args);
ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_MATRIC_NUMBER, PREFIX_PHONE,
+ PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
Index index;
@@ -46,6 +48,8 @@ public EditCommand parse(String args) throws ParseException {
EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
try {
ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).ifPresent(editPersonDescriptor::setName);
+ ParserUtil.parseMatricNumber(argMultimap.getValue(PREFIX_MATRIC_NUMBER))
+ .ifPresent(editPersonDescriptor::setMatricNumber);
ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE)).ifPresent(editPersonDescriptor::setPhone);
ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL)).ifPresent(editPersonDescriptor::setEmail);
ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS)).ifPresent(editPersonDescriptor::setAddress);
diff --git a/src/main/java/seedu/address/logic/parser/EmailCommandParser.java b/src/main/java/seedu/address/logic/parser/EmailCommandParser.java
new file mode 100644
index 000000000000..892e88f94465
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/EmailCommandParser.java
@@ -0,0 +1,30 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.address.logic.commands.EmailCommand;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new DeleteCommand object
+ */
+public class EmailCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the EmailCommand
+ * and returns an EmailCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public EmailCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new EmailCommand(index);
+ } catch (IllegalValueException ive) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EmailCommand.MESSAGE_USAGE));
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java
index b186a967cb94..b5f3d0c50324 100644
--- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java
@@ -6,7 +6,7 @@
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.person.InfoContainsKeywordsPredicate;
/**
* Parses input arguments and creates a new FindCommand object
@@ -27,7 +27,7 @@ public FindCommand parse(String args) throws ParseException {
String[] nameKeywords = trimmedArgs.split("\\s+");
- return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
+ return new FindCommand(new InfoContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
}
}
diff --git a/src/main/java/seedu/address/logic/parser/ImportCommandParser.java b/src/main/java/seedu/address/logic/parser/ImportCommandParser.java
new file mode 100644
index 000000000000..5e4e37167c59
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/ImportCommandParser.java
@@ -0,0 +1,28 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.logic.commands.ImportCommand;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new ImportCommandParser object
+ */
+public class ImportCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the ImportCommand
+ * and returns an Import Command object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public ImportCommand parse(String userInput) throws ParseException {
+ String trimmedInput = userInput.trim();
+
+ String exceptionMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, ImportCommand.MESSAGE_USAGE);
+ if (trimmedInput.isEmpty()) {
+ throw new ParseException(exceptionMessage);
+ }
+
+ return new ImportCommand(userInput);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java
index 5d6d4ae3f7b1..6f9be47c0482 100644
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java
@@ -12,6 +12,7 @@
import seedu.address.commons.util.StringUtil;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Phone;
import seedu.address.model.tag.Tag;
@@ -67,6 +68,32 @@ public static Optional parseName(Optional name) throws IllegalValu
return name.isPresent() ? Optional.of(parseName(name.get())) : Optional.empty();
}
+ /**
+ * Parses a {@code String matricNumber} into a {@code MatriculationNumber}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws IllegalValueException if the given {@code matricNumber} is invalid.
+ */
+ public static MatriculationNumber parseMatricNumber(String matricNumber) throws IllegalValueException {
+ requireNonNull(matricNumber);
+ String trimmedMatricNumber = matricNumber.trim();
+ if (!MatriculationNumber.isValidMatricNumber(trimmedMatricNumber)) {
+ throw new IllegalValueException(MatriculationNumber.MESSAGE_MATRIC_NUMBER_CONSTRAINTS);
+ }
+ return new MatriculationNumber(trimmedMatricNumber);
+ }
+
+ /**
+ * Parses a {@code Optional matricNumber} into an {@code Optional}
+ * if {@code matricNumber} is present.
+ * See header comment of this class regarding the use of {@code Optional} parameters.
+ */
+ public static Optional
+ parseMatricNumber(Optional matricNumber) throws IllegalValueException {
+ requireNonNull(matricNumber);
+ return matricNumber.isPresent() ? Optional.of(parseMatricNumber(matricNumber.get())) : Optional.empty();
+ }
+
/**
* Parses a {@code String phone} into a {@code Phone}.
* Leading and trailing whitespaces will be trimmed.
diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java
index f8d0260de159..db4265087978 100644
--- a/src/main/java/seedu/address/model/AddressBook.java
+++ b/src/main/java/seedu/address/model/AddressBook.java
@@ -132,7 +132,8 @@ private Person syncWithMasterTagList(Person person) {
final Set correctTagReferences = new HashSet<>();
personTags.forEach(tag -> correctTagReferences.add(masterTagObjects.get(tag)));
return new Person(
- person.getName(), person.getPhone(), person.getEmail(), person.getAddress(), correctTagReferences);
+ person.getName(), person.getMatricNumber(),
+ person.getPhone(), person.getEmail(), person.getAddress(), correctTagReferences);
}
/**
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
index 22a7d0eb3f4d..1ea29fe4f014 100644
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ b/src/main/java/seedu/address/model/ModelManager.java
@@ -43,6 +43,7 @@ public ModelManager() {
this(new AddressBook(), new UserPrefs());
}
+
@Override
public void resetData(ReadOnlyAddressBook newData) {
addressBook.resetData(newData);
diff --git a/src/main/java/seedu/address/model/Todo/Description.java b/src/main/java/seedu/address/model/Todo/Description.java
new file mode 100644
index 000000000000..8c5aef366c44
--- /dev/null
+++ b/src/main/java/seedu/address/model/Todo/Description.java
@@ -0,0 +1,56 @@
+package seedu.address.model.Todo;
+
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a short description of a todo task
+ */
+public class Description {
+
+ public static final String MESSAGE_DESCRIPTION_CONSTRAINTS =
+ "Task description can take any values, and it should not be blank";
+
+ /*
+ * The first character of the description must not be a whitespace,
+ * otherwise " " (a blank string) becomes a valid input.
+ */
+ public static final String DESCRIPTION_VALIDATION_REGEX = "[^\\s].*";
+
+ public final String value;
+
+ /**
+ * Constructs an {@code Description}.
+ *
+ * @param description A valid address.
+ */
+ public Description(String description) {
+ assert description != null : MESSAGE_DESCRIPTION_CONSTRAINTS;
+ checkArgument(isValidDescription(description));
+ this.value = description;
+ }
+
+ /**
+ * Returns true if a given string is a valid person email.
+ */
+ public static boolean isValidDescription(String test) {
+ return test.matches(DESCRIPTION_VALIDATION_REGEX);
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Description // instanceof handles nulls
+ && this.value.equals(((Description) other).value)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/InfoContainsKeywordsPredicate.java
similarity index 51%
rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
rename to src/main/java/seedu/address/model/person/InfoContainsKeywordsPredicate.java
index 827e2cc106bd..74787d1d9497 100644
--- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
+++ b/src/main/java/seedu/address/model/person/InfoContainsKeywordsPredicate.java
@@ -6,26 +6,28 @@
import seedu.address.commons.util.StringUtil;
/**
- * Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
+ * Tests that a {@code Person}'s {@code Name} and {@code MatriculationNumber} matches any of the keywords given.
*/
-public class NameContainsKeywordsPredicate implements Predicate {
+public class InfoContainsKeywordsPredicate implements Predicate {
private final List keywords;
- public NameContainsKeywordsPredicate(List keywords) {
+ public InfoContainsKeywordsPredicate(List keywords) {
this.keywords = keywords;
}
@Override
public boolean test(Person person) {
return keywords.stream()
- .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword));
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword))
+ || keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getMatricNumber().value, keyword));
}
@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
- || (other instanceof NameContainsKeywordsPredicate // instanceof handles nulls
- && this.keywords.equals(((NameContainsKeywordsPredicate) other).keywords)); // state check
+ || (other instanceof InfoContainsKeywordsPredicate // instanceof handles nulls
+ && this.keywords.equals(((InfoContainsKeywordsPredicate) other).keywords)); // state check
}
}
diff --git a/src/main/java/seedu/address/model/person/MatriculationNumber.java b/src/main/java/seedu/address/model/person/MatriculationNumber.java
new file mode 100644
index 000000000000..8c1ae5d41622
--- /dev/null
+++ b/src/main/java/seedu/address/model/person/MatriculationNumber.java
@@ -0,0 +1,63 @@
+package seedu.address.model.person;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Person's matriculation number in the address book.
+ * Guarantees: immutable; is valid as declared in {@link #isValidMatricNumber(String)}
+ */
+public class MatriculationNumber {
+
+
+ public static final String MESSAGE_MATRIC_NUMBER_CONSTRAINTS =
+ "Matric numbers can only contain capital letters and numbers, and should contain 9 characters";
+ public static final String MATRIC_NUMBER_VALIDATION_REGEX_FIRST = "[AU]{1}";
+ public static final String MATRIC_NUMBER_VALIDATION_REGEX_SECOND = "\\d{7}";
+ public static final String MATRIC_NUMBER_VALIDATION_REGEX_LAST = "[A-Z]{1}";
+ public final String value;
+
+ /**
+ * Constructs a {@code MatriculationNumber}.
+ *
+ * @param matricNumber A valid matriculation number.
+ */
+ public MatriculationNumber(String matricNumber) {
+ requireNonNull(matricNumber);
+ checkArgument(isValidMatricNumber(matricNumber), MESSAGE_MATRIC_NUMBER_CONSTRAINTS);
+ this.value = matricNumber;
+ }
+
+ /**
+ * Returns true if a given string is a valid person matriculation number.
+ */
+ public static boolean isValidMatricNumber(String test) {
+ if (test.length() != 9) {
+ return false;
+ }
+ String firstCharacter = test.substring(0, 1);
+ String nextCharacters = test.substring(1, test.length() - 1);
+ String lastCharacter = test.substring(test.length() - 1, test.length());
+ return firstCharacter.matches(MATRIC_NUMBER_VALIDATION_REGEX_FIRST)
+ && nextCharacters.matches(MATRIC_NUMBER_VALIDATION_REGEX_SECOND)
+ && lastCharacter.matches(MATRIC_NUMBER_VALIDATION_REGEX_LAST);
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof MatriculationNumber // instanceof handles nulls
+ && this.value.equals(((MatriculationNumber) other).value)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java
index ec9f2aa5e919..860cf6d1b757 100644
--- a/src/main/java/seedu/address/model/person/Person.java
+++ b/src/main/java/seedu/address/model/person/Person.java
@@ -16,6 +16,7 @@
public class Person {
private final Name name;
+ private final MatriculationNumber matricNumber;
private final Phone phone;
private final Email email;
private final Address address;
@@ -25,9 +26,10 @@ public class Person {
/**
* Every field must be present and not null.
*/
- public Person(Name name, Phone phone, Email email, Address address, Set tags) {
+ public Person(Name name, MatriculationNumber matricNum, Phone phone, Email email, Address address, Set tags) {
requireAllNonNull(name, phone, email, address, tags);
this.name = name;
+ this.matricNumber = matricNum;
this.phone = phone;
this.email = email;
this.address = address;
@@ -39,6 +41,9 @@ public Name getName() {
return name;
}
+ public MatriculationNumber getMatricNumber() {
+ return matricNumber; }
+
public Phone getPhone() {
return phone;
}
@@ -71,6 +76,7 @@ public boolean equals(Object other) {
Person otherPerson = (Person) other;
return otherPerson.getName().equals(this.getName())
+ && otherPerson.getMatricNumber().equals(this.getMatricNumber())
&& otherPerson.getPhone().equals(this.getPhone())
&& otherPerson.getEmail().equals(this.getEmail())
&& otherPerson.getAddress().equals(this.getAddress());
@@ -79,13 +85,15 @@ public boolean equals(Object 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);
+ return Objects.hash(name, matricNumber, phone, email, address, tags);
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(getName())
+ .append(" Matriculation Number: ")
+ .append(getMatricNumber())
.append(" Phone: ")
.append(getPhone())
.append(" Email: ")
diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java
index aea96bfb31f3..8f3498356c19 100644
--- a/src/main/java/seedu/address/model/util/SampleDataUtil.java
+++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java
@@ -7,6 +7,7 @@
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
@@ -19,24 +20,30 @@
public class SampleDataUtil {
public static Person[] getSamplePersons() {
return new Person[] {
- new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"),
+ new Person(new Name("Alex Yeoh"), new MatriculationNumber("A1234567X"),
+ new Phone("87438807"), new Email("alexyeoh@example.com"),
new Address("Blk 30 Geylang Street 29, #06-40"),
- getTagSet("friends")),
- new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"),
+ getTagSet("1")),
+ new Person(new Name("Bernice Yu"), new MatriculationNumber("A2234567Y"),
+ new Phone("99272758"), new Email("berniceyu@example.com"),
new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"),
- getTagSet("colleagues", "friends")),
- new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"),
+ getTagSet("2")),
+ new Person(new Name("Charlotte Oliveiro"), new MatriculationNumber("A1234567X"),
+ new Phone("93210283"), new Email("charlotte@example.com"),
new Address("Blk 11 Ang Mo Kio Street 74, #11-04"),
- getTagSet("neighbours")),
- new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"),
+ getTagSet("exchange")),
+ new Person(new Name("David Li"), new MatriculationNumber("A3234567J"),
+ new Phone("91031282"), new Email("lidavid@example.com"),
new Address("Blk 436 Serangoon Gardens Street 26, #16-43"),
- getTagSet("family")),
- new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"),
+ getTagSet("retaking")),
+ new Person(new Name("Irfan Ibrahim"), new MatriculationNumber("A4234567K"),
+ new Phone("92492021"), new Email("irfan@example.com"),
new Address("Blk 47 Tampines Street 20, #17-35"),
- getTagSet("classmates")),
- new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"),
+ getTagSet("friend")),
+ new Person(new Name("Roy Balakrishnan"), new MatriculationNumber("A5234567G"),
+ new Phone("92624417"), new Email("royb@example.com"),
new Address("Blk 45 Aljunied Street 85, #11-31"),
- getTagSet("colleagues"))
+ getTagSet("brother"))
};
}
diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java
index cf5b527c063a..cba76a48324f 100644
--- a/src/main/java/seedu/address/storage/AddressBookStorage.java
+++ b/src/main/java/seedu/address/storage/AddressBookStorage.java
@@ -41,4 +41,10 @@ public interface AddressBookStorage {
*/
void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) throws IOException;
+ /**
+ * Saves the given (@link ReadOnlyAddressBook) to storage as a backup
+ * @param addressBook cannot be null
+ * @throws IOException if there is any issue writing to the temporary file
+ */
+ void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
}
diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java
index 53967b391a5a..f7a29e8e2170 100644
--- a/src/main/java/seedu/address/storage/StorageManager.java
+++ b/src/main/java/seedu/address/storage/StorageManager.java
@@ -77,6 +77,10 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) th
addressBookStorage.saveAddressBook(addressBook, filePath);
}
+ @Override
+ public void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
+ backupAddressBook(addressBook);
+ }
@Override
@Subscribe
diff --git a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java
index 2cd92dc4fd20..a25d0d31a2c5 100644
--- a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java
+++ b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java
@@ -11,6 +11,7 @@
import seedu.address.commons.exceptions.IllegalValueException;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
@@ -26,6 +27,8 @@ public class XmlAdaptedPerson {
@XmlElement(required = true)
private String name;
@XmlElement(required = true)
+ private String matricNumber;
+ @XmlElement(required = true)
private String phone;
@XmlElement(required = true)
private String email;
@@ -44,8 +47,10 @@ public XmlAdaptedPerson() {}
/**
* Constructs an {@code XmlAdaptedPerson} with the given person details.
*/
- public XmlAdaptedPerson(String name, String phone, String email, String address, List tagged) {
+ public XmlAdaptedPerson(String name, String matricNumber, String phone,
+ String email, String address, List tagged) {
this.name = name;
+ this.matricNumber = matricNumber;
this.phone = phone;
this.email = email;
this.address = address;
@@ -61,6 +66,7 @@ public XmlAdaptedPerson(String name, String phone, String email, String address,
*/
public XmlAdaptedPerson(Person source) {
name = source.getName().fullName;
+ matricNumber = source.getMatricNumber().value;
phone = source.getPhone().value;
email = source.getEmail().value;
address = source.getAddress().value;
@@ -89,6 +95,17 @@ public Person toModelType() throws IllegalValueException {
}
final Name name = new Name(this.name);
+ if (this.matricNumber == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ MatriculationNumber.class.getSimpleName()));
+ }
+
+ if (!MatriculationNumber.isValidMatricNumber(this.matricNumber)) {
+ throw new IllegalValueException(MatriculationNumber.MESSAGE_MATRIC_NUMBER_CONSTRAINTS);
+ }
+
+ final MatriculationNumber matricNumber = new MatriculationNumber(this.matricNumber);
+
if (this.phone == null) {
throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()));
}
@@ -114,7 +131,7 @@ public Person toModelType() throws IllegalValueException {
final Address address = new Address(this.address);
final Set tags = new HashSet<>(personTags);
- return new Person(name, phone, email, address, tags);
+ return new Person(name, matricNumber, phone, email, address, tags);
}
@Override
@@ -129,6 +146,7 @@ public boolean equals(Object other) {
XmlAdaptedPerson otherPerson = (XmlAdaptedPerson) other;
return Objects.equals(name, otherPerson.name)
+ && Objects.equals(matricNumber, otherPerson.matricNumber)
&& Objects.equals(phone, otherPerson.phone)
&& Objects.equals(email, otherPerson.email)
&& Objects.equals(address, otherPerson.address)
diff --git a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java b/src/main/java/seedu/address/storage/XmlAddressBookStorage.java
index c77ebe67435c..79ca2b80202d 100644
--- a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java
+++ b/src/main/java/seedu/address/storage/XmlAddressBookStorage.java
@@ -79,4 +79,9 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) th
XmlFileStorage.saveDataToFile(file, new XmlSerializableAddressBook(addressBook));
}
+ @Override
+ public void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
+ saveAddressBook(addressBook, (filePath + ".bak"));
+ }
+
}
diff --git a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java b/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java
index dc820896c312..2efa7eccb495 100644
--- a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java
+++ b/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java
@@ -7,15 +7,19 @@
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
import seedu.address.commons.exceptions.IllegalValueException;
import seedu.address.model.AddressBook;
import seedu.address.model.ReadOnlyAddressBook;
+import seedu.address.model.person.Person;
+import seedu.address.model.tag.Tag;
/**
* An Immutable AddressBook that is serializable to XML format
*/
@XmlRootElement(name = "addressbook")
-public class XmlSerializableAddressBook {
+public class XmlSerializableAddressBook implements ReadOnlyAddressBook {
@XmlElement
private List persons;
@@ -70,4 +74,28 @@ public boolean equals(Object other) {
XmlSerializableAddressBook otherAb = (XmlSerializableAddressBook) other;
return persons.equals(otherAb.persons) && tags.equals(otherAb.tags);
}
+
+ @Override
+ public ObservableList getPersonList() {
+ final ObservableList persons = this.persons.stream().map(p -> {
+ try {
+ return p.toModelType();
+ } catch (IllegalValueException e) {
+ return null;
+ }
+ }).collect(Collectors.toCollection(FXCollections::observableArrayList));
+ return FXCollections.unmodifiableObservableList(persons);
+ }
+
+ @Override
+ public ObservableList getTagList() {
+ final ObservableList tags = this.tags.stream().map(t -> {
+ try {
+ return t.toModelType();
+ } catch (IllegalValueException e) {
+ return null;
+ }
+ }).collect(Collectors.toCollection(FXCollections::observableArrayList));
+ return FXCollections.unmodifiableObservableList(tags);
+ }
}
diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java
index f6727ea83abd..6303f1027b45 100644
--- a/src/main/java/seedu/address/ui/PersonCard.java
+++ b/src/main/java/seedu/address/ui/PersonCard.java
@@ -14,6 +14,16 @@ public class PersonCard extends UiPart {
private static final String FXML = "PersonListCard.fxml";
+ private static final String lecturerTag = "lecturer";
+
+ private static final String TATag = "TA";
+
+ private static final String studentTag = "student";
+
+ private static final String tutorial1Tag = "T1";
+
+ private static final String[] TAG_COLOR_STYLES = { "teal", "orange", "brown", "pink", "black", "grey" };
+
/**
* Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX.
* As a consequence, UI elements' variable names cannot be set to such keywords
@@ -29,6 +39,8 @@ public class PersonCard extends UiPart {
@FXML
private Label name;
@FXML
+ private Label matricNumber;
+ @FXML
private Label id;
@FXML
private Label phone;
@@ -44,10 +56,46 @@ public PersonCard(Person person, int displayedIndex) {
this.person = person;
id.setText(displayedIndex + ". ");
name.setText(person.getName().fullName);
+ matricNumber.setText(person.getMatricNumber().value);
phone.setText(person.getPhone().value);
address.setText(person.getAddress().value);
email.setText(person.getEmail().value);
- person.getTags().forEach(tag -> tags.getChildren().add(new Label(tag.tagName)));
+ initTags(person);
+ }
+
+ /**
+ * Returns the color style for {@code tagName}'s label.
+ */
+ private String getTagColorStyleFor(String tagName) {
+ // we use the hash code of the tag name to generate a random color, so that the color remain consistent
+ // between different runs of the program while still making it random enough between tags.
+ switch (tagName) {
+ case lecturerTag:
+ return "red";
+
+ case TATag:
+ return "yellow";
+
+ case studentTag:
+ return "blue";
+
+ case tutorial1Tag:
+ return "green";
+
+ default:
+ return TAG_COLOR_STYLES[Math.abs(tagName.hashCode()) % TAG_COLOR_STYLES.length];
+ }
+ }
+
+ /**
+ * Creates the tag labels for {@code person}.
+ */
+ private void initTags(Person person) {
+ person.getTags().forEach(tag -> {
+ Label tagLabel = new Label(tag.tagName);
+ tagLabel.getStyleClass().add(getTagColorStyleFor(tag.tagName));
+ tags.getChildren().add(tagLabel);
+ });
}
@Override
diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css
index d06336391cca..fe6df9a36a2d 100644
--- a/src/main/resources/view/DarkTheme.css
+++ b/src/main/resources/view/DarkTheme.css
@@ -342,10 +342,104 @@
}
#tags .label {
- -fx-text-fill: white;
- -fx-background-color: #3e7b91;
-fx-padding: 1 3 1 3;
-fx-border-radius: 2;
-fx-background-radius: 2;
-fx-font-size: 11;
}
+
+#tags .teal {
+ -fx-text-fill: white;
+ -fx-background-color: #3e7b91;
+}
+
+#tags .red {
+ -fx-text-fill: black;
+ -fx-background-color: red;
+}
+
+#tags .yellow {
+ -fx-background-color: yellow;
+ -fx-text-fill: black;
+}
+
+#tags .blue {
+ -fx-text-fill: white;
+ -fx-background-color: blue;
+}
+
+#tags .orange {
+ -fx-text-fill: black;
+ -fx-background-color: orange;
+}
+
+#tags .brown {
+ -fx-text-fill: white;
+ -fx-background-color: brown;
+}
+
+#tags .green {
+ -fx-text-fill: black;
+ -fx-background-color: green;
+}
+
+#tags .pink {
+ -fx-text-fill: black;
+ -fx-background-color: pink;
+}
+
+#tags .black {
+ -fx-text-fill: white;
+ -fx-background-color: black;
+}
+
+#tags .grey {
+ -fx-text-fill: black;
+ -fx-background-color: grey;
+}
+
+.tab-pane {
+ -fx-padding: 0 0 0 1;
+ -fx-background-color: #232A34;
+}
+
+.tab-pane .tab-header-area {
+ -fx-background-color: #232A34;
+ -fx-padding: 0 0 0 0;
+ -fx-min-height: 0;
+ -fx-max-height: 0;
+}
+
+.tab-pane .tab-header-area .tab-header-background {
+ -fx-opacity: 0;
+}
+
+.tab-pane {
+ -fx-tab-min-width:150px;
+}
+
+.tab {
+ -fx-background-insets: 0 1 0 1,0,0;
+}
+
+.tab-pane .tab {
+ -fx-background-color: #404040;
+
+}
+
+.tab-pane .tab:selected {
+ -fx-border-color: transparent !important;
+ -fx-background-color: #5F6A6A;
+}
+
+.tab .tab-label {
+ -fx-alignment: CENTER;
+ -fx-text-fill: #f3f3f3;
+ -fx-font-size: 12px;
+ -fx-font-weight: bold;
+}
+
+.tab:selected .tab-label {
+ -fx-border-color: transparent !important;
+ -fx-text-fill: white;
+}
diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml
index 1dadb95b6ffe..2606328e3442 100644
--- a/src/main/resources/view/MainWindow.fxml
+++ b/src/main/resources/view/MainWindow.fxml
@@ -11,6 +11,8 @@
+
+
@@ -47,14 +49,21 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml
index f08ea32ad558..51a2dac3743c 100644
--- a/src/main/resources/view/PersonListCard.fxml
+++ b/src/main/resources/view/PersonListCard.fxml
@@ -28,6 +28,7 @@
+
diff --git a/src/main/resources/view/PersonPanel.fxml b/src/main/resources/view/PersonPanel.fxml
new file mode 100644
index 000000000000..71557af8f109
--- /dev/null
+++ b/src/main/resources/view/PersonPanel.fxml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/todoListCard.fxml b/src/main/resources/view/todoListCard.fxml
new file mode 100644
index 000000000000..59e61c5a1454
--- /dev/null
+++ b/src/main/resources/view/todoListCard.fxml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/todoListPanel.fxml b/src/main/resources/view/todoListPanel.fxml
new file mode 100644
index 000000000000..39570960a567
--- /dev/null
+++ b/src/main/resources/view/todoListPanel.fxml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml b/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml
index c778cccc4c89..66a62437ed1a 100644
--- a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml
+++ b/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml
@@ -4,6 +4,7 @@
Alice Pauline
+ A1234567X85355255alice@example.com
123, Jurong West Ave 6, #08-111
@@ -11,6 +12,7 @@
Benson Meier
+ A2234567X98765432johnd@example.com
311, Clementi Ave 2, #02-25
@@ -19,30 +21,35 @@
Carl Kurz
+ A3234567X95352563heinz@example.com
wall street
Daniel Meier
+ A4234567X87652533cornelia@example.com
10th street
Elle Meyer
+ A5234567X9482224werner@example.com
michegan ave
Fiona Kunz
+ A6234567X9482427lydia@example.com
little tokyo
George Best
+ A7234567X9482442anna@example.com
4th street
diff --git a/src/test/data/XmlUtilTest/invalidPersonField.xml b/src/test/data/XmlUtilTest/invalidPersonField.xml
index ba49c971e884..e0f179d13ab1 100644
--- a/src/test/data/XmlUtilTest/invalidPersonField.xml
+++ b/src/test/data/XmlUtilTest/invalidPersonField.xml
@@ -2,6 +2,7 @@
Hans Muster
+ A0123456I9482asf424hans@example
4th street
diff --git a/src/test/data/XmlUtilTest/missingPersonField.xml b/src/test/data/XmlUtilTest/missingPersonField.xml
index c0da5c86d080..cfb4663f7760 100644
--- a/src/test/data/XmlUtilTest/missingPersonField.xml
+++ b/src/test/data/XmlUtilTest/missingPersonField.xml
@@ -1,6 +1,7 @@
+ A0123456I9482424hans@example
4th street
diff --git a/src/test/data/XmlUtilTest/validAddressBook.xml b/src/test/data/XmlUtilTest/validAddressBook.xml
index 6265778674d3..707adc0927c5 100644
--- a/src/test/data/XmlUtilTest/validAddressBook.xml
+++ b/src/test/data/XmlUtilTest/validAddressBook.xml
@@ -2,54 +2,63 @@
Hans Muster
+ A1234567X9482424hans@example.com
4th street
Ruth Mueller
+ A2234567X87249245ruth@example.com
81th street
Heinz Kurz
+ A3234567X95352563heinz@example.com
wall street
Cornelia Meier
+ A4234567X87652533cornelia@example.com
10th street
Werner Meyer
+ A5234567X9482224werner@example.com
michegan ave
Lydia Kunz
+ A6234567X9482427lydia@example.com
little tokyo
Anna Best
+ A7234567X9482442anna@example.com
4th street
Stefan Meier
+ A8234567X8482424stefan@example.com
little india
Martin Mueller
+ A9234567X8482131hans@example.com
chicago ave
diff --git a/src/test/data/XmlUtilTest/validPerson.xml b/src/test/data/XmlUtilTest/validPerson.xml
index c029008d54f4..76d75cbc58ab 100644
--- a/src/test/data/XmlUtilTest/validPerson.xml
+++ b/src/test/data/XmlUtilTest/validPerson.xml
@@ -1,6 +1,7 @@
Hans Muster
+ A0123456I9482424hans@example
4th street
diff --git a/src/test/java/guitests/guihandles/PersonCardHandle.java b/src/test/java/guitests/guihandles/PersonCardHandle.java
index d337d3a4cee9..37164b91674c 100644
--- a/src/test/java/guitests/guihandles/PersonCardHandle.java
+++ b/src/test/java/guitests/guihandles/PersonCardHandle.java
@@ -68,4 +68,13 @@ public List getTags() {
.map(Label::getText)
.collect(Collectors.toList());
}
+
+ public List getTagStyleClasses(String tag) {
+ return tagLabels
+ .stream()
+ .filter(label -> label.getText().equals(tag))
+ .map(Label::getStyleClass)
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException("No such tag."));
+ }
}
diff --git a/src/test/java/seedu/address/commons/util/XmlUtilTest.java b/src/test/java/seedu/address/commons/util/XmlUtilTest.java
index 56b6ef8f40d3..b14b6ae6fed5 100644
--- a/src/test/java/seedu/address/commons/util/XmlUtilTest.java
+++ b/src/test/java/seedu/address/commons/util/XmlUtilTest.java
@@ -36,6 +36,7 @@ public class XmlUtilTest {
private static final String INVALID_PHONE = "9482asf424";
private static final String VALID_NAME = "Hans Muster";
+ private static final String VALID_MATRICULATION_NUMBER = "A0123456I";
private static final String VALID_PHONE = "9482424";
private static final String VALID_EMAIL = "hans@example";
private static final String VALID_ADDRESS = "4th street";
@@ -80,7 +81,7 @@ public void xmlAdaptedPersonFromFile_fileWithMissingPersonField_validResult() th
XmlAdaptedPerson actualPerson = XmlUtil.getDataFromFile(
MISSING_PERSON_FIELD_FILE, XmlAdaptedPersonWithRootElement.class);
XmlAdaptedPerson expectedPerson = new XmlAdaptedPerson(
- null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ null, VALID_MATRICULATION_NUMBER, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
assertEquals(expectedPerson, actualPerson);
}
@@ -89,7 +90,7 @@ public void xmlAdaptedPersonFromFile_fileWithInvalidPersonField_validResult() th
XmlAdaptedPerson actualPerson = XmlUtil.getDataFromFile(
INVALID_PERSON_FIELD_FILE, XmlAdaptedPersonWithRootElement.class);
XmlAdaptedPerson expectedPerson = new XmlAdaptedPerson(
- VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ VALID_NAME, VALID_MATRICULATION_NUMBER, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
assertEquals(expectedPerson, actualPerson);
}
@@ -98,7 +99,7 @@ public void xmlAdaptedPersonFromFile_fileWithValidPerson_validResult() throws Ex
XmlAdaptedPerson actualPerson = XmlUtil.getDataFromFile(
VALID_PERSON_FILE, XmlAdaptedPersonWithRootElement.class);
XmlAdaptedPerson expectedPerson = new XmlAdaptedPerson(
- VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ VALID_NAME, VALID_MATRICULATION_NUMBER, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
assertEquals(expectedPerson, actualPerson);
}
diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
index 9a5679cc29b6..ad4281003bd8 100644
--- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
+++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
@@ -5,6 +5,7 @@
import static org.junit.Assert.fail;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
@@ -19,7 +20,7 @@
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.AddressBook;
import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.person.InfoContainsKeywordsPredicate;
import seedu.address.model.person.Person;
import seedu.address.model.person.exceptions.PersonNotFoundException;
import seedu.address.testutil.EditPersonDescriptorBuilder;
@@ -31,6 +32,8 @@ public class CommandTestUtil {
public static final String VALID_NAME_AMY = "Amy Bee";
public static final String VALID_NAME_BOB = "Bob Choo";
+ public static final String VALID_MATRIC_NUMBER_AMY = "A5678901L";
+ public static final String VALID_MATRIC_NUMBER_BOB = "U1234567K";
public static final String VALID_PHONE_AMY = "11111111";
public static final String VALID_PHONE_BOB = "22222222";
public static final String VALID_EMAIL_AMY = "amy@example.com";
@@ -42,6 +45,8 @@ public class CommandTestUtil {
public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY;
public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB;
+ public static final String MATRIC_NUMBER_DESC_AMY = " " + PREFIX_MATRIC_NUMBER + VALID_MATRIC_NUMBER_AMY;
+ public static final String MATRIC_NUMBER_DESC_BOB = " " + PREFIX_MATRIC_NUMBER + VALID_MATRIC_NUMBER_BOB;
public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY;
public static final String PHONE_DESC_BOB = " " + PREFIX_PHONE + VALID_PHONE_BOB;
public static final String EMAIL_DESC_AMY = " " + PREFIX_EMAIL + VALID_EMAIL_AMY;
@@ -52,11 +57,15 @@ public class CommandTestUtil {
public static final String TAG_DESC_HUSBAND = " " + PREFIX_TAG + VALID_TAG_HUSBAND;
public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names
+ public static final String INVALID_MATRIC_NUMBER_DESC = " " + PREFIX_MATRIC_NUMBER
+ + "E12345678"; // first letter must be A or U
public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones
public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol
public static final String INVALID_ADDRESS_DESC = " " + PREFIX_ADDRESS; // empty string not allowed for addresses
public static final String INVALID_TAG_DESC = " " + PREFIX_TAG + "hubby*"; // '*' not allowed in tags
+ public static final String INVALID_FILE = "invalidFileTest.xml";
+
public static final String PREAMBLE_WHITESPACE = "\t \r \n";
public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble";
@@ -64,10 +73,10 @@ public class CommandTestUtil {
public static final EditCommand.EditPersonDescriptor DESC_BOB;
static {
- DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY)
+ DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY).withMatricNumber(VALID_MATRIC_NUMBER_AMY)
.withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY)
.withTags(VALID_TAG_FRIEND).build();
- DESC_BOB = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
+ DESC_BOB = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).withMatricNumber(VALID_MATRIC_NUMBER_BOB)
.withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB)
.withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build();
}
@@ -119,7 +128,7 @@ public static void showPersonAtIndex(Model model, Index targetIndex) {
Person person = model.getFilteredPersonList().get(targetIndex.getZeroBased());
final String[] splitName = person.getName().fullName.split("\\s+");
- model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
+ model.updateFilteredPersonList(new InfoContainsKeywordsPredicate(Arrays.asList(splitName[0])));
assertEquals(1, model.getFilteredPersonList().size());
}
diff --git a/src/test/java/seedu/address/logic/commands/EmailCommandTest.java b/src/test/java/seedu/address/logic/commands/EmailCommandTest.java
new file mode 100644
index 000000000000..ba5ad0d6b095
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/EmailCommandTest.java
@@ -0,0 +1,100 @@
+package seedu.address.logic.commands;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
+import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+
+import org.junit.Test;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.CommandHistory;
+import seedu.address.logic.UndoRedoStack;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.logic.commands.exceptions.UnsupportDesktopException;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.person.Person;
+
+/**
+ * Contains unit tests for
+ * {@code EmailCommand}.
+ */
+public class EmailCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_validIndexUnfilteredList_success() {
+ Person personToEmail = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
+ EmailCommand emailCommand = prepareCommand(INDEX_FIRST_PERSON);
+
+ String expectedMessage = String.format(EmailCommand.MESSAGE_EMAIL_PERSON_SUCCESS,
+ personToEmail.getName().toString());
+ assertEmailSuccess(expectedMessage, emailCommand);
+ }
+
+ @Test
+ public void execute_invalidIndexUnfilteredList_throwsCommandException() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
+ EmailCommand emailCommand = prepareCommand(outOfBoundIndex);
+
+ assertCommandFailure(emailCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_validIndexFilteredList_success() {
+ showPersonAtIndex(model, INDEX_FIRST_PERSON);
+
+ Person personToEmail = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
+ EmailCommand emailCommand = prepareCommand(INDEX_FIRST_PERSON);
+
+ String expectedMessage = String.format(EmailCommand.MESSAGE_EMAIL_PERSON_SUCCESS,
+ personToEmail.getName().toString());
+ assertEmailSuccess(expectedMessage, emailCommand);
+ }
+
+ @Test
+ public void execute_invalidIndexFilteredList_throwsCommandException() {
+ showPersonAtIndex(model, INDEX_FIRST_PERSON);
+
+ Index outOfBoundIndex = INDEX_SECOND_PERSON;
+ // ensures that outOfBoundIndex is still in bounds of address book list
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
+
+ EmailCommand emailCommand = prepareCommand(outOfBoundIndex);
+
+ assertCommandFailure(emailCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+ /**
+ * Returns a {@code EmailCommand} with the parameter {@code index}.
+ */
+ private EmailCommand prepareCommand(Index index) {
+ EmailCommand emailCommand = new EmailCommand(index);
+ emailCommand.setData(model, new CommandHistory(), new UndoRedoStack());
+ return emailCommand;
+ }
+
+ /**
+ * Executes the given {@code command}, confirms that
+ * - the result message matches {@code expectedResult}
+ * - the {@code expectedResult} matches {@code testCommand}
+ */
+ private static void assertEmailSuccess(String expectedResult, EmailCommand testCommand) {
+ try {
+ CommandResult result = testCommand.execute();
+ assertEquals(expectedResult, result.feedbackToUser);
+ } catch (UnsupportDesktopException de) {
+ // Code is running on unsupported OS
+ assertEquals(de.getMessage(), Messages.UNSUPPORTED_DESKTOP);
+ } catch (CommandException ce) {
+ throw new AssertionError("Execution of command should not fail.", ce);
+ }
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
index dee1f007f751..78ab3d9942dd 100644
--- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
@@ -21,7 +21,7 @@
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.person.InfoContainsKeywordsPredicate;
import seedu.address.model.person.Person;
/**
@@ -32,10 +32,10 @@ public class FindCommandTest {
@Test
public void equals() {
- NameContainsKeywordsPredicate firstPredicate =
- new NameContainsKeywordsPredicate(Collections.singletonList("first"));
- NameContainsKeywordsPredicate secondPredicate =
- new NameContainsKeywordsPredicate(Collections.singletonList("second"));
+ InfoContainsKeywordsPredicate firstPredicate =
+ new InfoContainsKeywordsPredicate(Collections.singletonList("first"));
+ InfoContainsKeywordsPredicate secondPredicate =
+ new InfoContainsKeywordsPredicate(Collections.singletonList("second"));
FindCommand findFirstCommand = new FindCommand(firstPredicate);
FindCommand findSecondCommand = new FindCommand(secondPredicate);
@@ -76,7 +76,7 @@ public void execute_multipleKeywords_multiplePersonsFound() {
*/
private FindCommand prepareCommand(String userInput) {
FindCommand command =
- new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+"))));
+ new FindCommand(new InfoContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+"))));
command.setData(model, new CommandHistory(), new UndoRedoStack());
return command;
}
diff --git a/src/test/java/seedu/address/logic/commands/ImportCommandTest.java b/src/test/java/seedu/address/logic/commands/ImportCommandTest.java
new file mode 100644
index 000000000000..06f618e45526
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/ImportCommandTest.java
@@ -0,0 +1,67 @@
+package seedu.address.logic.commands;
+
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_FILE;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import seedu.address.logic.CommandHistory;
+import seedu.address.logic.UndoRedoStack;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.storage.JsonUserPrefsStorage;
+import seedu.address.storage.StorageManager;
+import seedu.address.storage.XmlAddressBookStorage;
+import seedu.address.ui.testutil.EventsCollectorRule;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code ImportCommand}.
+ */
+public class ImportCommandTest {
+
+ public static final String VALID_IMPORT_FILE_PATH = "src/data/ValidImport.xml";
+ public static final String INVALID_IMPORT_FILE_PATH = "src/data/InValidImport.txt";
+
+ @Rule
+ public TemporaryFolder testFolder = new TemporaryFolder();
+ @Rule
+ public final EventsCollectorRule eventsCollectorRule = new EventsCollectorRule();
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private StorageManager storageManager;
+
+ @Before
+ public void setUp() {
+ XmlAddressBookStorage addressBookStorage = new XmlAddressBookStorage(getTempFilePath("ab"));
+ JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(getTempFilePath("prefs"));
+ storageManager = new StorageManager(addressBookStorage, userPrefsStorage);
+ }
+
+ private String getTempFilePath(String fileName) {
+ return testFolder.getRoot().getPath() + fileName;
+ }
+
+ @Test
+ public void fileNotFound() {
+ ImportCommand importCommand = pathInCommand(INVALID_FILE);
+ assertCommandFailure(importCommand, model, ImportCommand.MESSAGE_INVALID_PATH);
+ }
+
+ /**
+ * Returns an {@code ImportCommand} with parameters {@code filePath}
+ */
+ private ImportCommand pathInCommand(String filePath) {
+ ImportCommand testCommand = new ImportCommand(filePath);
+ testCommand.setData(model, new CommandHistory(), new UndoRedoStack());
+ return testCommand;
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
index c9a350c09657..0a3e10985194 100644
--- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
@@ -7,9 +7,12 @@
import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_MATRIC_NUMBER_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.MATRIC_NUMBER_DESC_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.MATRIC_NUMBER_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
@@ -22,6 +25,8 @@
import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_MATRIC_NUMBER_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_MATRIC_NUMBER_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
@@ -36,6 +41,7 @@
import seedu.address.logic.commands.AddCommand;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
@@ -47,44 +53,53 @@ public class AddCommandParserTest {
@Test
public void parse_allFieldsPresent_success() {
- Person expectedPerson = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
+ Person expectedPerson = new PersonBuilder().withName(VALID_NAME_BOB)
+ .withMatriculationNumber(VALID_MATRIC_NUMBER_BOB).withPhone(VALID_PHONE_BOB)
.withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND).build();
// whitespace only preamble
- assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
+ assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
// multiple names - last name accepted
- assertParseSuccess(parser, NAME_DESC_AMY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ assertParseSuccess(parser, NAME_DESC_AMY + NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_BOB
+ + EMAIL_DESC_BOB
+ ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
+ // multiple matricNumbers - last matricNumber accepted
+ assertParseSuccess(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_AMY + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
+
// multiple phones - last phone accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
+ assertParseSuccess(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_AMY + PHONE_DESC_BOB
+ + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
// multiple emails - last email accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
+ assertParseSuccess(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY
+ + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
// multiple addresses - last address accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_AMY
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
+ assertParseSuccess(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ + ADDRESS_DESC_AMY + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
// multiple tags - all accepted
- Person expectedPersonMultipleTags = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
+ Person expectedPersonMultipleTags = new PersonBuilder().withName(VALID_NAME_BOB)
+ .withMatriculationNumber(VALID_MATRIC_NUMBER_BOB).withPhone(VALID_PHONE_BOB)
.withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB)
.withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND).build();
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, new AddCommand(expectedPersonMultipleTags));
+ assertParseSuccess(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, new AddCommand(expectedPersonMultipleTags));
}
@Test
public void parse_optionalFieldsMissing_success() {
// zero tags
- Person expectedPerson = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY)
+ Person expectedPerson = new PersonBuilder().withName(VALID_NAME_AMY)
+ .withMatriculationNumber(VALID_MATRIC_NUMBER_AMY).withPhone(VALID_PHONE_AMY)
.withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags().build();
- assertParseSuccess(parser, NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY,
- new AddCommand(expectedPerson));
+ assertParseSuccess(parser, NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY
+ + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY
+ + EMAIL_DESC_AMY + ADDRESS_DESC_AMY, new AddCommand(expectedPerson));
}
@Test
@@ -92,54 +107,70 @@ public void parse_compulsoryFieldMissing_failure() {
String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE);
// missing name prefix
- assertParseFailure(parser, VALID_NAME_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
+ assertParseFailure(parser, VALID_NAME_BOB + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ + ADDRESS_DESC_BOB, expectedMessage);
+
+ // missing matricNumber prefix
+ assertParseFailure(parser, NAME_DESC_BOB + VALID_MATRIC_NUMBER_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ + ADDRESS_DESC_BOB, expectedMessage);
// missing phone prefix
- assertParseFailure(parser, NAME_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
+ assertParseFailure(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB
+ + ADDRESS_DESC_BOB, expectedMessage);
// missing email prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
+ assertParseFailure(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB
+ + ADDRESS_DESC_BOB, expectedMessage);
// missing address prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
+ assertParseFailure(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ + VALID_ADDRESS_BOB, expectedMessage);
// all prefixes missing
- assertParseFailure(parser, VALID_NAME_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
+ assertParseFailure(parser, VALID_NAME_BOB + VALID_MATRIC_NUMBER_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB
+ + VALID_ADDRESS_BOB, expectedMessage);
}
@Test
public void parse_invalidValue_failure() {
// invalid name
- assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
+ assertParseFailure(parser, INVALID_NAME_DESC + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
+ TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Name.MESSAGE_NAME_CONSTRAINTS);
+ // invalid matricNumber
+ assertParseFailure(parser, NAME_DESC_BOB + INVALID_MATRIC_NUMBER_DESC
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
+ + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, MatriculationNumber.MESSAGE_MATRIC_NUMBER_CONSTRAINTS);
+
// invalid phone
- assertParseFailure(parser, NAME_DESC_BOB + INVALID_PHONE_DESC + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
+ assertParseFailure(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB
+ + INVALID_PHONE_DESC + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
+ TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Phone.MESSAGE_PHONE_CONSTRAINTS);
// invalid email
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + INVALID_EMAIL_DESC + ADDRESS_DESC_BOB
+ assertParseFailure(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + INVALID_EMAIL_DESC + ADDRESS_DESC_BOB
+ TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Email.MESSAGE_EMAIL_CONSTRAINTS);
// invalid address
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC
+ assertParseFailure(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC
+ TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Address.MESSAGE_ADDRESS_CONSTRAINTS);
// invalid tag
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
+ assertParseFailure(parser, NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
+ INVALID_TAG_DESC + VALID_TAG_FRIEND, Tag.MESSAGE_TAG_CONSTRAINTS);
// two invalid values, only first invalid value reported
- assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC,
+ assertParseFailure(parser, INVALID_NAME_DESC + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC,
Name.MESSAGE_NAME_CONSTRAINTS);
// non-empty preamble
- assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND,
String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
}
diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
index 7466da232666..fa4b70d70db2 100644
--- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
@@ -20,6 +20,7 @@
import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
+import seedu.address.logic.commands.EmailCommand;
import seedu.address.logic.commands.ExitCommand;
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.commands.HelpCommand;
@@ -29,7 +30,7 @@
import seedu.address.logic.commands.SelectCommand;
import seedu.address.logic.commands.UndoCommand;
import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.person.InfoContainsKeywordsPredicate;
import seedu.address.model.person.Person;
import seedu.address.testutil.EditPersonDescriptorBuilder;
import seedu.address.testutil.PersonBuilder;
@@ -48,12 +49,34 @@ public void parseCommand_add() throws Exception {
assertEquals(new AddCommand(person), command);
}
+ @Test
+ public void parseCommand_add_alias() throws Exception {
+ Person person = new PersonBuilder().build();
+ AddCommand command = (AddCommand) parser.parseCommand(AddCommand.COMMAND_ALIAS + " "
+ + PersonUtil.getPersonDetails(person));
+ assertEquals(new AddCommand(person), command);
+ }
+
+ @Test
+ public void parseCommand_add_sign() throws Exception {
+ Person person = new PersonBuilder().build();
+ AddCommand command = (AddCommand) parser.parseCommand(AddCommand.COMMAND_SIGN + " "
+ + PersonUtil.getPersonDetails(person));
+ assertEquals(new AddCommand(person), command);
+ }
+
@Test
public void parseCommand_clear() throws Exception {
assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD) instanceof ClearCommand);
assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD + " 3") instanceof ClearCommand);
}
+ @Test
+ public void parseCommand_clear_alias() throws Exception {
+ assertTrue(parser.parseCommand(ClearCommand.COMMAND_ALIAS) instanceof ClearCommand);
+ assertTrue(parser.parseCommand(ClearCommand.COMMAND_ALIAS + " 3") instanceof ClearCommand);
+ }
+
@Test
public void parseCommand_delete() throws Exception {
DeleteCommand command = (DeleteCommand) parser.parseCommand(
@@ -61,6 +84,27 @@ public void parseCommand_delete() throws Exception {
assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command);
}
+ @Test
+ public void parseCommand_delete_alias() throws Exception {
+ DeleteCommand command = (DeleteCommand) parser.parseCommand(
+ DeleteCommand.COMMAND_ALIAS + " " + INDEX_FIRST_PERSON.getOneBased());
+ assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command);
+ }
+
+ @Test
+ public void parseCommand_delete_sign() throws Exception {
+ DeleteCommand command = (DeleteCommand) parser.parseCommand(
+ DeleteCommand.COMMAND_SIGN + " " + INDEX_FIRST_PERSON.getOneBased());
+ assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command);
+ }
+
+ @Test
+ public void parseCommand_email() throws Exception {
+ EmailCommand command = (EmailCommand) parser.parseCommand(
+ EmailCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased());
+ assertEquals(new EmailCommand(INDEX_FIRST_PERSON), command);
+ }
+
@Test
public void parseCommand_edit() throws Exception {
Person person = new PersonBuilder().build();
@@ -81,7 +125,15 @@ public void parseCommand_find() throws Exception {
List keywords = Arrays.asList("foo", "bar", "baz");
FindCommand command = (FindCommand) parser.parseCommand(
FindCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" ")));
- assertEquals(new FindCommand(new NameContainsKeywordsPredicate(keywords)), command);
+ assertEquals(new FindCommand(new InfoContainsKeywordsPredicate(keywords)), command);
+ }
+
+ @Test
+ public void parseCommand_find_alias() throws Exception {
+ List keywords = Arrays.asList("foo", "bar", "baz");
+ FindCommand command = (FindCommand) parser.parseCommand(
+ FindCommand.COMMAND_ALIAS + " " + keywords.stream().collect(Collectors.joining(" ")));
+ assertEquals(new FindCommand(new InfoContainsKeywordsPredicate(keywords)), command);
}
@Test
@@ -90,6 +142,12 @@ public void parseCommand_help() throws Exception {
assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD + " 3") instanceof HelpCommand);
}
+ @Test
+ public void parseCommand_help_sign() throws Exception {
+ assertTrue(parser.parseCommand(HelpCommand.COMMAND_SIGN) instanceof HelpCommand);
+ assertTrue(parser.parseCommand(HelpCommand.COMMAND_SIGN + " 3") instanceof HelpCommand);
+ }
+
@Test
public void parseCommand_history() throws Exception {
assertTrue(parser.parseCommand(HistoryCommand.COMMAND_WORD) instanceof HistoryCommand);
@@ -103,12 +161,24 @@ public void parseCommand_history() throws Exception {
}
}
+ @Test
+ public void parseCommand_history_alias() throws Exception {
+ assertTrue(parser.parseCommand(HistoryCommand.COMMAND_ALIAS) instanceof HistoryCommand);
+ assertTrue(parser.parseCommand(HistoryCommand.COMMAND_ALIAS + " 3") instanceof HistoryCommand);
+ }
+
@Test
public void parseCommand_list() throws Exception {
assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand);
assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand);
}
+ @Test
+ public void parseCommand_list_alias() throws Exception {
+ assertTrue(parser.parseCommand(ListCommand.COMMAND_ALIAS) instanceof ListCommand);
+ assertTrue(parser.parseCommand(ListCommand.COMMAND_ALIAS + " 3") instanceof ListCommand);
+ }
+
@Test
public void parseCommand_select() throws Exception {
SelectCommand command = (SelectCommand) parser.parseCommand(
@@ -116,18 +186,37 @@ public void parseCommand_select() throws Exception {
assertEquals(new SelectCommand(INDEX_FIRST_PERSON), command);
}
+ @Test
+ public void parseCommand_select_alias() throws Exception {
+ SelectCommand command = (SelectCommand) parser.parseCommand(
+ SelectCommand.COMMAND_ALIAS + " " + INDEX_FIRST_PERSON.getOneBased());
+ assertEquals(new SelectCommand(INDEX_FIRST_PERSON), command);
+ }
+
@Test
public void parseCommand_redoCommandWord_returnsRedoCommand() throws Exception {
assertTrue(parser.parseCommand(RedoCommand.COMMAND_WORD) instanceof RedoCommand);
assertTrue(parser.parseCommand("redo 1") instanceof RedoCommand);
}
+ @Test
+ public void parseCommand_redoCommandAlias_returnsRedoCommand() throws Exception {
+ assertTrue(parser.parseCommand(RedoCommand.COMMAND_ALIAS) instanceof RedoCommand);
+ assertTrue(parser.parseCommand(RedoCommand.COMMAND_ALIAS + " 1") instanceof RedoCommand);
+ }
+
@Test
public void parseCommand_undoCommandWord_returnsUndoCommand() throws Exception {
assertTrue(parser.parseCommand(UndoCommand.COMMAND_WORD) instanceof UndoCommand);
assertTrue(parser.parseCommand("undo 3") instanceof UndoCommand);
}
+ @Test
+ public void parseCommand_undoCommandAlias_returnsUndoCommand() throws Exception {
+ assertTrue(parser.parseCommand(UndoCommand.COMMAND_ALIAS) instanceof UndoCommand);
+ assertTrue(parser.parseCommand(UndoCommand.COMMAND_ALIAS + " 3") instanceof UndoCommand);
+ }
+
@Test
public void parseCommand_unrecognisedInput_throwsParseException() throws Exception {
thrown.expect(ParseException.class);
diff --git a/src/test/java/seedu/address/logic/parser/EmailCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EmailCommandParserTest.java
new file mode 100644
index 000000000000..4f1240baf2e6
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/EmailCommandParserTest.java
@@ -0,0 +1,32 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+
+import org.junit.Test;
+
+import seedu.address.logic.commands.EmailCommand;
+
+/**
+ * As we are only doing white-box testing, our test cases do not cover path variations
+ * outside of the EmailCommand code. For example, inputs "1" and "1 abc" take the
+ * same path through the EmailCommand, and therefore we test only one of them.
+ * The path variation for those two cases occur inside the ParserUtil, and
+ * therefore should be covered by the ParserUtilTest.
+ */
+public class EmailCommandParserTest {
+
+ private EmailCommandParser parser = new EmailCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsEmailCommand() {
+ assertParseSuccess(parser, "1", new EmailCommand(INDEX_FIRST_PERSON));
+ }
+
+ @Test
+ public void parse_invalidArgs_throwsParseException() {
+ assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, EmailCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
index e65143d3b7b0..04fbdddea7b2 100644
--- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
@@ -9,7 +9,7 @@
import org.junit.Test;
import seedu.address.logic.commands.FindCommand;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.person.InfoContainsKeywordsPredicate;
public class FindCommandParserTest {
@@ -24,7 +24,7 @@ public void parse_emptyArg_throwsParseException() {
public void parse_validArgs_returnsFindCommand() {
// no leading and trailing whitespaces
FindCommand expectedFindCommand =
- new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")));
+ new FindCommand(new InfoContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")));
assertParseSuccess(parser, "Alice Bob", expectedFindCommand);
// multiple whitespaces between keywords
diff --git a/src/test/java/seedu/address/logic/parser/ImportCommandParserTest.java b/src/test/java/seedu/address/logic/parser/ImportCommandParserTest.java
new file mode 100644
index 000000000000..7e9e9b3480a2
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/ImportCommandParserTest.java
@@ -0,0 +1,23 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import seedu.address.logic.commands.ImportCommand;
+
+public class ImportCommandParserTest {
+ @Rule
+ public TemporaryFolder testFolder = new TemporaryFolder();
+
+ private ImportCommandParser parser = new ImportCommandParser();
+
+ @Test
+ public void parse_noFile_throwsParseException() {
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, ImportCommand.MESSAGE_USAGE);
+ assertParseFailure(parser, " ", expectedMessage);
+ }
+}
diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java
index 59ce1b83693a..62d71a8ac1bf 100644
--- a/src/test/java/seedu/address/model/ModelManagerTest.java
+++ b/src/test/java/seedu/address/model/ModelManagerTest.java
@@ -12,7 +12,7 @@
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.person.InfoContainsKeywordsPredicate;
import seedu.address.testutil.AddressBookBuilder;
public class ModelManagerTest {
@@ -51,7 +51,7 @@ public void equals() {
// different filteredList -> returns false
String[] keywords = ALICE.getName().fullName.split("\\s+");
- modelManager.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(keywords)));
+ modelManager.updateFilteredPersonList(new InfoContainsKeywordsPredicate(Arrays.asList(keywords)));
assertFalse(modelManager.equals(new ModelManager(addressBook, userPrefs)));
// resets modelManager to initial state for upcoming tests
diff --git a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/InfoContainsKeywordsPredicateTest.java
similarity index 76%
rename from src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java
rename to src/test/java/seedu/address/model/person/InfoContainsKeywordsPredicateTest.java
index 76841215e3a0..ff1d89956356 100644
--- a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java
+++ b/src/test/java/seedu/address/model/person/InfoContainsKeywordsPredicateTest.java
@@ -11,21 +11,21 @@
import seedu.address.testutil.PersonBuilder;
-public class NameContainsKeywordsPredicateTest {
+public class InfoContainsKeywordsPredicateTest {
@Test
public void equals() {
List firstPredicateKeywordList = Collections.singletonList("first");
List secondPredicateKeywordList = Arrays.asList("first", "second");
- NameContainsKeywordsPredicate firstPredicate = new NameContainsKeywordsPredicate(firstPredicateKeywordList);
- NameContainsKeywordsPredicate secondPredicate = new NameContainsKeywordsPredicate(secondPredicateKeywordList);
+ InfoContainsKeywordsPredicate firstPredicate = new InfoContainsKeywordsPredicate(firstPredicateKeywordList);
+ InfoContainsKeywordsPredicate secondPredicate = new InfoContainsKeywordsPredicate(secondPredicateKeywordList);
// same object -> returns true
assertTrue(firstPredicate.equals(firstPredicate));
// same values -> returns true
- NameContainsKeywordsPredicate firstPredicateCopy = new NameContainsKeywordsPredicate(firstPredicateKeywordList);
+ InfoContainsKeywordsPredicate firstPredicateCopy = new InfoContainsKeywordsPredicate(firstPredicateKeywordList);
assertTrue(firstPredicate.equals(firstPredicateCopy));
// different types -> returns false
@@ -41,34 +41,34 @@ public void equals() {
@Test
public void test_nameContainsKeywords_returnsTrue() {
// One keyword
- NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.singletonList("Alice"));
+ InfoContainsKeywordsPredicate predicate = new InfoContainsKeywordsPredicate(Collections.singletonList("Alice"));
assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
// Multiple keywords
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"));
+ predicate = new InfoContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"));
assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
// Only one matching keyword
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("Bob", "Carol"));
+ predicate = new InfoContainsKeywordsPredicate(Arrays.asList("Bob", "Carol"));
assertTrue(predicate.test(new PersonBuilder().withName("Alice Carol").build()));
// Mixed-case keywords
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB"));
+ predicate = new InfoContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB"));
assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
}
@Test
public void test_nameDoesNotContainKeywords_returnsFalse() {
// Zero keywords
- NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.emptyList());
+ InfoContainsKeywordsPredicate predicate = new InfoContainsKeywordsPredicate(Collections.emptyList());
assertFalse(predicate.test(new PersonBuilder().withName("Alice").build()));
// Non-matching keyword
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("Carol"));
+ predicate = new InfoContainsKeywordsPredicate(Arrays.asList("Carol"));
assertFalse(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
// Keywords match phone, email and address, but does not match name
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("12345", "alice@email.com", "Main", "Street"));
+ predicate = new InfoContainsKeywordsPredicate(Arrays.asList("12345", "alice@email.com", "Main", "Street"));
assertFalse(predicate.test(new PersonBuilder().withName("Alice").withPhone("12345")
.withEmail("alice@email.com").withAddress("Main Street").build()));
}
diff --git a/src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java b/src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java
index c3c91a5c27a7..6656417ef4b8 100644
--- a/src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java
+++ b/src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java
@@ -13,18 +13,21 @@
import seedu.address.commons.exceptions.IllegalValueException;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Phone;
import seedu.address.testutil.Assert;
public class XmlAdaptedPersonTest {
private static final String INVALID_NAME = "R@chel";
+ private static final String INVALID_MATRIC_NUMBER = "E12345678";
private static final String INVALID_PHONE = "+651234";
private static final String INVALID_ADDRESS = " ";
private static final String INVALID_EMAIL = "example.com";
private static final String INVALID_TAG = "#friend";
private static final String VALID_NAME = BENSON.getName().toString();
+ private static final String VALID_MATRIC_NUMBER = BENSON.getMatricNumber().toString();
private static final String VALID_PHONE = BENSON.getPhone().toString();
private static final String VALID_EMAIL = BENSON.getEmail().toString();
private static final String VALID_ADDRESS = BENSON.getAddress().toString();
@@ -41,29 +44,50 @@ public void toModelType_validPersonDetails_returnsPerson() throws Exception {
@Test
public void toModelType_invalidName_throwsIllegalValueException() {
XmlAdaptedPerson person =
- new XmlAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ new XmlAdaptedPerson(INVALID_NAME, VALID_MATRIC_NUMBER, VALID_PHONE,
+ VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
String expectedMessage = Name.MESSAGE_NAME_CONSTRAINTS;
Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
}
@Test
public void toModelType_nullName_throwsIllegalValueException() {
- XmlAdaptedPerson person = new XmlAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ XmlAdaptedPerson person = new XmlAdaptedPerson(null, VALID_MATRIC_NUMBER, VALID_PHONE,
+ VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName());
Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
}
+ @Test
+ public void toModelType_invalidMatricNumber_throwsIllegalValueException() {
+ XmlAdaptedPerson person =
+ new XmlAdaptedPerson(VALID_NAME, INVALID_MATRIC_NUMBER,
+ VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ String expectedMessage = MatriculationNumber.MESSAGE_MATRIC_NUMBER_CONSTRAINTS;
+ Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullMatricNumber_throwsIllegalValueException() {
+ XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, null, VALID_PHONE,
+ VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, MatriculationNumber.class.getSimpleName());
+ Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
+ }
+
@Test
public void toModelType_invalidPhone_throwsIllegalValueException() {
XmlAdaptedPerson person =
- new XmlAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ new XmlAdaptedPerson(VALID_NAME, VALID_MATRIC_NUMBER,
+ INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
String expectedMessage = Phone.MESSAGE_PHONE_CONSTRAINTS;
Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
}
@Test
public void toModelType_nullPhone_throwsIllegalValueException() {
- XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, VALID_MATRIC_NUMBER, null,
+ VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName());
Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
}
@@ -71,14 +95,16 @@ public void toModelType_nullPhone_throwsIllegalValueException() {
@Test
public void toModelType_invalidEmail_throwsIllegalValueException() {
XmlAdaptedPerson person =
- new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+ new XmlAdaptedPerson(VALID_NAME, VALID_MATRIC_NUMBER, VALID_PHONE,
+ INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
String expectedMessage = Email.MESSAGE_EMAIL_CONSTRAINTS;
Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
}
@Test
public void toModelType_nullEmail_throwsIllegalValueException() {
- XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS);
+ XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, VALID_MATRIC_NUMBER, VALID_PHONE,
+ null, VALID_ADDRESS, VALID_TAGS);
String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName());
Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
}
@@ -86,14 +112,16 @@ public void toModelType_nullEmail_throwsIllegalValueException() {
@Test
public void toModelType_invalidAddress_throwsIllegalValueException() {
XmlAdaptedPerson person =
- new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, VALID_TAGS);
+ new XmlAdaptedPerson(VALID_NAME, VALID_MATRIC_NUMBER,
+ VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, VALID_TAGS);
String expectedMessage = Address.MESSAGE_ADDRESS_CONSTRAINTS;
Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
}
@Test
public void toModelType_nullAddress_throwsIllegalValueException() {
- XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS);
+ XmlAdaptedPerson person = new XmlAdaptedPerson(VALID_NAME, VALID_MATRIC_NUMBER, VALID_PHONE,
+ VALID_EMAIL, null, VALID_TAGS);
String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName());
Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
}
@@ -103,7 +131,8 @@ public void toModelType_invalidTags_throwsIllegalValueException() {
List invalidTags = new ArrayList<>(VALID_TAGS);
invalidTags.add(new XmlAdaptedTag(INVALID_TAG));
XmlAdaptedPerson person =
- new XmlAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags);
+ new XmlAdaptedPerson(VALID_NAME, VALID_MATRIC_NUMBER, VALID_PHONE,
+ VALID_EMAIL, VALID_ADDRESS, invalidTags);
Assert.assertThrows(IllegalValueException.class, person::toModelType);
}
diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
index 4584bd5044e1..ca0a5ec9d06e 100644
--- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
+++ b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
@@ -7,6 +7,7 @@
import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
@@ -33,6 +34,7 @@ public EditPersonDescriptorBuilder(EditPersonDescriptor descriptor) {
public EditPersonDescriptorBuilder(Person person) {
descriptor = new EditPersonDescriptor();
descriptor.setName(person.getName());
+ descriptor.setMatricNumber(person.getMatricNumber());
descriptor.setPhone(person.getPhone());
descriptor.setEmail(person.getEmail());
descriptor.setAddress(person.getAddress());
@@ -47,6 +49,14 @@ public EditPersonDescriptorBuilder withName(String name) {
return this;
}
+ /**
+ * Sets the {@code MatriculationNumber} of the {@code EditPersonDescriptor} that we are building.
+ */
+ public EditPersonDescriptorBuilder withMatricNumber(String matricNumber) {
+ descriptor.setMatricNumber(new MatriculationNumber(matricNumber));
+ return this;
+ }
+
/**
* Sets the {@code Phone} of the {@code EditPersonDescriptor} that we are building.
*/
diff --git a/src/test/java/seedu/address/testutil/PersonBuilder.java b/src/test/java/seedu/address/testutil/PersonBuilder.java
index b124fc1d73b1..01ec46f7ee56 100644
--- a/src/test/java/seedu/address/testutil/PersonBuilder.java
+++ b/src/test/java/seedu/address/testutil/PersonBuilder.java
@@ -5,6 +5,7 @@
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
@@ -17,12 +18,14 @@
public class PersonBuilder {
public static final String DEFAULT_NAME = "Alice Pauline";
+ public static final String DEFAULT_MATRIC_NUMBER = "A0123456I";
public static final String DEFAULT_PHONE = "85355255";
public static final String DEFAULT_EMAIL = "alice@gmail.com";
public static final String DEFAULT_ADDRESS = "123, Jurong West Ave 6, #08-111";
public static final String DEFAULT_TAGS = "friends";
private Name name;
+ private MatriculationNumber matricNumber;
private Phone phone;
private Email email;
private Address address;
@@ -30,6 +33,7 @@ public class PersonBuilder {
public PersonBuilder() {
name = new Name(DEFAULT_NAME);
+ matricNumber = new MatriculationNumber(DEFAULT_MATRIC_NUMBER);
phone = new Phone(DEFAULT_PHONE);
email = new Email(DEFAULT_EMAIL);
address = new Address(DEFAULT_ADDRESS);
@@ -41,6 +45,7 @@ public PersonBuilder() {
*/
public PersonBuilder(Person personToCopy) {
name = personToCopy.getName();
+ matricNumber = personToCopy.getMatricNumber();
phone = personToCopy.getPhone();
email = personToCopy.getEmail();
address = personToCopy.getAddress();
@@ -71,6 +76,14 @@ public PersonBuilder withAddress(String address) {
return this;
}
+ /**
+ * Sets the {@code MatriculationNumber} of the {@code Person} that we are building.
+ */
+ public PersonBuilder withMatriculationNumber(String matricNumber) {
+ this.matricNumber = new MatriculationNumber(matricNumber);
+ return this;
+ }
+
/**
* Sets the {@code Phone} of the {@code Person} that we are building.
*/
@@ -88,7 +101,7 @@ public PersonBuilder withEmail(String email) {
}
public Person build() {
- return new Person(name, phone, email, address, tags);
+ return new Person(name, matricNumber, phone, email, address, tags);
}
}
diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java
index 642d4f174514..3faaa87eca7f 100644
--- a/src/test/java/seedu/address/testutil/PersonUtil.java
+++ b/src/test/java/seedu/address/testutil/PersonUtil.java
@@ -2,6 +2,7 @@
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
@@ -27,6 +28,7 @@ public static String getAddCommand(Person person) {
public static String getPersonDetails(Person person) {
StringBuilder sb = new StringBuilder();
sb.append(PREFIX_NAME + person.getName().fullName + " ");
+ sb.append(PREFIX_MATRIC_NUMBER + person.getMatricNumber().value + " ");
sb.append(PREFIX_PHONE + person.getPhone().value + " ");
sb.append(PREFIX_EMAIL + person.getEmail().value + " ");
sb.append(PREFIX_ADDRESS + person.getAddress().value + " ");
diff --git a/src/test/java/seedu/address/testutil/TypicalImportFile.java b/src/test/java/seedu/address/testutil/TypicalImportFile.java
new file mode 100644
index 000000000000..54cd99ff776d
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/TypicalImportFile.java
@@ -0,0 +1,72 @@
+package seedu.address.testutil;
+
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import seedu.address.model.AddressBook;
+import seedu.address.model.person.Person;
+import seedu.address.model.person.exceptions.DuplicatePersonException;
+
+/**
+ * A utility class containing a list of {@code Person} objects to be used in tests for import.
+ */
+public class TypicalImportFile {
+ //data for import files
+ public static final Person ALICE = new PersonBuilder().withName("Alice Pauline")
+ .withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com")
+ .withPhone("85355255")
+ .withTags("friends").build();
+ public static final Person BENSON = new PersonBuilder().withName("Benson Meier")
+ .withAddress("311, Clementi Ave 2, #02-25")
+ .withEmail("johnd@example.com").withPhone("98765432")
+ .withTags("owesMoney", "friends").build();
+ public static final Person ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("9482224")
+ .withEmail("werner@example.com").withAddress("michegan ave").build();
+ public static final Person FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("9482427")
+ .withEmail("lydia@example.com").withAddress("little tokyo").build();
+ public static final Person GEORGE = new PersonBuilder().withName("George Best").withPhone("9482442")
+ .withEmail("anna@example.com").withAddress("4th street").build();
+
+ public static final Person HOON = new PersonBuilder().withName("Hoon Meier").withPhone("8482424")
+ .withEmail("stefan@example.com").withAddress("little india").build();
+ public static final Person IDA = new PersonBuilder().withName("Ida Mueller").withPhone("8482131")
+ .withEmail("hans@example.com").withAddress("chicago ave").build();
+
+ // Manually added - Person's details found in {@code CommandTestUtil}
+ public static final Person AMY = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY)
+ .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
+ public static final Person BOB = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
+ .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND)
+ .build();
+
+ private TypicalImportFile() {
+ }
+
+ public static List getTypicalPersons() {
+ return new ArrayList<>(Arrays.asList(ALICE, BENSON, ELLE, FIONA, GEORGE, HOON, IDA, AMY, BOB));
+ }
+
+ public static AddressBook getTypicalImportFile() {
+ AddressBook importFile = new AddressBook();
+ for (Person person: getTypicalPersons()) {
+ try {
+ importFile.addPerson(person);
+ } catch (DuplicatePersonException e) {
+ e.printStackTrace();
+ }
+ }
+ return importFile;
+ }
+}
diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java
index 6d7bdbfc55ed..c86c5cbf327a 100644
--- a/src/test/java/seedu/address/testutil/TypicalPersons.java
+++ b/src/test/java/seedu/address/testutil/TypicalPersons.java
@@ -4,6 +4,8 @@
import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_MATRIC_NUMBER_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_MATRIC_NUMBER_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
@@ -25,34 +27,45 @@
public class TypicalPersons {
public static final Person ALICE = new PersonBuilder().withName("Alice Pauline")
+ .withMatriculationNumber("A1234567X")
.withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com")
.withPhone("85355255")
.withTags("friends").build();
public static final Person BENSON = new PersonBuilder().withName("Benson Meier")
+ .withMatriculationNumber("A2234567X")
.withAddress("311, Clementi Ave 2, #02-25")
.withEmail("johnd@example.com").withPhone("98765432")
.withTags("owesMoney", "friends").build();
public static final Person CARL = new PersonBuilder().withName("Carl Kurz").withPhone("95352563")
+ .withMatriculationNumber("A3234567X")
.withEmail("heinz@example.com").withAddress("wall street").build();
public static final Person DANIEL = new PersonBuilder().withName("Daniel Meier").withPhone("87652533")
+ .withMatriculationNumber("A4234567X")
.withEmail("cornelia@example.com").withAddress("10th street").build();
public static final Person ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("9482224")
+ .withMatriculationNumber("A5234567X")
.withEmail("werner@example.com").withAddress("michegan ave").build();
public static final Person FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("9482427")
+ .withMatriculationNumber("A6234567X")
.withEmail("lydia@example.com").withAddress("little tokyo").build();
public static final Person GEORGE = new PersonBuilder().withName("George Best").withPhone("9482442")
+ .withMatriculationNumber("A7234567X")
.withEmail("anna@example.com").withAddress("4th street").build();
// Manually added
public static final Person HOON = new PersonBuilder().withName("Hoon Meier").withPhone("8482424")
+ .withMatriculationNumber("A8234567X")
.withEmail("stefan@example.com").withAddress("little india").build();
public static final Person IDA = new PersonBuilder().withName("Ida Mueller").withPhone("8482131")
+ .withMatriculationNumber("A9234567X")
.withEmail("hans@example.com").withAddress("chicago ave").build();
// Manually added - Person's details found in {@code CommandTestUtil}
- public static final Person AMY = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY)
+ public static final Person AMY = new PersonBuilder().withName(VALID_NAME_AMY)
+ .withMatriculationNumber(VALID_MATRIC_NUMBER_AMY).withPhone(VALID_PHONE_AMY)
.withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
- public static final Person BOB = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
+ public static final Person BOB = new PersonBuilder().withName(VALID_NAME_BOB)
+ .withMatriculationNumber(VALID_MATRIC_NUMBER_BOB).withPhone(VALID_PHONE_BOB)
.withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND)
.build();
diff --git a/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java b/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java
index d21cc2fb3739..b88fe2f206b4 100644
--- a/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java
+++ b/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java
@@ -2,6 +2,7 @@
import static org.junit.Assert.assertEquals;
+import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@@ -9,11 +10,15 @@
import guitests.guihandles.PersonListPanelHandle;
import guitests.guihandles.ResultDisplayHandle;
import seedu.address.model.person.Person;
+import seedu.address.ui.PersonCard;
/**
* A set of assertion methods useful for writing GUI tests.
*/
public class GuiTestAssert {
+ private static final String LABEL_DEFAULT_STYLE = "label";
+ private static final String[] TAG_COLOR_STYLES = { "teal", "orange", "brown", "pink", "black", "grey" };
+
/**
* Asserts that {@code actualCard} displays the same values as {@code expectedCard}.
*/
@@ -24,6 +29,9 @@ public static void assertCardEquals(PersonCardHandle expectedCard, PersonCardHan
assertEquals(expectedCard.getName(), actualCard.getName());
assertEquals(expectedCard.getPhone(), actualCard.getPhone());
assertEquals(expectedCard.getTags(), actualCard.getTags());
+
+ expectedCard.getTags().forEach(tag ->
+ assertEquals(expectedCard.getTagStyleClasses(tag), actualCard.getTagStyleClasses(tag)));
}
/**
@@ -34,8 +42,46 @@ public static void assertCardDisplaysPerson(Person expectedPerson, PersonCardHan
assertEquals(expectedPerson.getPhone().value, actualCard.getPhone());
assertEquals(expectedPerson.getEmail().value, actualCard.getEmail());
assertEquals(expectedPerson.getAddress().value, actualCard.getAddress());
- assertEquals(expectedPerson.getTags().stream().map(tag -> tag.tagName).collect(Collectors.toList()),
- actualCard.getTags());
+
+ assertTagsEqual(expectedPerson, actualCard);
+ }
+
+ /**
+ * Returns the color style for {@code tagName}'s label. The tag's color is determined by looking up the color
+ * in {@code PersonCard#TAG_COLOR_STYLES}, using an index generated by the hash code of the tag's content.
+ *
+ * @see PersonCard#getTagColorStyleFor(String)
+ */
+ private static String getTagColorStyleFor(String tagName) {
+ switch (tagName) {
+ case "lecturer":
+ return "red";
+
+ case "TA":
+ return "yellow";
+
+ case "student":
+ return "blue";
+
+ case "T1":
+ return "green";
+
+ default:
+ return TAG_COLOR_STYLES[Math.abs(tagName.hashCode()) % TAG_COLOR_STYLES.length];
+ }
+ }
+
+ /**
+ * Asserts that the tags in {@code actualCard} matches all the tags in {@code expectedPerson} with the correct
+ * color.
+ */
+ private static void assertTagsEqual(Person expectedPerson, PersonCardHandle actualCard) {
+ List expectedTags = expectedPerson.getTags().stream()
+ .map(tag -> tag.tagName).collect(Collectors.toList());
+ assertEquals(expectedTags, actualCard.getTags());
+ expectedTags.forEach(tag ->
+ assertEquals(Arrays.asList(LABEL_DEFAULT_STYLE, getTagColorStyleFor(tag)),
+ actualCard.getTagStyleClasses(tag)));
}
/**
diff --git a/src/test/java/systemtests/AddCommandSystemTest.java b/src/test/java/systemtests/AddCommandSystemTest.java
index 3254b60154c4..2de022031efa 100644
--- a/src/test/java/systemtests/AddCommandSystemTest.java
+++ b/src/test/java/systemtests/AddCommandSystemTest.java
@@ -7,9 +7,12 @@
import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_MATRIC_NUMBER_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.MATRIC_NUMBER_DESC_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.MATRIC_NUMBER_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
@@ -20,6 +23,8 @@
import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_MATRIC_NUMBER_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_MATRIC_NUMBER_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
@@ -44,6 +49,7 @@
import seedu.address.model.Model;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
@@ -64,8 +70,8 @@ public void add() throws Exception {
* -> added
*/
Person toAdd = AMY;
- String command = " " + AddCommand.COMMAND_WORD + " " + NAME_DESC_AMY + " " + PHONE_DESC_AMY + " "
- + EMAIL_DESC_AMY + " " + ADDRESS_DESC_AMY + " " + TAG_DESC_FRIEND + " ";
+ String command = " " + AddCommand.COMMAND_WORD + " " + NAME_DESC_AMY + " " + MATRIC_NUMBER_DESC_AMY + " "
+ + PHONE_DESC_AMY + " " + EMAIL_DESC_AMY + " " + ADDRESS_DESC_AMY + " " + TAG_DESC_FRIEND + " ";
assertCommandSuccess(command, toAdd);
/* Case: undo adding Amy to the list -> Amy deleted */
@@ -80,31 +86,43 @@ public void add() throws Exception {
assertCommandSuccess(command, model, expectedResultMessage);
/* Case: add a person with all fields same as another person in the address book except name -> added */
- toAdd = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY)
+ toAdd = new PersonBuilder().withName(VALID_NAME_BOB).withMatriculationNumber(VALID_MATRIC_NUMBER_AMY)
+ .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY)
.withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
- command = AddCommand.COMMAND_WORD + NAME_DESC_BOB + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY
- + TAG_DESC_FRIEND;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_BOB + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY
+ + ADDRESS_DESC_AMY + TAG_DESC_FRIEND;
assertCommandSuccess(command, toAdd);
/* Case: add a person with all fields same as another person in the address book except phone -> added */
- toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY)
+ toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withMatriculationNumber(VALID_MATRIC_NUMBER_AMY)
+ .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY)
.withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_AMY + ADDRESS_DESC_AMY
- + TAG_DESC_FRIEND;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_AMY
+ + ADDRESS_DESC_AMY + TAG_DESC_FRIEND;
assertCommandSuccess(command, toAdd);
/* Case: add a person with all fields same as another person in the address book except email -> added */
- toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_BOB)
+ toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withMatriculationNumber(VALID_MATRIC_NUMBER_AMY)
+ .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_BOB)
.withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_BOB + ADDRESS_DESC_AMY
- + TAG_DESC_FRIEND;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_BOB
+ + ADDRESS_DESC_AMY + TAG_DESC_FRIEND;
assertCommandSuccess(command, toAdd);
/* Case: add a person with all fields same as another person in the address book except address -> added */
- toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY)
+ toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withMatriculationNumber(VALID_MATRIC_NUMBER_AMY)
+ .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY)
.withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND).build();
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_BOB
- + TAG_DESC_FRIEND;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY
+ + ADDRESS_DESC_BOB + TAG_DESC_FRIEND;
+ assertCommandSuccess(command, toAdd);
+
+ /* Case: add a person with all fields same as another person in the address book except matricNumber -> added */
+ toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withMatriculationNumber(VALID_MATRIC_NUMBER_BOB)
+ .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY)
+ .withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_AMY + EMAIL_DESC_AMY
+ + ADDRESS_DESC_AMY + TAG_DESC_FRIEND;
assertCommandSuccess(command, toAdd);
/* Case: add to empty address book -> added */
@@ -113,8 +131,8 @@ public void add() throws Exception {
/* Case: add a person with tags, command with parameters in random order -> added */
toAdd = BOB;
- command = AddCommand.COMMAND_WORD + TAG_DESC_FRIEND + PHONE_DESC_BOB + ADDRESS_DESC_BOB + NAME_DESC_BOB
- + TAG_DESC_HUSBAND + EMAIL_DESC_BOB;
+ command = AddCommand.COMMAND_WORD + TAG_DESC_FRIEND + MATRIC_NUMBER_DESC_BOB + PHONE_DESC_BOB
+ + ADDRESS_DESC_BOB + NAME_DESC_BOB + TAG_DESC_HUSBAND + EMAIL_DESC_BOB;
assertCommandSuccess(command, toAdd);
/* Case: add a person, missing tags -> added */
@@ -146,19 +164,23 @@ public void add() throws Exception {
assertCommandFailure(command, AddCommand.MESSAGE_DUPLICATE_PERSON);
/* Case: missing name -> rejected */
- command = AddCommand.COMMAND_WORD + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
+ command = AddCommand.COMMAND_WORD + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
/* Case: missing phone -> rejected */
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
/* Case: missing email -> rejected */
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + ADDRESS_DESC_AMY;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY + ADDRESS_DESC_AMY;
assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
/* Case: missing address -> rejected */
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY;
+ assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+
+ /* Case: missing matricNumber -> rejected */
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
/* Case: invalid keyword -> rejected */
@@ -166,24 +188,33 @@ public void add() throws Exception {
assertCommandFailure(command, Messages.MESSAGE_UNKNOWN_COMMAND);
/* Case: invalid name -> rejected */
- command = AddCommand.COMMAND_WORD + INVALID_NAME_DESC + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
+ command = AddCommand.COMMAND_WORD + INVALID_NAME_DESC + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY
+ + EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
assertCommandFailure(command, Name.MESSAGE_NAME_CONSTRAINTS);
/* Case: invalid phone -> rejected */
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + INVALID_PHONE_DESC + EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + INVALID_PHONE_DESC
+ + EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
assertCommandFailure(command, Phone.MESSAGE_PHONE_CONSTRAINTS);
/* Case: invalid email -> rejected */
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + INVALID_EMAIL_DESC + ADDRESS_DESC_AMY;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY
+ + INVALID_EMAIL_DESC + ADDRESS_DESC_AMY;
assertCommandFailure(command, Email.MESSAGE_EMAIL_CONSTRAINTS);
/* Case: invalid address -> rejected */
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + INVALID_ADDRESS_DESC;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY
+ + EMAIL_DESC_AMY + INVALID_ADDRESS_DESC;
assertCommandFailure(command, Address.MESSAGE_ADDRESS_CONSTRAINTS);
+ /* Case: invalid matricNumber -> rejected */
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + INVALID_MATRIC_NUMBER_DESC + PHONE_DESC_AMY
+ + EMAIL_DESC_AMY + INVALID_ADDRESS_DESC;
+ assertCommandFailure(command, MatriculationNumber.MESSAGE_MATRIC_NUMBER_CONSTRAINTS);
+
/* Case: invalid tag -> rejected */
- command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY
- + INVALID_TAG_DESC;
+ command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY
+ + ADDRESS_DESC_AMY + INVALID_TAG_DESC;
assertCommandFailure(command, Tag.MESSAGE_TAG_CONSTRAINTS);
}
diff --git a/src/test/java/systemtests/EditCommandSystemTest.java b/src/test/java/systemtests/EditCommandSystemTest.java
index 820933203dd9..8230f87f0e5c 100644
--- a/src/test/java/systemtests/EditCommandSystemTest.java
+++ b/src/test/java/systemtests/EditCommandSystemTest.java
@@ -8,9 +8,12 @@
import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_MATRIC_NUMBER_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.MATRIC_NUMBER_DESC_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.MATRIC_NUMBER_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
@@ -19,6 +22,7 @@
import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND;
import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_MATRIC_NUMBER_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
@@ -40,6 +44,7 @@
import seedu.address.model.Model;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.MatriculationNumber;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
@@ -62,8 +67,10 @@ public void edit() throws Exception {
*/
Index index = INDEX_FIRST_PERSON;
String command = " " + EditCommand.COMMAND_WORD + " " + index.getOneBased() + " " + NAME_DESC_BOB + " "
- + PHONE_DESC_BOB + " " + EMAIL_DESC_BOB + " " + ADDRESS_DESC_BOB + " " + TAG_DESC_HUSBAND + " ";
- Person editedPerson = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
+ + MATRIC_NUMBER_DESC_BOB + " " + PHONE_DESC_BOB + " " + EMAIL_DESC_BOB + " " + ADDRESS_DESC_BOB
+ + " " + TAG_DESC_HUSBAND + " ";
+ Person editedPerson = new PersonBuilder().withName(VALID_NAME_BOB)
+ .withMatriculationNumber(VALID_MATRIC_NUMBER_BOB).withPhone(VALID_PHONE_BOB)
.withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build();
assertCommandSuccess(command, index, editedPerson);
@@ -80,8 +87,8 @@ public void edit() throws Exception {
assertCommandSuccess(command, model, expectedResultMessage);
/* Case: edit a person with new values same as existing values -> edited */
- command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND;
+ command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND;
assertCommandSuccess(command, index, BOB);
/* Case: edit some fields -> edited */
@@ -124,8 +131,8 @@ public void edit() throws Exception {
showAllPersons();
index = INDEX_FIRST_PERSON;
selectPerson(index);
- command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY
- + ADDRESS_DESC_AMY + TAG_DESC_FRIEND;
+ command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_AMY + MATRIC_NUMBER_DESC_AMY
+ + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + TAG_DESC_FRIEND;
// this can be misleading: card selection actually remains unchanged but the
// browser's url is updated to reflect the new person's name
assertCommandSuccess(command, index, AMY, index);
@@ -157,6 +164,11 @@ public void edit() throws Exception {
assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased() + INVALID_NAME_DESC,
Name.MESSAGE_NAME_CONSTRAINTS);
+ /* Case: invalid matricNumber -> rejected */
+ assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()
+ + INVALID_MATRIC_NUMBER_DESC, MatriculationNumber.MESSAGE_MATRIC_NUMBER_CONSTRAINTS);
+
+
/* Case: invalid phone -> rejected */
assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased() + INVALID_PHONE_DESC,
Phone.MESSAGE_PHONE_CONSTRAINTS);
@@ -178,13 +190,13 @@ public void edit() throws Exception {
assertTrue(getModel().getAddressBook().getPersonList().contains(BOB));
index = INDEX_FIRST_PERSON;
assertFalse(getModel().getFilteredPersonList().get(index.getZeroBased()).equals(BOB));
- command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND;
+ command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND;
assertCommandFailure(command, EditCommand.MESSAGE_DUPLICATE_PERSON);
/* Case: edit a person with new values same as another person's values but with different tags -> rejected */
- command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND;
+ command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + MATRIC_NUMBER_DESC_BOB
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND;
assertCommandFailure(command, EditCommand.MESSAGE_DUPLICATE_PERSON);
}
diff --git a/src/test/java/systemtests/FindCommandSystemTest.java b/src/test/java/systemtests/FindCommandSystemTest.java
index 0bde83c0444b..71a626620feb 100644
--- a/src/test/java/systemtests/FindCommandSystemTest.java
+++ b/src/test/java/systemtests/FindCommandSystemTest.java
@@ -70,6 +70,11 @@ public void find() {
assertCommandSuccess(command, expectedModel);
assertSelectedCardUnchanged();
+ /* Case: find by matriculation number in address book, 2 keywords in reversed order -> 2 persons found */
+ command = FindCommand.COMMAND_WORD + " A4234567X A2234567X";
+ assertCommandSuccess(command, expectedModel);
+ assertSelectedCardUnchanged();
+
/* Case: undo previous find command -> rejected */
command = UndoCommand.COMMAND_WORD;
String expectedResultMessage = UndoCommand.MESSAGE_FAILURE;