Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tutorial 2 #34

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ Format: `help`
#### Adding a person: `add`
> Adds a person to the address book

Format: `add NAME p/PHONE_NUMBER e/EMAIL`
Format: `add NAME p/PHONE_NUMBER e/EMAIL c/POSTAL_CODE`
> Words in `UPPER_CASE` are the parameters<br>
Phone number and email can be in any order but the name must come first.

Examples:
* `add John Doe p/98765432 e/[email protected]`
* `add Betsy Crowe e/[email protected] p/1234567 `
* `add John Doe p/98765432 e/[email protected] c/123456`
* `add Betsy Crowe e/[email protected] p/1234567 c/111111`

#### Listing all persons: `list`

Expand Down
144 changes: 115 additions & 29 deletions src/seedu/addressbook/AddressBook.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ public class AddressBook {
* at which java String.format(...) method can insert values.
* =========================================================================
*/
private static final String MESSAGE_ADDED = "New person added: %1$s, Phone: %2$s, Email: %3$s";
private static final String MESSAGE_ADDED = "New person added: %1$s, Phone: %2$s, Email: %3$s, Postal Code: %4$s";
private static final String MESSAGE_ADDRESSBOOK_CLEARED = "Address book has been cleared!";
private static final String MESSAGE_COMMAND_HELP = "%1$s: %2$s";
private static final String MESSAGE_COMMAND_HELP_PARAMETERS = "\tParameters: %1$s";
private static final String MESSAGE_COMMAND_HELP_EXAMPLE = "\tExample: %1$s";
private static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
private static final String MESSAGE_DISPLAY_PERSON_DATA = "%1$s Phone Number: %2$s Email: %3$s";
private static final String MESSAGE_DISPLAY_PERSON_DATA = "%1$s Phone Number: %2$s Email: %3$s Postal Code: %4$s";
private static final String MESSAGE_DISPLAY_LIST_ELEMENT_INDEX = "%1$d. ";
private static final String MESSAGE_GOODBYE = "Exiting Address Book... Good bye!";
private static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format: %1$s " + LS + "%2$s";
Expand All @@ -94,16 +94,21 @@ public class AddressBook {
// These are the prefix strings to define the data type of a command parameter
private static final String PERSON_DATA_PREFIX_PHONE = "p/";
private static final String PERSON_DATA_PREFIX_EMAIL = "e/";
private static final String PERSON_DATA_PREFIX_POSTALCODE = "c/";

private static final String PERSON_STRING_REPRESENTATION = "%1$s " // name
+ PERSON_DATA_PREFIX_PHONE + "%2$s " // phone
+ PERSON_DATA_PREFIX_EMAIL + "%3$s"; // email
+ PERSON_DATA_PREFIX_EMAIL + "%3$s " // email
+ PERSON_DATA_PREFIX_POSTALCODE + "%4$s"; // postal code
private static final String COMMAND_ADD_WORD = "add";
private static final String COMMAND_ADD_DESC = "Adds a person to the address book.";
private static final String COMMAND_ADD_PARAMETERS = "NAME "
+ PERSON_DATA_PREFIX_PHONE + "PHONE_NUMBER "
+ PERSON_DATA_PREFIX_EMAIL + "EMAIL";
private static final String COMMAND_ADD_EXAMPLE = COMMAND_ADD_WORD + " John Doe p/98765432 e/[email protected]";
+ PERSON_DATA_PREFIX_EMAIL + "EMAIL "
+ PERSON_DATA_PREFIX_POSTALCODE + "POSTAL_CODE";

private static final String COMMAND_ADD_EXAMPLE = COMMAND_ADD_WORD +
" John Doe p/98765432 e/[email protected] c/123456";

private static final String COMMAND_FIND_WORD = "find";
private static final String COMMAND_FIND_DESC = "Finds all persons whose names contain any of the specified "
Expand Down Expand Up @@ -144,11 +149,13 @@ public class AddressBook {
private static final int PERSON_DATA_INDEX_NAME = 0;
private static final int PERSON_DATA_INDEX_PHONE = 1;
private static final int PERSON_DATA_INDEX_EMAIL = 2;
private static final int PERSON_DATA_INDEX_POSTALCODE = 3;


/**
* The number of data elements for a single person.
*/
private static final int PERSON_DATA_COUNT = 3;
private static final int PERSON_DATA_COUNT = 4;

/**
* Offset required to convert between 1-indexing and 0-indexing.COMMAND_
Expand Down Expand Up @@ -439,7 +446,8 @@ private static String executeAddPerson(String commandArgs) {
*/
private static String getMessageForSuccessfulAddPerson(String[] addedPerson) {
return String.format(MESSAGE_ADDED,
getNameFromPerson(addedPerson), getPhoneFromPerson(addedPerson), getEmailFromPerson(addedPerson));
getNameFromPerson(addedPerson), getPhoneFromPerson(addedPerson),
getEmailFromPerson(addedPerson), getPostalFromPerson(addedPerson));
}

/**
Expand Down Expand Up @@ -669,7 +677,8 @@ private static String getIndexedPersonListElementMessage(int visibleIndex, Strin
*/
private static String getMessageForFormattedPersonData(String[] person) {
return String.format(MESSAGE_DISPLAY_PERSON_DATA,
getNameFromPerson(person), getPhoneFromPerson(person), getEmailFromPerson(person));
getNameFromPerson(person), getPhoneFromPerson(person),
getEmailFromPerson(person), getPostalFromPerson(person));
}

/**
Expand Down Expand Up @@ -860,6 +869,15 @@ private static String getEmailFromPerson(String[] person) {
return person[PERSON_DATA_INDEX_EMAIL];
}

/**
* Returns given person's postal code
*
* @param person whose postal code you want
*/
private static String getPostalFromPerson(String[] person) {
return person[PERSON_DATA_INDEX_POSTALCODE];
}

/**
* Creates a person from the given data.
*
Expand All @@ -868,11 +886,12 @@ private static String getEmailFromPerson(String[] person) {
* @param email without data prefix
* @return constructed person
*/
private static String[] makePersonFromData(String name, String phone, String email) {
private static String[] makePersonFromData(String name, String phone, String email, String postalCode) {
final String[] person = new String[PERSON_DATA_COUNT];
person[PERSON_DATA_INDEX_NAME] = name;
person[PERSON_DATA_INDEX_PHONE] = phone;
person[PERSON_DATA_INDEX_EMAIL] = email;
person[PERSON_DATA_INDEX_POSTALCODE] = postalCode;
return person;
}

Expand All @@ -884,7 +903,8 @@ private static String[] makePersonFromData(String name, String phone, String ema
*/
private static String encodePersonToString(String[] person) {
return String.format(PERSON_STRING_REPRESENTATION,
getNameFromPerson(person), getPhoneFromPerson(person), getEmailFromPerson(person));
getNameFromPerson(person), getPhoneFromPerson(person),
getEmailFromPerson(person), getPostalFromPerson(person));
}

/**
Expand Down Expand Up @@ -923,7 +943,9 @@ private static Optional<String[]> decodePersonFromString(String encoded) {
final String[] decodedPerson = makePersonFromData(
extractNameFromPersonString(encoded),
extractPhoneFromPersonString(encoded),
extractEmailFromPersonString(encoded)
extractEmailFromPersonString(encoded),
extractPostalFromPersonString(encoded)

);
// check that the constructed person is valid
return isPersonDataValid(decodedPerson) ? Optional.of(decodedPerson) : Optional.empty();
Expand Down Expand Up @@ -955,12 +977,15 @@ private static Optional<ArrayList<String[]>> decodePersonsFromStrings(ArrayList<
* @param personData person string representation
*/
private static boolean isPersonDataExtractableFrom(String personData) {
final String matchAnyPersonDataPrefix = PERSON_DATA_PREFIX_PHONE + '|' + PERSON_DATA_PREFIX_EMAIL;
final String matchAnyPersonDataPrefix = PERSON_DATA_PREFIX_PHONE + '|' +
PERSON_DATA_PREFIX_EMAIL+ '|' +
PERSON_DATA_PREFIX_POSTALCODE;
final String[] splitArgs = personData.trim().split(matchAnyPersonDataPrefix);
return splitArgs.length == 3 // 3 arguments
return splitArgs.length == 4 // 4 arguments
&& !splitArgs[0].isEmpty() // non-empty arguments
&& !splitArgs[1].isEmpty()
&& !splitArgs[2].isEmpty();
&& !splitArgs[2].isEmpty()
&& !splitArgs[3].isEmpty();
}

/**
Expand All @@ -986,17 +1011,24 @@ private static String extractNameFromPersonString(String encoded) {
private static String extractPhoneFromPersonString(String encoded) {
final int indexOfPhonePrefix = encoded.indexOf(PERSON_DATA_PREFIX_PHONE);
final int indexOfEmailPrefix = encoded.indexOf(PERSON_DATA_PREFIX_EMAIL);
final int indexOfPostalPrefix = encoded.indexOf(PERSON_DATA_PREFIX_POSTALCODE);

// phone is last arg, target is from prefix to end of string
if (indexOfPhonePrefix > indexOfEmailPrefix) {
if (indexOfPhonePrefix > indexOfEmailPrefix && indexOfPhonePrefix > indexOfPostalPrefix) {
return removePrefixSign(encoded.substring(indexOfPhonePrefix, encoded.length()).trim(),
PERSON_DATA_PREFIX_PHONE);

// phone is middle arg, target is from own prefix to next prefix
} else {
// phone is before mail, target is from own prefix to next prefix
} else if ((indexOfPhonePrefix < indexOfEmailPrefix && indexOfPostalPrefix < indexOfPhonePrefix)
|| (indexOfPhonePrefix < indexOfEmailPrefix && indexOfPostalPrefix > indexOfPhonePrefix)) {
return removePrefixSign(
encoded.substring(indexOfPhonePrefix, indexOfEmailPrefix).trim(),
PERSON_DATA_PREFIX_PHONE);
// phone is before postal code, target is from own prefix to next prefix
} else {
return removePrefixSign(
encoded.substring(indexOfPhonePrefix, indexOfPostalPrefix).trim(),
PERSON_DATA_PREFIX_PHONE);
}
}

Expand All @@ -1008,30 +1040,70 @@ private static String extractPhoneFromPersonString(String encoded) {
*/
private static String extractEmailFromPersonString(String encoded) {
final int indexOfPhonePrefix = encoded.indexOf(PERSON_DATA_PREFIX_PHONE);
final int indexOfPostalPrefix = encoded.indexOf(PERSON_DATA_PREFIX_POSTALCODE);
final int indexOfEmailPrefix = encoded.indexOf(PERSON_DATA_PREFIX_EMAIL);

// email is last arg, target is from prefix to end of string
if (indexOfEmailPrefix > indexOfPhonePrefix) {
if (indexOfEmailPrefix > indexOfPhonePrefix && indexOfEmailPrefix > indexOfPostalPrefix) {
return removePrefixSign(encoded.substring(indexOfEmailPrefix, encoded.length()).trim(),
PERSON_DATA_PREFIX_EMAIL);

// email is middle arg, target is from own prefix to next prefix
// email is before postal code, target is from own prefix to next prefix
} else if ((indexOfEmailPrefix > indexOfPhonePrefix && indexOfEmailPrefix < indexOfPostalPrefix)
|| (indexOfEmailPrefix < indexOfPhonePrefix && indexOfEmailPrefix < indexOfPostalPrefix)){
return removePrefixSign(
encoded.substring(indexOfEmailPrefix, indexOfPostalPrefix).trim(),
PERSON_DATA_PREFIX_EMAIL);
// email is middle arg, phone is last arg, target is from own prefix to next prefix
} else {
return removePrefixSign(
encoded.substring(indexOfEmailPrefix, indexOfPhonePrefix).trim(),
encoded.substring(indexOfPhonePrefix, indexOfEmailPrefix).trim(),
PERSON_DATA_PREFIX_EMAIL);
}
}


/**
* Extracts substring representing postal code from person string representation
*
* @param encoded person string representation
* @return postal code argument WITHOUT prefix
*/
private static String extractPostalFromPersonString(String encoded) {
final int indexOfPhonePrefix = encoded.indexOf(PERSON_DATA_PREFIX_PHONE);
final int indexOfPostalPrefix = encoded.indexOf(PERSON_DATA_PREFIX_POSTALCODE);
final int indexOfEmailPrefix = encoded.indexOf(PERSON_DATA_PREFIX_EMAIL);

// pc is last arg, target is from prefix to end of string
if (indexOfPostalPrefix > indexOfEmailPrefix && indexOfPostalPrefix > indexOfPhonePrefix) {
return removePrefixSign(encoded.substring(indexOfPostalPrefix, encoded.length()).trim(),
PERSON_DATA_PREFIX_POSTALCODE);

// pc is before email target is from own prefix to next prefix
} else if ((indexOfPostalPrefix < indexOfEmailPrefix && indexOfPhonePrefix < indexOfPostalPrefix)
|| (indexOfPostalPrefix < indexOfEmailPrefix && indexOfPhonePrefix > indexOfPostalPrefix)){
return removePrefixSign(
encoded.substring(indexOfPostalPrefix, indexOfEmailPrefix).trim(),
PERSON_DATA_PREFIX_POSTALCODE);

// pc is middle arg, phone is last arg, target is from own prefix to next prefix
} else {
return removePrefixSign(
encoded.substring(indexOfPostalPrefix, indexOfPhonePrefix).trim(),
PERSON_DATA_PREFIX_POSTALCODE);
}
}

/**
* Returns true if the given person's data fields are valid
*
* @param person String array representing the person (used in internal data)
*/
private static boolean isPersonDataValid(String[] person) {
return isPersonNameValid(person[PERSON_DATA_INDEX_NAME])
&& isPersonPhoneValid(person[PERSON_DATA_INDEX_PHONE])
&& isPersonEmailValid(person[PERSON_DATA_INDEX_EMAIL]);
return isPersonNameValid(person[PERSON_DATA_INDEX_NAME], "(\\w|\\s)+")
&& isPersonPhoneValid(person[PERSON_DATA_INDEX_PHONE], "\\d+")
&& isPersonEmailValid(person[PERSON_DATA_INDEX_EMAIL], "\\S+@\\S+\\.\\S+")
&& isPersonPostalValid(person[PERSON_DATA_INDEX_POSTALCODE], "\\d+");
}

/*
Expand All @@ -1046,33 +1118,47 @@ && isPersonPhoneValid(person[PERSON_DATA_INDEX_PHONE])
* Returns true if the given string as a legal person name
*
* @param name to be validated
* @param regex
*/
private static boolean isPersonNameValid(String name) {
return name.matches("(\\w|\\s)+"); // name is nonempty mixture of alphabets and whitespace
private static boolean isPersonNameValid(String name, String regex) {
return isPersonPhoneValid(name, regex); // name is nonempty mixture of alphabets and whitespace
//TODO: implement a more permissive validation
}

/**
* Returns true if the given string as a legal person phone number
*
* @param phone to be validated
* @param regex
*/
private static boolean isPersonPhoneValid(String phone) {
return phone.matches("\\d+"); // phone nonempty sequence of digits
private static boolean isPersonPhoneValid(String phone, String regex) {
return phone.matches(regex); // phone nonempty sequence of digits
//TODO: implement a more permissive validation
}

/**
* Returns true if the given string is a legal person email
*
* @param email to be validated
* @param regex
* @return whether arg is a valid person email
*/
private static boolean isPersonEmailValid(String email) {
return email.matches("\\S+@\\S+\\.\\S+"); // email is [non-whitespace]@[non-whitespace].[non-whitespace]
private static boolean isPersonEmailValid(String email, String regex) {
return isPersonPhoneValid(email, regex); // email is [non-whitespace]@[non-whitespace].[non-whitespace]
//TODO: implement a more permissive validation
}

/**
* Returns true if the given string is a legal postal code
*
* @param postalCode to be validated
* @param regex
* @return whether arg is a legal postal code
*/
private static boolean isPersonPostalValid(String postalCode, String regex) {
return isPersonPhoneValid(postalCode, regex); // email is [non-whitespace]@[non-whitespace].[non-whitespace]
//TODO: implement a more permissive validation
}

/*
* ===============================================
Expand Down
21 changes: 11 additions & 10 deletions test/input.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,27 @@

# should catch invalid args format
add wrong args wrong args
add Valid Name p/12345 [email protected]
add Valid Name 12345 e/[email protected]
add Valid Name p/12345 [email protected] c/111111
add Valid Name 12345 e/[email protected] c/111111

# should catch invalid person data
add []\[;] p/12345 e/[email protected]
add Valid Name p/not_numbers e/[email protected]
add Valid Name p/12345 e/notAnEmail
add Valid Name p/not_numbers e/[email protected] c/111111
add Valid Name p/12345 e/notAnEmail c/111111
add Valid Name p/12345 e/[email protected] c/not_numbers

# should add correctly
add Adam Brown p/111111 e/[email protected]
add Adam Brown p/111111 e/[email protected] c/111111
list
add Betsy Choo p/222222 e/[email protected]
add Betsy Choo p/222222 e/[email protected] c/222222
list

# order of phone and email should not matter
add Charlie Dickson e/[email protected] p/333333
# order of phone and email and postal code should not matter
add Charlie Dickson e/[email protected] p/333333 c/111111
list
add Dickson Ee e/[email protected] p/444444
add Dickson Ee e/[email protected] p/444444 c/111111
list
add Esther Potato p/555555 e/[email protected]
add Esther Potato p/555555 c/111111 e/[email protected]
list

##########################################################
Expand Down