diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 4abb17e3e..66787bc07 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -72,6 +72,26 @@ Examples: Shows a list of all persons, along with their non-private details, in the address book. + Format: `list` +== Adding a person & Listing all persons: `add&list` + +Adds a person to the address book and shows a list of all persons, along with their non-private details, in the address book after adding. + +Format: `add&list NAME [p]p/PHONE_NUMBER [p]e/EMAIL [p]a/ADDRESS [t/TAG]...` + +**** +Words in `UPPER_CASE` are the parameters, items in `SQUARE_BRACKETS` are optional, +items with `...` after them can have multiple instances. Order of parameters are fixed. + +Put a `p` before the phone / email / address prefixes to mark it as `private`. `private` details can only +be seen using the `viewall` command. + +Persons can have any number of tags (including 0). +**** + +Examples: + +* `add&list John Doe p/98765432 e/johnd@gmail.com a/John street, block 123, #01-01` +* `add&list Betsy Crowe pp/1234567 e/betsycrowe@gmail.com pa/Newgate Prison t/criminal t/friend` + == Finding all persons containing any keyword in their name: `find` Finds persons whose names contain any of the given keywords. + diff --git a/src/seedu/addressbook/commands/AddListCommand.java b/src/seedu/addressbook/commands/AddListCommand.java new file mode 100644 index 000000000..da5ab11d6 --- /dev/null +++ b/src/seedu/addressbook/commands/AddListCommand.java @@ -0,0 +1,76 @@ +package seedu.addressbook.commands; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import seedu.addressbook.data.exception.IllegalValueException; +import seedu.addressbook.data.person.Address; +import seedu.addressbook.data.person.Email; +import seedu.addressbook.data.person.Name; +import seedu.addressbook.data.person.Person; +import seedu.addressbook.data.person.Phone; +import seedu.addressbook.data.person.ReadOnlyPerson; +import seedu.addressbook.data.person.UniquePersonList; +import seedu.addressbook.data.tag.Tag; + +/* +Add a person to the addressbook and list down everyone in the addressbook right after + */ +public class AddListCommand extends Command{ + public static final String COMMAND_WORD = "add&list"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book and list the whole address book after a successful add. " + + "Contact details can be marked private by prepending 'p' to the prefix.\n" + + "Parameters: NAME [p]p/PHONE [p]e/EMAIL [p]a/ADDRESS [t/TAG]...\n" + + "Example: " + COMMAND_WORD + + " John Doe p/98765432 e/johnd@gmail.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney"; + +// public static final String MESSAGE_SUCCESS = "New person added: %1$s"; + public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; + + private final Person toAdd; + + /** + * Convenience constructor using raw values. + * + * @throws IllegalValueException if any of the raw values are invalid + */ + public AddListCommand(String name, + String phone, boolean isPhonePrivate, + String email, boolean isEmailPrivate, + String address, boolean isAddressPrivate, + Set tags) throws IllegalValueException { + final Set tagSet = new HashSet<>(); + for (String tagName : tags) { + tagSet.add(new Tag(tagName)); + } + this.toAdd = new Person( + new Name(name), + new Phone(phone, isPhonePrivate), + new Email(email, isEmailPrivate), + new Address(address, isAddressPrivate), + tagSet + ); + } + + public AddListCommand(Person toAdd) { + this.toAdd = toAdd; + } + + public ReadOnlyPerson getPerson() { + return toAdd; + } + + @Override + public CommandResult execute() { + try { + addressBook.addPerson(toAdd); + List allPersons = addressBook.getAllPersons().immutableListView(); + return new CommandResult(getMessageForPersonListShownSummary(allPersons), allPersons); +// return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); + } catch (UniquePersonList.DuplicatePersonException dpe) { + return new CommandResult(MESSAGE_DUPLICATE_PERSON); + } + } +} diff --git a/src/seedu/addressbook/commands/HelpCommand.java b/src/seedu/addressbook/commands/HelpCommand.java index 9be217d89..7a37688a9 100644 --- a/src/seedu/addressbook/commands/HelpCommand.java +++ b/src/seedu/addressbook/commands/HelpCommand.java @@ -15,6 +15,7 @@ public class HelpCommand extends Command { public CommandResult execute() { return new CommandResult( AddCommand.MESSAGE_USAGE + + "\n" + AddListCommand.MESSAGE_USAGE + "\n" + DeleteCommand.MESSAGE_USAGE + "\n" + ClearCommand.MESSAGE_USAGE + "\n" + FindCommand.MESSAGE_USAGE diff --git a/src/seedu/addressbook/parser/Parser.java b/src/seedu/addressbook/parser/Parser.java index abddb3f45..71bda62e9 100644 --- a/src/seedu/addressbook/parser/Parser.java +++ b/src/seedu/addressbook/parser/Parser.java @@ -12,6 +12,7 @@ import java.util.regex.Pattern; import seedu.addressbook.commands.AddCommand; +import seedu.addressbook.commands.AddListCommand; import seedu.addressbook.commands.ClearCommand; import seedu.addressbook.commands.Command; import seedu.addressbook.commands.DeleteCommand; @@ -76,6 +77,9 @@ public Command parseCommand(String userInput) { case AddCommand.COMMAND_WORD: return prepareAdd(arguments); + case AddListCommand.COMMAND_WORD: + return prepareAddList(arguments); + case DeleteCommand.COMMAND_WORD: return prepareDelete(arguments); @@ -135,6 +139,32 @@ private Command prepareAdd(String args) { } } + private Command prepareAddList(String args) { + final Matcher matcher = PERSON_DATA_ARGS_FORMAT.matcher(args.trim()); + // Validate arg string format + if (!matcher.matches()) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddListCommand.MESSAGE_USAGE)); + } + try { + return new AddListCommand( + matcher.group("name"), + + matcher.group("phone"), + isPrivatePrefixPresent(matcher.group("isPhonePrivate")), + + matcher.group("email"), + isPrivatePrefixPresent(matcher.group("isEmailPrivate")), + + matcher.group("address"), + isPrivatePrefixPresent(matcher.group("isAddressPrivate")), + + getTagsFromArgs(matcher.group("tagArguments")) + ); + } catch (IllegalValueException ive) { + return new IncorrectCommand(ive.getMessage()); + } + } + /** * Returns true if the private prefix is present for a contact detail in the add command's arguments string. */ diff --git a/test/java/seedu/addressbook/commands/AddListCommandTest.java b/test/java/seedu/addressbook/commands/AddListCommandTest.java new file mode 100644 index 000000000..89e277d1a --- /dev/null +++ b/test/java/seedu/addressbook/commands/AddListCommandTest.java @@ -0,0 +1,147 @@ +package seedu.addressbook.commands; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Test; + +import seedu.addressbook.data.AddressBook; +import seedu.addressbook.data.exception.IllegalValueException; +import seedu.addressbook.data.person.Address; +import seedu.addressbook.data.person.Email; +import seedu.addressbook.data.person.Name; +import seedu.addressbook.data.person.Person; +import seedu.addressbook.data.person.Phone; +import seedu.addressbook.data.person.ReadOnlyPerson; +import seedu.addressbook.data.person.UniquePersonList; +import seedu.addressbook.util.TestUtil; + +public class AddListCommandTest { + private static final List EMPTY_PERSON_LIST = Collections.emptyList(); + private static final Set EMPTY_STRING_SET = Collections.emptySet(); + + @Test + public void addListCommand_invalidName_throwsException() { + final String[] invalidNames = { "", " ", "[]\\[;]" }; + for (String name : invalidNames) { + assertConstructingInvalidAddCmdThrowsException(name, Phone.EXAMPLE, true, Email.EXAMPLE, false, + Address.EXAMPLE, true, EMPTY_STRING_SET); + } + } + + @Test + public void addListCommand_invalidPhone_throwsException() { + final String[] invalidNumbers = { "", " ", "1234-5678", "[]\\[;]", "abc", "a123", "+651234" }; + for (String number : invalidNumbers) { + assertConstructingInvalidAddCmdThrowsException(Name.EXAMPLE, number, false, Email.EXAMPLE, true, + Address.EXAMPLE, false, EMPTY_STRING_SET); + } + } + + @Test + public void addListCommand_invalidEmail_throwsException() { + final String[] invalidEmails = { "", " ", "def.com", "@", "@def", "@def.com", "abc@", + "@invalid@email", "invalid@email!", "!invalid@email" }; + for (String email : invalidEmails) { + assertConstructingInvalidAddCmdThrowsException(Name.EXAMPLE, Phone.EXAMPLE, false, email, false, + Address.EXAMPLE, false, EMPTY_STRING_SET); + } + } + + @Test + public void addListCommand_invalidAddress_throwsException() { + final String[] invalidAddresses = { "", " " }; + for (String address : invalidAddresses) { + assertConstructingInvalidAddCmdThrowsException(Name.EXAMPLE, Phone.EXAMPLE, true, Email.EXAMPLE, + true, address, true, EMPTY_STRING_SET); + } + } + + @Test + public void addListCommand_invalidTags_throwsException() { + final String[][] invalidTags = { { "" }, { " " }, { "'" }, { "[]\\[;]" }, { "validTag", "" }, + { "", " " } }; + for (String[] tags : invalidTags) { + Set tagsToAdd = new HashSet<>(Arrays.asList(tags)); + assertConstructingInvalidAddCmdThrowsException(Name.EXAMPLE, Phone.EXAMPLE, true, Email.EXAMPLE, + true, Address.EXAMPLE, false, tagsToAdd); + } + } + + /** + * Asserts that attempting to construct an add command with the supplied + * invalid data throws an IllegalValueException + */ + private void assertConstructingInvalidAddCmdThrowsException(String name, String phone, + boolean isPhonePrivate, String email, boolean isEmailPrivate, String address, + boolean isAddressPrivate, Set tags) { + try { + new AddListCommand(name, phone, isPhonePrivate, email, isEmailPrivate, address, isAddressPrivate, + tags); + } catch (IllegalValueException e) { + return; + } + String error = String.format( + "An add command was successfully constructed with invalid input: %s %s %s %s %s %s %s %s", + name, phone, isPhonePrivate, email, isEmailPrivate, address, isAddressPrivate, tags); + fail(error); + } + + @Test + public void addListCommand_validData_correctlyConstructed() throws Exception { + AddListCommand command = new AddListCommand(Name.EXAMPLE, Phone.EXAMPLE, true, Email.EXAMPLE, false, + Address.EXAMPLE, true, EMPTY_STRING_SET); + ReadOnlyPerson p = command.getPerson(); + + // TODO: add comparison of tags to person.equals and equality methods to + // individual fields that compare privacy to simplify this + assertEquals(Name.EXAMPLE, p.getName().fullName); + assertEquals(Phone.EXAMPLE, p.getPhone().value); + assertTrue(p.getPhone().isPrivate()); + assertEquals(Email.EXAMPLE, p.getEmail().value); + assertFalse(p.getEmail().isPrivate()); + assertEquals(Address.EXAMPLE, p.getAddress().value); + assertTrue(p.getAddress().isPrivate()); + boolean isTagListEmpty = !p.getTags().iterator().hasNext(); + assertTrue(isTagListEmpty); + } + + @Test + public void addListCommand_emptyAddressBook_addressBookContainsPerson() { + Person p = TestUtil.generateTestPerson(); + AddListCommand command = new AddListCommand(p); + AddressBook book = new AddressBook(); + command.setData(book, EMPTY_PERSON_LIST); + CommandResult result = command.execute(); + UniquePersonList people = book.getAllPersons(); + + assertTrue(people.contains(p)); + assertEquals(1, people.immutableListView().size()); +// assertFalse(result.getRelevantPersons().isPresent()); +// assertEquals(String.format(AddListCommand.MESSAGE_SUCCESS, p), result.feedbackToUser); + } + + @Test + public void AddListCommand_addressBookAlreadyContainsPerson_addressBookUnmodified() throws Exception { + Person p = TestUtil.generateTestPerson(); + AddressBook book = new AddressBook(); + book.addPerson(p); + AddListCommand command = new AddListCommand(p); + command.setData(book, EMPTY_PERSON_LIST); + CommandResult result = command.execute(); + + assertFalse(result.getRelevantPersons().isPresent()); + assertEquals(AddListCommand.MESSAGE_DUPLICATE_PERSON, result.feedbackToUser); + UniquePersonList people = book.getAllPersons(); + assertTrue(people.contains(p)); + assertEquals(1, people.immutableListView().size()); + } +}