Project: K.N.S. Address Book

K.N.S. Address Book is a desktop address book application written in Java, created by Team W11-B3 for CS2103T: Software Engineering module offered by School of Computing, National University of Singapore, in AY 2017/2018 Semester 1. This project portfolio page consists of contributions that I have made to K.N.S. Address Book during this semester.

Code contributed: [Functional code] [Test code]

Enhancement Added: Find by All Field

External behavior


Start of Extract [from: User Guide]

Find by All Field

You can find your contact by using any field as the search query. For example, you can type in a phone number as the search query, and the contact in your address book who has that phone number will appear in the search result.

Find by all field supports find by name, phone number, email, address, birthday, and tags. ==== By Any Field To find by other fields, you can use their respective prefixes. (p/ for phone, e/ for email, b/ for birthday, a/ for address)
You can search all fields, save for avatar (v/) as of v1.4
All prefixes will show contacts with partial matches of the respective information.

Examples:

  • find p/ 1234567
    Returns any person with phone number containing 1234567.

  • find a/ Jurong
    Returns any person with address containing Jurong (case-insensitive) in it.

  • find b/ 16/02
    Returns any person with birthday containing 16/02.

  • find e/ johndoe
    Returns any person with email containing johndoe.

End of Extract


Justification

Previously, the find command only enables users to search their contacts with name query. Hence, users who only remember some part of their contact details but do not remember their contact’s name would find it troublesome when searching for their contacts, as they couldn’t find their contacts with the contact details that they remember. Together with Kevin, we enable the find command to accept all field as the query. Kevin implemented the find by tag feature, and I implemented find by phone, email, address, and birthday. This feature will help users to find their contacts faster and hassle-free.

Implementation


Start of Extract [from: Developer Guide]

Find by All Field

The find by all field feature is implemented by adding one argument, prefix of field that want to be searched, to the find command parameter. If the user does not specify the prefix, the address book will automatically search the query in the name field. The FindCommandParser will parse the input given by the user. The mechanism to find by each field is implemented in <field name>ContainsKeywordPredicate class (i.e. NameContainsKeywordPredicate, AddressContainsKeywordPredicate) inside Model component.

Java Implementation

The FindCommandParser is now able to parse the additional prefix argument, as shown in the code snippet below:

public FindCommand parse(String args) throws ParseException {
        // make sure that the argument is valid
        // store the prefix inside String 'toSearch'
        // store the search query inside array of string 'keyword'

        if (toSearch.equals(PREFIX_TAG.getPrefix())) {
            return new FindCommand(new TagListContainsKeywordsPredicate(Arrays.asList(keywords)));
        } else if (toSearch.equals(PREFIX_PHONE.getPrefix())) {
            return new FindCommand(new PhoneContainsKeywordsPredicate(Arrays.asList(keywords)));
        } else if (toSearch.equals(PREFIX_EMAIL.getPrefix())) {
            return new FindCommand(new EmailContainsKeywordsPredicate(Arrays.asList(keywords)));
        } else if (toSearch.equals(PREFIX_ADDRESS.getPrefix())) {
            return new FindCommand(new AddressContainsKeywordsPredicate(Arrays.asList(keywords)));
        } else if (toSearch.equals(PREFIX_BIRTHDAY.getPrefix())) {
            return new FindCommand(new BirthdayContainsKeywordsPredicate(Arrays.asList(keywords)));
        } else {
            return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(keywords)));
        }
    }

After FindCommandParser parse the arguments, it will call the <field name>ContainsKeywordsPredicate class for each respective field.

All contacts with partial matches will appear on the search result, implemented in the method below for phone field. The method is similar for other field.

public boolean test(ReadOnlyPerson person) {
        return keywords.stream().anyMatch(keyword -> StringUtil
                .containsWordPartialIgnoreCase(person.getPhone().value, keyword));
    }

Design Considerations

Aspect: Implementation of find by all field
Alternative 1 (current choice): Enables user to find by all field (name, phone, email, address, birthday, and tag).
Pros: Easier for user to find their contacts when the user does not remember their contact’s name, instead they remember the contacts' details (such as address or birthday). This feature is useful for a broader range of purpose, for example when the user wants to send a birthday wishes to their contacts, the user can easily find by using birthday field.
Cons: Need to type the prefix of the field that want to be searched.
Alternative 2: Find by name only.
Pros: Some people only remember their contact’s name, and find by all field feature might not be useful for them as they don’t remember their contact’s details.
Cons: User could not find their contact details when they do not remember their contact’s name.


Aspect: Find result upon executing find command.
Alternative 1 (current choice): All contacts with partial match with the find query will appear.
Pros: With less restrictive requirement, users can find a broad range of contacts when they are searching using a global keyword. For example, a user can find all their contacts who lived in "Clementi" when using this alternative.
Cons: More contacts will appear on the find result, some of them might not be the target contact that the user wants to find.
Alternative 2: Only contacts with exact match will appear.
Pros: Less contacts will appear on the find result, easier to find the exact person while searching for a single person.
Cons: It will be hard for a forgetful user to find their contacts as they may remember their contact details' partially. This alternative is also more cumbersome when applied to find by address, as user need to type the full address of their contact.

End of Extract


Adding a Tag: addtag or at

Adds tag(s) to an existing person in the address book.

Format: addtag INDEX TAG [MORE_TAGS]…​

  • Adds the given tag(s) to 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, …​

  • When adding the tag, the existing tags of the person will NOT be removed i.e. adding the tag is cumulative.

  • The new tag added must be different from existing tags i.e. no duplicate tags will be allowed

  • You are able to add more than 1 tag in a single addtag command.

Examples:

  • addtag 1 owesMoney
    Adds a owesMoney tag for the 1st person on the list. If previously the 1st person has friends tag, now the 1st person has both friends and owesMoney tag.

  • addtag 3 friends highSchool
    Adds a friends tag and a highSchool tag for the 3rd person on the list.

Deleting a Tag: deletetag or dt

Deletes given tag from an existing person in the address book.

Format: deletetag INDEX TAG [MORE_TAGS]…​

  • Deletes given tag(s) from 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, …​

  • When deleting the tag, only specified tag will be removed.

  • The tag that will be deleted must exist in the person’s tag list.

  • You are able to delete more than 1 tag in a single deletetag command.

Examples:

  • deletetag 1 owesMoney
    Deletes the owesMoney tag from the 1st person on the list.

  • deletetag 3 friends highSchool
    Deletes the friends tag and highSchool tag from the 3rd person on the list.

End of Extract


Justification

Previously, to add or delete a single tag from their contacts, the user can use edit command. This edit command is quite troublesome when user only wants to add or delete some tags from a certain contact’s tag list, as the user needs to retype all current tags that they wish to keep. Problems may arise when they wrongly retype the tags that they wish to keep, or when they forgot to retype it at all. As such, I developed the add tag and delete tag commands, that are useful for adding and deleting tags from a contact’s tag list, without retyping all the current tags that were not changed. Add tag and delete tag also supports add and deleting multiple tags in a single command. This feature will help users to add and delete tags faster.

Implementation


Start of Extract [from: Developer Guide]

Add Tag and Delete Tag

Add tag and delete tag mechanism is facilitated by the addtag command and deletetag command, or their equivalent aliases at and dt, which is useful for adding and deleting tags in a person’s tag list. On previous versions before Add and Delete tag feature was introduced, users are able to change a person’s tag list by using edit command. Using edit command to add and delete tags is quite cumbersome as users need to retype all the current tags that they didn’t want to edit. addtag command and deletetag command enables user to add and delete tags using only a single command, without retyping all the current tags.

Java Implementation

As addtag and deletetag are commands, their implementations are a part of Logic component in the address book. The implementation of add tag and delete tag can be found in AddTagCommand and DeleteTagCommand. AddTagCommand and DeleteTagCommand inherits UndoableCommands, as they modify the state of the address book (adding and deleting a person’s tag in the address book). Therefore, users can undo/redo their previously entered addtag and deletetag command.

addtag command is implemented in this way:

public class AddTagCommand extends UndoableCommand {
    @Override
    public CommandResult executeUndoableCommand() throws CommandException {
        // ... list logic ...
    }
}

addtag command can be used by calling the method with an index and a string of tag name that will be added, shown by this code snippet:

public AddTagCommand(Index index, Set<Tag> addedTag) {
    requireNonNull(index);
    requireNonNull(addedTag);

    this.index = index;
    this.addedTag = addedTag;
}

Similar to addtag command, deletetag command is implemented in this way:

public class DeleteTagCommand extends UndoableCommand {
    @Override
    public CommandResult executeUndoableCommand() throws CommandException {
        // ... list logic ...
    }
}

deletetag command can be used by calling the method with an index and a string of tag name that will be added, just like addtag command, shown by the following code snippet:

public DeleteTagCommand(Index index, Set<Tag> deletedTag) {
    requireNonNull(index);
    requireNonNull(deletedTag);

    this.index = index;
    this.addedTag = deletedTag;
}

Design Considerations

Aspect: Implementation of AddTagCommand and DeleteTagCommand
Alternative 1 (current choice): Implementing a new command addtag and deletetag instead of using the existing Edit command.
Pros: Users can add and delete a single tag only by typing the new tag that they want to assign or remove from a contact. addtag and deletetag supports adding and deleting several tags at a single execution.
Cons: More commands to remember.
Alternative 2: Use existing Edit command to add or delete tags from a person in the address book.
Pros: Less commands to remember.
Cons: Users need to retype all existing tags they want to keep when they are using edit command. Users might mistype existing tags or not typing a complete set of existing tags while using edit command.

End of Extract


Enhancement Added: Birthday Field

External behavior


In K.N.S. Address Book, users can input the birthday details of their contacts in dd/mm/yyyy format. If the user chooses not to specify their contact’s birthday details, the birthday field would be automatically filled by the default value (-). Users can specify their contact’s birthday details through add and edit command.


Justification

It is important for freelancers to keep a good relation with their clients by remembering their clients' birthday. As such, I created a Birthday class which will support the storage of birthday details in K.N.S. Address Book. Users can input their contact’s birthday details via the add command when they add their contact, or via the edit command. This birthday field is also searchable via the find command to make it easier for users to find their contacts whose birthday is on a certain day. This feature is also useful for Stanley’s proposed enhancement, birthday countdown & reminder feature.

Implementation


Start of Extract [from: Developer Guide]

Birthday

The Birthday class enables users to store their contact’s birthday details in K.N.S. Address Book. Birthday details should be inputted in dd/mm/yyyy form, and will be stored in the address book in the same form. If the user chooses not to enter their contact’s birthday details, the address book will automatically store the default value for empty birthday, which is -, and the value that will appear in the Person Panel for birthday field would be the default value.

Java Implementation

The Birthday class is implemented in similar way like other fields, such as address, phone, and email.

    public Birthday(String birthday) throws IllegalValueException {
        requireNonNull(birthday);
        String trimmedBirthday = birthday.trim();
        if (!isValidBirthday(trimmedBirthday)) {
            throw new IllegalValueException(MESSAGE_BIRTHDAY_CONSTRAINTS);
        }
        this.value = trimmedBirthday;
    }

Design Considerations

Aspect: Birthday Input Format
Alternative 1 (current choice): Using dd/mm/yyyy as the input format
Pros: It is easier for users to remember the format, as it is the format that is commonly used.
Cons: For some people who use mm/dd/yyyy format instead of dd/mm/yyyy format, they might need some time to adjust to K.N.S Address Book’s date format. K.N.S. Address Book assumes that the date entered is in dd/mm/yyyy format and will not send an error message when the number is valid. These users might enter 03/05/2017 which they intend to be 5 March, but the address book will interpret it as 3 May.
Alternative 2: Using ddmmyyyy as the input format
Pros: Faster to type as it consists of only numbers and no other characters.
Cons: The format is not easy to read and is similar to phone number format.

End of Extract


Enhancement Proposed: Favourite contacts

Justification

Some users may have a list of frequently contacted contacts, and in the current version of K.N.S. Address Book, users need to search their contacts using the find command every time they want to see the contact details of these frequently contacted people. Favourite feature will enable users to set these frequently contacted people as their favourite contacts, and these contacts will always appear at the top of the contact list and the search result. This feature will help users to find their frequently contacted contacts easily, without using the find command to search for these contacts.

Enhancement Proposed: Login Page

Justification

Some users might use K.N.S. Address Book in a shared computer in their workplace. These users might want to keep their contact list in private, and not sharing the Address Book with other people who use the same computer. As such, a login page would be useful. When K.N.S Address Book is opened, a login page will appear, and the user can type in their login details such as username and password. This feature will enable users to keep their contact details in private while using a shared computer, as the address book requires password to be accessed.

Other contributions

  • Shorthand Alias

    • Add shorthand equivalent alias for commands. This feature is useful to increase speed and efficiency while using K.N.S Address Book, as users are able to type command with only 1 or 2 alphabets instead of typing the whole word. This feature is mainly for professional K.N.S. Address Book users who already memorized the command list.

    • PR : #5, #51

  • Set up Travis CI configuration for github repo

  • Reported bugs in team T17-B4 OneBook Address Book