From ba3bd4d71146d5456599ab2a823c34b6477e5296 Mon Sep 17 00:00:00 2001 From: Deborah Low Shi Lei Date: Thu, 22 Mar 2018 04:23:13 +0800 Subject: [PATCH] Add and edit feature (#57) * Add skeleton Birthday, LevelOfFriendship and GroupTag class * Add Birthday and GroupTag skeleton classes, add full LevelOfFriendship class * Edit logic portion in source * Edit source model classes * Edit storage * Edit person card * Update some test files * Minor changes * Edit XmlAdaptedPerson class * Edit XmlUtilTest * Edit minor changes, remove birthday and grouptag class * Fix bug * Add 3 classes * Minor changes * Add changes * Update all related documents for adding new classes * Add heart symbols * Remove unused import * Edit failing tests * Minor edits * Add heart string method * Edited several failing tests, added extra method in GuiTestAssert * Edit GUI test * Add git ignore to AddCommandSystemtest * Comment out AddCommandSystemTest to fix later * Add more tests to pass coveralls --- .gitignore | 1 + .../address/logic/commands/AddCommand.java | 19 +- .../address/logic/commands/EditCommand.java | 93 +++++--- .../logic/parser/AddCommandParser.java | 31 ++- .../seedu/address/logic/parser/CliSyntax.java | 6 +- .../logic/parser/EditCommandParser.java | 34 ++- .../address/logic/parser/ParserUtil.java | 106 ++++++--- .../java/seedu/address/model/AddressBook.java | 89 ++++++-- .../address/model/ReadOnlyAddressBook.java | 8 + .../seedu/address/model/person/Birthday.java | 57 +++++ .../java/seedu/address/model/person/Cca.java | 53 +++++ .../seedu/address/model/person/Email.java | 67 ------ .../model/person/LevelOfFriendship.java | 70 ++++++ .../java/seedu/address/model/person/Meet.java | 4 +- .../seedu/address/model/person/Person.java | 62 ++++-- .../address/model/person/UniqueCcaList.java | 142 ++++++++++++ .../address/model/person/UnitNumber.java | 52 +++++ .../address/model/util/SampleDataUtil.java | 56 +++-- .../seedu/address/storage/XmlAdaptedCca.java | 62 ++++++ .../address/storage/XmlAdaptedPerson.java | 79 +++++-- .../storage/XmlSerializableAddressBook.java | 11 +- .../java/seedu/address/ui/PersonCard.java | 40 +++- src/main/resources/view/MainWindow.fxml | 1 + src/main/resources/view/PersonListCard.fxml | 6 +- .../invalidAndValidPersonAddressBook.xml | 12 +- .../invalidPersonAddressBook.xml | 5 +- .../invalidPersonAddressBook.xml | 7 +- .../typicalPersonsAddressBook.xml | 39 ++-- .../data/XmlUtilTest/invalidPersonField.xml | 6 +- .../data/XmlUtilTest/missingPersonField.xml | 6 +- .../data/XmlUtilTest/validAddressBook.xml | 45 ++-- src/test/data/XmlUtilTest/validPerson.xml | 6 +- .../guitests/guihandles/PersonCardHandle.java | 51 +++-- .../address/commons/util/XmlUtilTest.java | 19 +- .../commands/AddCommandIntegrationTest.java | 3 +- .../logic/commands/CommandTestUtil.java | 51 +++-- .../logic/commands/EditCommandTest.java | 2 +- .../commands/EditPersonDescriptorTest.java | 23 +- .../logic/parser/AddCommandParserTest.java | 202 ++++++++++++------ .../logic/parser/EditCommandParserTest.java | 112 ++++++---- .../address/logic/parser/ParserUtilTest.java | 176 +++++++++++---- .../seedu/address/model/AddressBookTest.java | 20 +- .../address/model/person/AddressTest.java | 37 ---- .../address/model/person/BirthdayTest.java | 61 ++++++ .../seedu/address/model/person/CcaTest.java | 40 ++++ .../seedu/address/model/person/EmailTest.java | 62 ------ .../model/person/LevelOfFriendshipTest.java | 51 +++++ .../NameContainsKeywordsPredicateTest.java | 8 +- .../model/person/UniqueCcaListTest.java | 18 ++ .../address/model/person/UnitNumberTest.java | 37 ++++ .../address/storage/XmlAdaptedPersonTest.java | 89 ++++++-- .../address/testutil/AddressBookBuilder.java | 16 +- .../testutil/EditPersonDescriptorBuilder.java | 43 +++- .../seedu/address/testutil/PersonBuilder.java | 60 ++++-- .../seedu/address/testutil/PersonUtil.java | 14 +- .../address/testutil/TypicalPersons.java | 50 +++-- .../address/ui/testutil/GuiTestAssert.java | 43 +++- .../systemtests/AddCommandSystemTest.java | 181 +++++++++++----- .../systemtests/EditCommandSystemTest.java | 82 ++++--- .../systemtests/FindCommandSystemTest.java | 21 +- 60 files changed, 2124 insertions(+), 723 deletions(-) create mode 100644 src/main/java/seedu/address/model/person/Birthday.java create mode 100644 src/main/java/seedu/address/model/person/Cca.java delete mode 100644 src/main/java/seedu/address/model/person/Email.java create mode 100644 src/main/java/seedu/address/model/person/LevelOfFriendship.java create mode 100644 src/main/java/seedu/address/model/person/UniqueCcaList.java create mode 100644 src/main/java/seedu/address/model/person/UnitNumber.java create mode 100644 src/main/java/seedu/address/storage/XmlAdaptedCca.java delete mode 100644 src/test/java/seedu/address/model/person/AddressTest.java create mode 100644 src/test/java/seedu/address/model/person/BirthdayTest.java create mode 100644 src/test/java/seedu/address/model/person/CcaTest.java delete mode 100644 src/test/java/seedu/address/model/person/EmailTest.java create mode 100644 src/test/java/seedu/address/model/person/LevelOfFriendshipTest.java create mode 100644 src/test/java/seedu/address/model/person/UniqueCcaListTest.java create mode 100644 src/test/java/seedu/address/model/person/UnitNumberTest.java diff --git a/.gitignore b/.gitignore index 823d175eb670..a416207a776b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ lib/* *.csv config.json src/test/data/sandbox/ +src/test/java/systemtests/AddCommandSystemTest preferences.json .DS_Store ./screenshot*.png diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index d5de4a572715..59bbe8afd4da 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -1,11 +1,13 @@ package seedu.address.logic.commands; 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_BIRTHDAY; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CCA; +import static seedu.address.logic.parser.CliSyntax.PREFIX_LEVEL_OF_FRIENDSHIP; 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; +import static seedu.address.logic.parser.CliSyntax.PREFIX_UNIT_NUMBER; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.person.Person; @@ -23,14 +25,19 @@ public class AddCommand extends UndoableCommand { + "Parameters: " + PREFIX_NAME + "NAME " + PREFIX_PHONE + "PHONE " - + PREFIX_EMAIL + "EMAIL " - + PREFIX_ADDRESS + "ADDRESS " + + PREFIX_BIRTHDAY + "BIRTHDAY " + + PREFIX_LEVEL_OF_FRIENDSHIP + "LEVEL OF FRIENDSHIP " + + PREFIX_UNIT_NUMBER + "UNIT NUMBER " + + PREFIX_CCA + "CCA " + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + "John Doe " + PREFIX_PHONE + "98765432 " - + PREFIX_EMAIL + "johnd@example.com " - + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " + + PREFIX_BIRTHDAY + "24/05/1997 " + + PREFIX_LEVEL_OF_FRIENDSHIP + "9 " + + PREFIX_UNIT_NUMBER + "#02-25 " + + PREFIX_CCA + "Badminton " + + PREFIX_CCA + "tennis " + PREFIX_TAG + "friends " + PREFIX_TAG + "owesMoney"; diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index cfa9a8bc426e..ca9367f118f2 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -1,11 +1,13 @@ package seedu.address.logic.commands; 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_BIRTHDAY; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CCA; +import static seedu.address.logic.parser.CliSyntax.PREFIX_LEVEL_OF_FRIENDSHIP; 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; +import static seedu.address.logic.parser.CliSyntax.PREFIX_UNIT_NUMBER; import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; import java.util.Collections; @@ -19,12 +21,14 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.util.CollectionUtil; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; +import seedu.address.model.person.Birthday; +import seedu.address.model.person.Cca; +import seedu.address.model.person.LevelOfFriendship; import seedu.address.model.person.Meet; import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.person.UnitNumber; import seedu.address.model.person.exceptions.DuplicatePersonException; import seedu.address.model.person.exceptions.PersonNotFoundException; import seedu.address.model.tag.Tag; @@ -44,12 +48,14 @@ public class EditCommand extends UndoableCommand { + "Parameters: INDEX (must be a positive integer) " + "[" + PREFIX_NAME + "NAME] " + "[" + PREFIX_PHONE + "PHONE] " - + "[" + PREFIX_EMAIL + "EMAIL] " - + "[" + PREFIX_ADDRESS + "ADDRESS] " + + "[" + PREFIX_BIRTHDAY + "BIRTHDAY] " + + "[" + PREFIX_LEVEL_OF_FRIENDSHIP + "LEVEL OF FRIENDSHIP] " + + "[" + PREFIX_UNIT_NUMBER + "UNIT NUMBER] " + + "[" + PREFIX_CCA + "CCA]... " + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " 1 " + PREFIX_PHONE + "91234567 " - + PREFIX_EMAIL + "johndoe@example.com"; + + PREFIX_BIRTHDAY + "21/3/1990 "; public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s"; public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; @@ -107,12 +113,16 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName()); Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone()); - Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); - Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress()); + Birthday updatedBirthday = editPersonDescriptor.getBirthday().orElse(personToEdit.getBirthday()); + LevelOfFriendship updatedLevelOfFriendship = editPersonDescriptor.getLevelOfFriendship() + .orElse(personToEdit.getLevelOfFriendship()); + UnitNumber updatedUnitNumber = editPersonDescriptor.getUnitNumber().orElse(personToEdit.getUnitNumber()); Meet updatedMeetDate = personToEdit.getMeetDate(); + Set updatedCcas = editPersonDescriptor.getCcas().orElse(personToEdit.getCcas()); Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); - return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedMeetDate, updatedTags); + return new Person(updatedName, updatedPhone, updatedBirthday, updatedLevelOfFriendship, updatedUnitNumber, + updatedCcas, updatedMeetDate, updatedTags); } @Override @@ -141,8 +151,10 @@ public boolean equals(Object other) { public static class EditPersonDescriptor { private Name name; private Phone phone; - private Email email; - private Address address; + private Birthday birthday; + private LevelOfFriendship levelOfFriendship; + private UnitNumber unitNumber; + private Set ccas; private Set tags; public EditPersonDescriptor() {} @@ -154,8 +166,10 @@ public EditPersonDescriptor() {} public EditPersonDescriptor(EditPersonDescriptor toCopy) { setName(toCopy.name); setPhone(toCopy.phone); - setEmail(toCopy.email); - setAddress(toCopy.address); + setBirthday(toCopy.birthday); + setLevelOfFriendship(toCopy.levelOfFriendship); + setUnitNumber(toCopy.unitNumber); + setCcas(toCopy.ccas); setTags(toCopy.tags); } @@ -163,7 +177,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.phone, this.birthday, + this.levelOfFriendship, this.unitNumber, this.ccas, this.tags); } public void setName(Name name) { @@ -182,20 +197,46 @@ public Optional getPhone() { return Optional.ofNullable(phone); } - public void setEmail(Email email) { - this.email = email; + public void setBirthday(Birthday birthday) { + this.birthday = birthday; } - public Optional getEmail() { - return Optional.ofNullable(email); + public Optional getBirthday() { + return Optional.ofNullable(birthday); } - public void setAddress(Address address) { - this.address = address; + public void setLevelOfFriendship(LevelOfFriendship levelOfFriendship) { + this.levelOfFriendship = levelOfFriendship; } - public Optional
getAddress() { - return Optional.ofNullable(address); + public Optional getLevelOfFriendship() { + return Optional.ofNullable(levelOfFriendship); + } + + public void setUnitNumber(UnitNumber unitNumber) { + this.unitNumber = unitNumber; + } + + public Optional getUnitNumber() { + return Optional.ofNullable(unitNumber); + } + + + /** + * Sets {@code ccas} to this object's {@code ccas}. + * A defensive copy of {@code ccas} is used internally. + */ + public void setCcas(Set ccas) { + this.ccas = (ccas != null) ? new HashSet<>(ccas) : null; + } + + /** + * Returns an unmodifiable cca set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + * Returns {@code Optional#empty()} if {@code ccas} is null. + */ + public Optional> getCcas() { + return (ccas != null) ? Optional.of(Collections.unmodifiableSet(ccas)) : Optional.empty(); } /** @@ -232,8 +273,10 @@ public boolean equals(Object other) { return getName().equals(e.getName()) && getPhone().equals(e.getPhone()) - && getEmail().equals(e.getEmail()) - && getAddress().equals(e.getAddress()) + && getBirthday().equals(e.getBirthday()) + && getLevelOfFriendship().equals(e.getLevelOfFriendship()) + && getUnitNumber().equals(e.getUnitNumber()) + && getCcas().equals(e.getCcas()) && getTags().equals(e.getTags()); } } diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 2d4368be6ec1..3bca7f782f1f 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -1,11 +1,13 @@ package seedu.address.logic.parser; 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_BIRTHDAY; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CCA; +import static seedu.address.logic.parser.CliSyntax.PREFIX_LEVEL_OF_FRIENDSHIP; 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; +import static seedu.address.logic.parser.CliSyntax.PREFIX_UNIT_NUMBER; import java.util.Set; import java.util.stream.Stream; @@ -13,14 +15,17 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.logic.commands.AddCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; +import seedu.address.model.person.Birthday; +import seedu.address.model.person.Cca; +import seedu.address.model.person.LevelOfFriendship; import seedu.address.model.person.Meet; import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.person.UnitNumber; import seedu.address.model.tag.Tag; + /** * Parses input arguments and creates a new AddCommand object */ @@ -33,9 +38,11 @@ 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_PHONE, PREFIX_BIRTHDAY, + PREFIX_LEVEL_OF_FRIENDSHIP, PREFIX_UNIT_NUMBER, PREFIX_CCA, PREFIX_TAG); - if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_BIRTHDAY, PREFIX_PHONE, PREFIX_UNIT_NUMBER, + PREFIX_LEVEL_OF_FRIENDSHIP, PREFIX_UNIT_NUMBER) || !argMultimap.getPreamble().isEmpty()) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } @@ -43,13 +50,15 @@ public AddCommand parse(String args) throws ParseException { try { Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).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(); + Birthday birthday = ParserUtil.parseBirthday(argMultimap.getValue(PREFIX_BIRTHDAY)).get(); + UnitNumber unitNumber = ParserUtil.parseUnitNumber(argMultimap.getValue(PREFIX_UNIT_NUMBER)).get(); + LevelOfFriendship levelOfFriendship = ParserUtil.parseLevelOfFriendship(argMultimap + .getValue(PREFIX_LEVEL_OF_FRIENDSHIP)).get(); + Set ccaList = ParserUtil.parseCcas(argMultimap.getAllValues(PREFIX_CCA)); Meet meetDate = new Meet(""); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - - Person person = new Person(name, phone, email, address, meetDate, tagList); - + Person person = new Person(name, phone, birthday, levelOfFriendship, unitNumber, ccaList, meetDate, + tagList); return new AddCommand(person); } catch (IllegalValueException ive) { throw new ParseException(ive.getMessage(), ive); diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index 719e74b77662..ca538779d91d 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -8,8 +8,10 @@ public class CliSyntax { /* Prefix definitions */ public static final Prefix PREFIX_NAME = new Prefix("n/"); 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/"); + public static final Prefix PREFIX_BIRTHDAY = new Prefix("b/"); + public static final Prefix PREFIX_LEVEL_OF_FRIENDSHIP = new Prefix("*/"); + public static final Prefix PREFIX_UNIT_NUMBER = new Prefix("u/"); + public static final Prefix PREFIX_CCA = new Prefix("cca/"); public static final Prefix PREFIX_TAG = new Prefix("t/"); public static final Prefix PREFIX_DATE = new Prefix("d/"); diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java index c9cdbed26cf1..c0244fb6222f 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java @@ -2,11 +2,13 @@ import static java.util.Objects.requireNonNull; 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_BIRTHDAY; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CCA; +import static seedu.address.logic.parser.CliSyntax.PREFIX_LEVEL_OF_FRIENDSHIP; 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; +import static seedu.address.logic.parser.CliSyntax.PREFIX_UNIT_NUMBER; import java.util.Collection; import java.util.Collections; @@ -18,6 +20,7 @@ import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.person.Cca; import seedu.address.model.tag.Tag; /** @@ -33,7 +36,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_PHONE, PREFIX_BIRTHDAY, + PREFIX_LEVEL_OF_FRIENDSHIP, PREFIX_UNIT_NUMBER, PREFIX_CCA, PREFIX_TAG); Index index; @@ -47,8 +51,13 @@ public EditCommand parse(String args) throws ParseException { try { ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).ifPresent(editPersonDescriptor::setName); 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); + ParserUtil.parseBirthday(argMultimap.getValue(PREFIX_BIRTHDAY)) + .ifPresent(editPersonDescriptor::setBirthday); + ParserUtil.parseLevelOfFriendship(argMultimap.getValue(PREFIX_LEVEL_OF_FRIENDSHIP)) + .ifPresent(editPersonDescriptor::setLevelOfFriendship); + ParserUtil.parseUnitNumber(argMultimap.getValue(PREFIX_UNIT_NUMBER)) + .ifPresent(editPersonDescriptor::setUnitNumber); + parseCcasForEdit(argMultimap.getAllValues(PREFIX_CCA)).ifPresent(editPersonDescriptor::setCcas); parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); } catch (IllegalValueException ive) { throw new ParseException(ive.getMessage(), ive); @@ -61,6 +70,21 @@ public EditCommand parse(String args) throws ParseException { return new EditCommand(index, editPersonDescriptor); } + /** + * Parses {@code Collection ccas} into a {@code Set} if {@code ccas} is non-empty. + * If {@code ccas} contain only one element which is an empty string, it will be parsed into a + * {@code Set} containing zero ccas. + */ + private Optional> parseCcasForEdit(Collection ccas) throws IllegalValueException { + assert ccas != null; + + if (ccas.isEmpty()) { + return Optional.empty(); + } + Collection ccaSet = ccas.size() == 1 && ccas.contains("") ? Collections.emptySet() : ccas; + return Optional.of(ParserUtil.parseCcas(ccaSet)); + } + /** * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty. * If {@code tags} contain only one element which is an empty string, it will be parsed into a diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 5d6d4ae3f7b1..1201dfdc1f78 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -10,10 +10,12 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.commons.util.StringUtil; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; +import seedu.address.model.person.Birthday; +import seedu.address.model.person.Cca; +import seedu.address.model.person.LevelOfFriendship; import seedu.address.model.person.Name; import seedu.address.model.person.Phone; +import seedu.address.model.person.UnitNumber; import seedu.address.model.tag.Tag; /** @@ -92,51 +94,105 @@ public static Optional parsePhone(Optional phone) throws IllegalV } /** - * Parses a {@code String address} into an {@code Address}. + * Parses a {@code String birthday} into an {@code birthday}. * Leading and trailing whitespaces will be trimmed. * * @throws IllegalValueException if the given {@code address} is invalid. */ - public static Address parseAddress(String address) throws IllegalValueException { - requireNonNull(address); - String trimmedAddress = address.trim(); - if (!Address.isValidAddress(trimmedAddress)) { - throw new IllegalValueException(Address.MESSAGE_ADDRESS_CONSTRAINTS); + public static Birthday parseBirthday(String birthday) throws IllegalValueException { + requireNonNull(birthday); + String trimmedBirthday = birthday.trim(); + if (!Birthday.isValidBirthday(trimmedBirthday)) { + throw new IllegalValueException(Birthday.MESSAGE_BIRTHDAY_CONSTRAINTS); } - return new Address(trimmedAddress); + return new Birthday(trimmedBirthday); } /** - * Parses a {@code Optional address} into an {@code Optional
} if {@code address} is present. + * Parses a {@code Optional birthday} into an {@code Optional} if {@code birthday} is present. * See header comment of this class regarding the use of {@code Optional} parameters. */ - public static Optional
parseAddress(Optional address) throws IllegalValueException { - requireNonNull(address); - return address.isPresent() ? Optional.of(parseAddress(address.get())) : Optional.empty(); + public static Optional parseBirthday(Optional birthday) throws IllegalValueException { + requireNonNull(birthday); + return birthday.isPresent() ? Optional.of(parseBirthday(birthday.get())) : Optional.empty(); } /** - * Parses a {@code String email} into an {@code Email}. + * Parses a {@code String levelOfFriendship} into a {@code LevelOfFriendship}. * Leading and trailing whitespaces will be trimmed. * - * @throws IllegalValueException if the given {@code email} is invalid. + * @throws IllegalValueException if the given {@code levelOfFriendship} is invalid. */ - public static Email parseEmail(String email) throws IllegalValueException { - requireNonNull(email); - String trimmedEmail = email.trim(); - if (!Email.isValidEmail(trimmedEmail)) { - throw new IllegalValueException(Email.MESSAGE_EMAIL_CONSTRAINTS); + public static LevelOfFriendship parseLevelOfFriendship(String levelOfFriendship) throws IllegalValueException { + requireNonNull(levelOfFriendship); + String trimmedLevelOfFriendship = levelOfFriendship.trim(); + if (!LevelOfFriendship.isValidLevelOfFriendship(trimmedLevelOfFriendship)) { + throw new IllegalValueException(LevelOfFriendship.MESSAGE_LEVEL_OF_FRIENDSHIP_CONSTRAINTS); } - return new Email(trimmedEmail); + return new LevelOfFriendship(trimmedLevelOfFriendship); } /** - * Parses a {@code Optional email} into an {@code Optional} if {@code email} is present. + * Parses a {@code Optional name} into an {@code Optional} if {@code name} is present. + * See header comment of this class regarding the use of {@code Optional} parameters. + */ + public static Optional parseLevelOfFriendship(Optional levelOfFriendship) + throws IllegalValueException { + requireNonNull(levelOfFriendship); + return levelOfFriendship.isPresent() ? Optional.of(parseLevelOfFriendship(levelOfFriendship.get())) + : Optional.empty(); + } + + /** + * Parses a {@code String unitNumber} into an {@code UnitNumber}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws IllegalValueException if the given {@code unitNumber} is invalid. + */ + public static UnitNumber parseUnitNumber(String unitNumber) throws IllegalValueException { + requireNonNull(unitNumber); + String trimmedUnitNumber = unitNumber.trim(); + if (!UnitNumber.isValidUnitNumber(trimmedUnitNumber)) { + throw new IllegalValueException(UnitNumber.MESSAGE_UNIT_NUMBER_CONSTRAINTS); + } + return new UnitNumber(trimmedUnitNumber); + } + + /** + * Parses a {@code Optional unitNumber} into an {@code Optional} if {@code unitNumber} + * is present. * See header comment of this class regarding the use of {@code Optional} parameters. */ - public static Optional parseEmail(Optional email) throws IllegalValueException { - requireNonNull(email); - return email.isPresent() ? Optional.of(parseEmail(email.get())) : Optional.empty(); + public static Optional parseUnitNumber(Optional unitNumber) throws IllegalValueException { + requireNonNull(unitNumber); + return unitNumber.isPresent() ? Optional.of(parseUnitNumber(unitNumber.get())) : Optional.empty(); + } + + /** + * Parses a {@code String cca} into a {@code Cca}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws IllegalValueException if the given {@code cca} is invalid. + */ + public static Cca parseCca(String cca) throws IllegalValueException { + requireNonNull(cca); + String trimmedCca = cca.trim(); + if (!Cca.isValidCcaName(trimmedCca)) { + throw new IllegalValueException(Cca.MESSAGE_CCA_CONSTRAINTS); + } + return new Cca(trimmedCca); + } + + /** + * Parses {@code Collection ccas} into a {@code Set}. + */ + public static Set parseCcas(Collection ccas) throws IllegalValueException { + requireNonNull(ccas); + final Set ccaSet = new HashSet<>(); + for (String ccaName : ccas) { + ccaSet.add(parseCca(ccaName)); + } + return ccaSet; } /** diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index d9f598a8587f..df55aeabc55b 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -11,7 +11,9 @@ import java.util.stream.Collectors; import javafx.collections.ObservableList; +import seedu.address.model.person.Cca; import seedu.address.model.person.Person; +import seedu.address.model.person.UniqueCcaList; import seedu.address.model.person.UniquePersonList; import seedu.address.model.person.exceptions.DuplicatePersonException; import seedu.address.model.person.exceptions.PersonNotFoundException; @@ -25,6 +27,7 @@ public class AddressBook implements ReadOnlyAddressBook { private final UniquePersonList persons; + private final UniqueCcaList ccas; private final UniqueTagList tags; /* @@ -36,13 +39,14 @@ public class AddressBook implements ReadOnlyAddressBook { */ { persons = new UniquePersonList(); + ccas = new UniqueCcaList(); tags = new UniqueTagList(); } public AddressBook() {} /** - * Creates an AddressBook using the Persons and Tags in the {@code toBeCopied} + * Creates a CollegeZone using the Persons, Ccas and Tags in the {@code toBeCopied} */ public AddressBook(ReadOnlyAddressBook toBeCopied) { this(); @@ -55,6 +59,8 @@ public void setPersons(List persons) throws DuplicatePersonException { this.persons.setPersons(persons); } + public void setCcas(Set ccas) { this.ccas.setCcas(ccas); } + public void setTags(Set tags) { this.tags.setTags(tags); } @@ -64,29 +70,32 @@ public void setTags(Set tags) { */ public void resetData(ReadOnlyAddressBook newData) { requireNonNull(newData); + setCcas(new HashSet<>(newData.getCcaList())); setTags(new HashSet<>(newData.getTagList())); List syncedPersonList = newData.getPersonList().stream() + .map(this::syncWithMasterCcaList) .map(this::syncWithMasterTagList) .collect(Collectors.toList()); try { setPersons(syncedPersonList); } catch (DuplicatePersonException e) { - throw new AssertionError("AddressBooks should not have duplicate persons"); + throw new AssertionError("CollegeZone should not have duplicate persons"); } } //// person-level operations /** - * Adds a person to the address book. - * Also checks the new person's tags and updates {@link #tags} with any new tags found, - * and updates the Tag objects in the person to point to those in {@link #tags}. + * Adds a person to CollegeZone. + * Also checks the new person's ccas and tags, and updates {@link #ccas #tags} with any new cca and tags found, + * and updates the Cca and Tag objects in the person to point to those in {@link #ccas #tags}. * * @throws DuplicatePersonException if an equivalent person already exists. */ public void addPerson(Person p) throws DuplicatePersonException { - Person person = syncWithMasterTagList(p); + Person person = syncWithMasterCcaList(p); + person = syncWithMasterTagList(person); // TODO: the tags master list will be updated even though the below line fails. // This can cause the tags master list to have additional tags that are not tagged to any person // in the person list. @@ -95,26 +104,38 @@ public void addPerson(Person p) throws DuplicatePersonException { /** * Replaces the given person {@code target} in the list with {@code editedPerson}. - * {@code AddressBook}'s tag list will be updated with the tags of {@code editedPerson}. + * {@code CollegeZone}'s cca and tag list will be updated with the ccas and tags of {@code editedPerson}. * * @throws DuplicatePersonException if updating the person's details causes the person to be equivalent to * another existing person in the list. * @throws PersonNotFoundException if {@code target} could not be found in the list. * + * @see #syncWithMasterCcaList(Person) * @see #syncWithMasterTagList(Person) */ public void updatePerson(Person target, Person editedPerson) throws DuplicatePersonException, PersonNotFoundException { requireNonNull(editedPerson); - - Person syncedEditedPerson = syncWithMasterTagList(editedPerson); + Person syncedEditedPerson = syncWithMasterCcaList(editedPerson); + syncedEditedPerson = syncWithMasterTagList(syncedEditedPerson); // TODO: the tags master list will be updated even though the below line fails. // This can cause the tags master list to have additional tags that are not tagged to any person // in the person list. persons.setPerson(target, syncedEditedPerson); + removeUnusedCcas(); removeUnusedTags(); } + /** + * Removes all {@code Ccas}s that are not used by any {@code Person} in this {@code AddressBook}. + */ + private void removeUnusedCcas() { + Set ccasInPersons = persons.asObservableList().stream() + .map(Person::getCcas) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + ccas.setCcas(ccasInPersons); + } /** * Removes all {@code Tag}s that are not used by any {@code Person} in this {@code AddressBook}. */ @@ -126,6 +147,29 @@ private void removeUnusedTags() { tags.setTags(tagsInPersons); } + /** + * Updates the master cca list to include ccas in {@code person} that are not in the list. + * @return a copy of this {@code person} such that every cca in this person points to a Cca object in the master + * list. + */ + private Person syncWithMasterCcaList(Person person) { + final UniqueCcaList personCcas = new UniqueCcaList(person.getCcas()); + ccas.mergeFrom(personCcas); + + // Create map with values = cca object references in the master list + // used for checking person cca references + final Map masterCcaObjects = new HashMap<>(); + ccas.forEach(cca -> masterCcaObjects.put(cca, cca)); + + // Rebuild the list of person tags to point to the relevant tags in the master tag list. + final Set correctCcaReferences = new HashSet<>(); + personCcas.forEach(cca -> correctCcaReferences.add(masterCcaObjects.get(cca))); + return new Person( + person.getName(), person.getPhone(), person.getBirthday(), + person.getLevelOfFriendship(), person.getUnitNumber(), correctCcaReferences, person.getMeetDate(), + person.getTags()); + } + /** * Updates the master tag list to include tags in {@code person} that are not in the list. * @return a copy of this {@code person} such that every tag in this person points to a Tag object in the master @@ -144,8 +188,9 @@ 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(), person.getMeetDate(), correctTagReferences); + person.getName(), person.getPhone(), person.getBirthday(), + person.getLevelOfFriendship(), person.getUnitNumber(), person.getCcas(), person.getMeetDate(), + correctTagReferences); } /** @@ -160,6 +205,12 @@ public boolean removePerson(Person key) throws PersonNotFoundException { } } + //// cca-level operations + + public void addCca(Cca cca) throws UniqueCcaList.DuplicateCcaException { + ccas.add(cca); + } + //// tag-level operations public void addTag(Tag t) throws UniqueTagList.DuplicateTagException { @@ -190,9 +241,8 @@ private void removeTagFromPerson(Tag tag, Person person) throws PersonNotFoundEx } Person newPerson = - new Person(person.getName(), person.getPhone(), person.getEmail(), - person.getAddress(), person.getMeetDate(), newTags); - + new Person(person.getName(), person.getPhone(), person.getBirthday(), person.getLevelOfFriendship(), + person.getUnitNumber(), person.getCcas(), person.getMeetDate(), newTags); try { updatePerson(person, newPerson); } catch (DuplicatePersonException dpe) { @@ -205,7 +255,8 @@ private void removeTagFromPerson(Tag tag, Person person) throws PersonNotFoundEx @Override public String toString() { - return persons.asObservableList().size() + " persons, " + tags.asObservableList().size() + " tags"; + return persons.asObservableList().size() + " persons, " + ccas.asObservableList().size() + + "ccas, " + tags.asObservableList().size() + " tags"; // TODO: refine later } @@ -214,6 +265,11 @@ public ObservableList getPersonList() { return persons.asObservableList(); } + @Override + public ObservableList getCcaList() { + return ccas.asObservableList(); + } + @Override public ObservableList getTagList() { return tags.asObservableList(); @@ -224,12 +280,13 @@ public boolean equals(Object other) { return other == this // short circuit if same object || (other instanceof AddressBook // instanceof handles nulls && this.persons.equals(((AddressBook) other).persons) + && this.ccas.equalsOrderInsensitive(((AddressBook) other).ccas) && this.tags.equalsOrderInsensitive(((AddressBook) other).tags)); } @Override public int hashCode() { // use this method for custom fields hashing instead of implementing your own - return Objects.hash(persons, tags); + return Objects.hash(persons, ccas, tags); } } diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java index 1f4e49a37d67..273e214ed0ba 100644 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java @@ -1,6 +1,8 @@ package seedu.address.model; import javafx.collections.ObservableList; + +import seedu.address.model.person.Cca; import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; @@ -15,6 +17,12 @@ public interface ReadOnlyAddressBook { */ ObservableList getPersonList(); + /** + * Returns an unmodifiable view of the ccas list. + * This list will not contain any duplicate ccas. + */ + ObservableList getCcaList(); + /** * Returns an unmodifiable view of the tags list. * This list will not contain any duplicate tags. diff --git a/src/main/java/seedu/address/model/person/Birthday.java b/src/main/java/seedu/address/model/person/Birthday.java new file mode 100644 index 000000000000..1c2d6376b618 --- /dev/null +++ b/src/main/java/seedu/address/model/person/Birthday.java @@ -0,0 +1,57 @@ +package seedu.address.model.person; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents a Person's birthday in CollegeZone. + * Guarantees: immutable; is valid as declared in {@link #isValidBirthday(String)} + */ +public class Birthday { + + public static final String MESSAGE_BIRTHDAY_CONSTRAINTS = "Person birthday should be a valid date."; + public static final String BIRTHDAY_VALIDATION_REGEX = + "^(?:(?:31(\\/|-|\\.)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\\1|(?:(?:29|30)(\\/|-|\\.)" + + "(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\\2))(?:(?:1[6-9]|[2-9]\\d)" + + "?\\d{2})$|^(?:29(\\/|-|\\.)(?:0?2|(?:Feb))\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])" + + "|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.)(?:(?:0?[1-9]|" + + "(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$"; + + public final String value; + + /** + * Constructs an {@code Birthday}. + * + * @param birthday A valid birthday. + */ + public Birthday(String birthday) { + requireNonNull(birthday); + checkArgument(isValidBirthday(birthday), MESSAGE_BIRTHDAY_CONSTRAINTS); + this.value = birthday; + } + + /** + * Returns if a given string is a valid person birthday. + */ + public static boolean isValidBirthday(String test) { + return test.matches(BIRTHDAY_VALIDATION_REGEX); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Birthday // instanceof handles nulls + && this.value.equals(((Birthday) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } + +} diff --git a/src/main/java/seedu/address/model/person/Cca.java b/src/main/java/seedu/address/model/person/Cca.java new file mode 100644 index 000000000000..9363c3eea6f0 --- /dev/null +++ b/src/main/java/seedu/address/model/person/Cca.java @@ -0,0 +1,53 @@ +package seedu.address.model.person; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents a Person's CCAs in CollegeZone. + * Guarantees: immutable; is valid as declared in {@link #isValidCcaName(String)} + */ +public class Cca { + + public static final String MESSAGE_CCA_CONSTRAINTS = "CCAs should be in alphanumeric"; + public static final String CCA_VALIDATION_REGEX = "\\s*\\p{Alnum}[\\p{Alnum}\\s]*"; + public final String ccaName; + + /** + * Constructs a {@code CCA}. + * + * @param ccaName A valid CCA. + */ + public Cca(String ccaName) { + requireNonNull(ccaName); + checkArgument(isValidCcaName(ccaName), MESSAGE_CCA_CONSTRAINTS); + this.ccaName = ccaName; + } + + /** + * Returns true if a given string is a valid CCA name. + */ + public static boolean isValidCcaName(String test) { + return test.matches(CCA_VALIDATION_REGEX); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Cca // instanceof handles nulls + && this.ccaName.equals(((Cca) other).ccaName)); // state check + } + + @Override + public int hashCode() { + return ccaName.hashCode(); + } + + /** + * Format state as text for viewing. + */ + public String toString() { + return '[' + ccaName + ']'; + } + +} diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/person/Email.java deleted file mode 100644 index 3759a577ec59..000000000000 --- a/src/main/java/seedu/address/model/person/Email.java +++ /dev/null @@ -1,67 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Person's email in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)} - */ -public class Email { - - private static final String SPECIAL_CHARACTERS = "!#$%&'*+/=?`{|}~^.-"; - public static final String MESSAGE_EMAIL_CONSTRAINTS = "Person emails should be of the format local-part@domain " - + "and adhere to the following constraints:\n" - + "1. The local-part should only contain alphanumeric characters and these special characters, excluding " - + "the parentheses, (" + SPECIAL_CHARACTERS + ") .\n" - + "2. This is followed by a '@' and then a domain name. " - + "The domain name must:\n" - + " - be at least 2 characters long\n" - + " - start and end with alphanumeric characters\n" - + " - consist of alphanumeric characters, a period or a hyphen for the characters in between, if any."; - // alphanumeric and special characters - private static final String LOCAL_PART_REGEX = "^[\\w" + SPECIAL_CHARACTERS + "]+"; - private static final String DOMAIN_FIRST_CHARACTER_REGEX = "[^\\W_]"; // alphanumeric characters except underscore - private static final String DOMAIN_MIDDLE_REGEX = "[a-zA-Z0-9.-]*"; // alphanumeric, period and hyphen - private static final String DOMAIN_LAST_CHARACTER_REGEX = "[^\\W_]$"; - public static final String EMAIL_VALIDATION_REGEX = LOCAL_PART_REGEX + "@" - + DOMAIN_FIRST_CHARACTER_REGEX + DOMAIN_MIDDLE_REGEX + DOMAIN_LAST_CHARACTER_REGEX; - - public final String value; - - /** - * Constructs an {@code Email}. - * - * @param email A valid email address. - */ - public Email(String email) { - requireNonNull(email); - checkArgument(isValidEmail(email), MESSAGE_EMAIL_CONSTRAINTS); - this.value = email; - } - - /** - * Returns if a given string is a valid person email. - */ - public static boolean isValidEmail(String test) { - return test.matches(EMAIL_VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Email // instanceof handles nulls - && this.value.equals(((Email) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/person/LevelOfFriendship.java b/src/main/java/seedu/address/model/person/LevelOfFriendship.java new file mode 100644 index 000000000000..7e6db353e352 --- /dev/null +++ b/src/main/java/seedu/address/model/person/LevelOfFriendship.java @@ -0,0 +1,70 @@ +package seedu.address.model.person; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents a Person's Level of Friendship in the address book. + * Guarantees: immutable; is valid as declared in {@link #isValidLevelOfFriendship(String)} + */ +public class LevelOfFriendship { + + public static final String MESSAGE_LEVEL_OF_FRIENDSHIP_CONSTRAINTS = + "Level of Friendship should only be a numerical integer value between 1 to 10"; + public static final String LEVEL_OF_FRIENDSHIP_VALIDATION_REGEX = "[0-9]+"; + private static final int MINIMUM_LEVEL_OF_FRIENDSHIP = 1; + private static final int MAXIMUM_LEVEL_OF_FRIENDSHIP = 10; + private static int levelOfFriendshipInIntegerForm; + public final String value; + + /** + * * Constructs an {@code LevelOfFriendship}. + * + * @param levelOfFriendship A valid level of friendship number. + */ + public LevelOfFriendship(String levelOfFriendship) { + requireNonNull(levelOfFriendship); + checkArgument(isValidLevelOfFriendship(levelOfFriendship), MESSAGE_LEVEL_OF_FRIENDSHIP_CONSTRAINTS); + this.value = levelOfFriendship; + } + + /** + * Returns true if a given string is a valid person level of friendship. + */ + public static boolean isValidLevelOfFriendship(String test) { + + return test.matches(LEVEL_OF_FRIENDSHIP_VALIDATION_REGEX) && isAnIntegerWithinRange(test); + } + + /** + * Returns true if a given string is an integer and within range of level of friendship. + */ + private static boolean isAnIntegerWithinRange(String test) { + levelOfFriendshipInIntegerForm = Integer.parseInt(test); + if (levelOfFriendshipInIntegerForm >= MINIMUM_LEVEL_OF_FRIENDSHIP + && levelOfFriendshipInIntegerForm <= MAXIMUM_LEVEL_OF_FRIENDSHIP) { + return true; + } + else { + return false; + } + } + + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof LevelOfFriendship // instanceof handles nulls + && this.value.equals(((LevelOfFriendship) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/person/Meet.java b/src/main/java/seedu/address/model/person/Meet.java index 915c0b605454..4030ad6afd43 100644 --- a/src/main/java/seedu/address/model/person/Meet.java +++ b/src/main/java/seedu/address/model/person/Meet.java @@ -1,6 +1,6 @@ package seedu.address.model.person; -import static java.util.Objects.requireNonNull; +//import static java.util.Objects.requireNonNull; /** * Represents a Person's date of meeting in the address book. @@ -13,7 +13,7 @@ public class Meet { public final String value; public Meet(String meet) { - requireNonNull(meet); + //requireNonNull(meet); this.value = meet; } diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index cc271bcfdb29..550b90443b20 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -17,23 +17,28 @@ public class Person { private final Name name; private final Phone phone; - private final Email email; - private final Address address; + private final Birthday birthday; + private final LevelOfFriendship levelOfFriendship; + private final UnitNumber unitNumber; private final Meet meetDate; - + private final UniqueCcaList ccas; private final UniqueTagList tags; /** * Every field must be present and not null. */ - public Person(Name name, Phone phone, Email email, Address address, Meet meetDate, Set tags) { - requireAllNonNull(name, phone, email, address, tags); + + public Person(Name name, Phone phone, Birthday birthday, LevelOfFriendship levelOfFriendship, + UnitNumber unitNumber, Set ccas, Meet meetDate, Set tags) { + requireAllNonNull(name, phone, birthday, levelOfFriendship, unitNumber, ccas, tags); this.name = name; this.phone = phone; - this.email = email; - this.address = address; + this.birthday = birthday; + this.levelOfFriendship = levelOfFriendship; + this.unitNumber = unitNumber; this.meetDate = meetDate; - // protect internal tags from changes in the arg list + // protect internal tags and ccas from changes in the arg list + this.ccas = new UniqueCcaList(ccas); this.tags = new UniqueTagList(tags); } @@ -45,16 +50,26 @@ public Phone getPhone() { return phone; } - public Email getEmail() { - return email; + public Birthday getBirthday() { + return birthday; } - public Address getAddress() { - return address; + public LevelOfFriendship getLevelOfFriendship() { + return levelOfFriendship; } - public Meet getMeetDate() { return meetDate; } + public UnitNumber getUnitNumber() { + return unitNumber; + } + /** + * Returns an immutable cca set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + */ + public Set getCcas() { + return Collections.unmodifiableSet(ccas.toSet()); + } + public Meet getMeetDate() { return meetDate; } /** * Returns an immutable tag set, which throws {@code UnsupportedOperationException} * if modification is attempted. @@ -76,14 +91,15 @@ public boolean equals(Object other) { Person otherPerson = (Person) other; return otherPerson.getName().equals(this.getName()) && otherPerson.getPhone().equals(this.getPhone()) - && otherPerson.getEmail().equals(this.getEmail()) - && otherPerson.getAddress().equals(this.getAddress()); + && otherPerson.getBirthday().equals(this.getBirthday()) + && otherPerson.getLevelOfFriendship().equals(this.getLevelOfFriendship()) + && otherPerson.getUnitNumber().equals(this.getUnitNumber()); } @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, phone, birthday, levelOfFriendship, unitNumber, ccas, tags); } @Override @@ -92,11 +108,15 @@ public String toString() { builder.append(getName()) .append(" Phone: ") .append(getPhone()) - .append(" Email: ") - .append(getEmail()) - .append(" Address: ") - .append(getAddress()) - .append(" Tags: "); + .append(" Birthday: ") + .append(getBirthday()) + .append(" Level Of Friendship: ") + .append(getLevelOfFriendship()) + .append(" Unit Number: ") + .append(getUnitNumber()) + .append(" Ccas: "); + getCcas().forEach(builder::append); + builder.append(" Tags: "); getTags().forEach(builder::append); return builder.toString(); } diff --git a/src/main/java/seedu/address/model/person/UniqueCcaList.java b/src/main/java/seedu/address/model/person/UniqueCcaList.java new file mode 100644 index 000000000000..89e1c3c39510 --- /dev/null +++ b/src/main/java/seedu/address/model/person/UniqueCcaList.java @@ -0,0 +1,142 @@ +package seedu.address.model.person; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.address.commons.exceptions.DuplicateDataException; +import seedu.address.commons.util.CollectionUtil; + +/** + * A list of ccas that enforces no nulls and uniqueness between its elements. + * + * Supports minimal set of list operations for the app's features. + * + * @see Cca#equals(Object) + */ +public class UniqueCcaList implements Iterable { + + private final ObservableList internalList = FXCollections.observableArrayList(); + + /** + * Constructs empty CcaList. + */ + public UniqueCcaList() {} + + /** + * Creates a UniqueCcaList using given ccas. + * Enforces no nulls. + */ + public UniqueCcaList(Set ccas) { + requireAllNonNull(ccas); + internalList.addAll(ccas); + + assert CollectionUtil.elementsAreUnique(internalList); + } + + /** + * Returns all ccas in this list as a Set. + * This set is mutable and change-insulated against the internal list. + */ + public Set toSet() { + assert CollectionUtil.elementsAreUnique(internalList); + return new HashSet<>(internalList); + } + + /** + * Replaces the Ccas in this list with those in the argument cca list. + */ + public void setCcas(Set ccas) { + requireAllNonNull(ccas); + internalList.setAll(ccas); + assert CollectionUtil.elementsAreUnique(internalList); + } + + /** + * Ensures every tag in the argument list exists in this object. + */ + public void mergeFrom(UniqueCcaList from) { + final Set alreadyInside = this.toSet(); + from.internalList.stream() + .filter(cca -> !alreadyInside.contains(cca)) + .forEach(internalList::add); + + assert CollectionUtil.elementsAreUnique(internalList); + } + + /** + * Returns true if the list contains an equivalent Cca as the given argument. + */ + public boolean contains(Cca toCheck) { + requireNonNull(toCheck); + return internalList.contains(toCheck); + } + + /** + * Adds a Cca to the list. + * + * @throws DuplicateCcaException if the Cca to add is a duplicate of an existing Cca in the list. + */ + public void add(Cca toAdd) throws DuplicateCcaException { + requireNonNull(toAdd); + if (contains(toAdd)) { + throw new DuplicateCcaException(); + } + internalList.add(toAdd); + + assert CollectionUtil.elementsAreUnique(internalList); + } + + @Override + public Iterator iterator() { + assert CollectionUtil.elementsAreUnique(internalList); + return internalList.iterator(); + } + + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ + public ObservableList asObservableList() { + assert CollectionUtil.elementsAreUnique(internalList); + return FXCollections.unmodifiableObservableList(internalList); + } + + @Override + public boolean equals(Object other) { + assert CollectionUtil.elementsAreUnique(internalList); + return other == this // short circuit if same object + || (other instanceof UniqueCcaList // instanceof handles nulls + && this.internalList.equals(((UniqueCcaList) other).internalList)); + } + + /** + * Returns true if the element in this list is equal to the elements in {@code other}. + * The elements do not have to be in the same order. + */ + public boolean equalsOrderInsensitive(UniqueCcaList other) { + assert CollectionUtil.elementsAreUnique(internalList); + assert CollectionUtil.elementsAreUnique(other.internalList); + return this == other || new HashSet<>(this.internalList).equals(new HashSet<>(other.internalList)); + } + + @Override + public int hashCode() { + assert CollectionUtil.elementsAreUnique(internalList); + return internalList.hashCode(); + } + + /** + * Signals that an operation would have violated the 'no duplicates' property of the list. + */ + public static class DuplicateCcaException extends DuplicateDataException { + protected DuplicateCcaException() { + super("Operation would result in duplicate ccas"); + } + } + +} diff --git a/src/main/java/seedu/address/model/person/UnitNumber.java b/src/main/java/seedu/address/model/person/UnitNumber.java new file mode 100644 index 000000000000..08bac87c0a88 --- /dev/null +++ b/src/main/java/seedu/address/model/person/UnitNumber.java @@ -0,0 +1,52 @@ +package seedu.address.model.person; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents a RC4 resident Unit Number in CollegeZone. + * Guarantees: immutable; is valid as declared in {@link #isValidUnitNumber(String)} + */ +public class UnitNumber { + + public static final String MESSAGE_UNIT_NUMBER_CONSTRAINTS = + "Unit Number should contain #, - and alphanumerical values."; + public static final String UNIT_NUMBER_VALIDATION_REGEX = "[^\\s].*"; + public final String value; + + /** + * * Constructs an {@code UnitNumber}. + * + * @param unitNumber A valid unit number. + */ + public UnitNumber(String unitNumber) { + requireNonNull(unitNumber); + checkArgument(isValidUnitNumber(unitNumber), MESSAGE_UNIT_NUMBER_CONSTRAINTS); + this.value = unitNumber; + } + + /** + * Returns true if a given string is a valid unit number. + */ + public static boolean isValidUnitNumber(String test) { + + return test.matches(UNIT_NUMBER_VALIDATION_REGEX); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof UnitNumber // instanceof handles nulls + && this.value.equals(((UnitNumber) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 3112de1b36a3..dd3c6a50544b 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -5,17 +5,19 @@ import seedu.address.model.AddressBook; import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; +import seedu.address.model.person.Birthday; +import seedu.address.model.person.Cca; +import seedu.address.model.person.LevelOfFriendship; import seedu.address.model.person.Meet; import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.person.UnitNumber; import seedu.address.model.person.exceptions.DuplicatePersonException; import seedu.address.model.tag.Tag; /** - * Contains utility methods for populating {@code AddressBook} with sample data. + * Contains utility methods for populating {@code CollegeZone} with sample data. */ public class SampleDataUtil { @@ -23,24 +25,24 @@ 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 Address("Blk 30 Geylang Street 29, #06-40"), EMPTY_MEET_DATE, - getTagSet("friends")), - new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), - new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), EMPTY_MEET_DATE, - getTagSet("colleagues", "friends")), - new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), - new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), EMPTY_MEET_DATE, - getTagSet("neighbours")), - new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), - new Address("Blk 436 Serangoon Gardens Street 26, #16-43"), EMPTY_MEET_DATE, - getTagSet("family")), - new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), - new Address("Blk 47 Tampines Street 20, #17-35"), EMPTY_MEET_DATE, - getTagSet("classmates")), - new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), - new Address("Blk 45 Aljunied Street 85, #11-31"), EMPTY_MEET_DATE, - getTagSet("colleagues")) + new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Birthday("1-01-1997"), + new LevelOfFriendship("5"), new UnitNumber("#06-40"), getCcaSet("Basketball"), + EMPTY_MEET_DATE, getTagSet("friends")), + new Person(new Name("Bernice Yu"), new Phone("99272758"), new Birthday("21-2-1990"), + new LevelOfFriendship("9"), new UnitNumber("#07-18"), getCcaSet(), + EMPTY_MEET_DATE, getTagSet("colleagues", "friends")), + new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Birthday("5/9/1980"), + new LevelOfFriendship("1"), new UnitNumber("#11-04"), getCcaSet("Swimming"), + EMPTY_MEET_DATE, getTagSet("neighbours")), + new Person(new Name("David Li"), new Phone("91031282"), new Birthday("20-2-1995"), + new LevelOfFriendship("6"), new UnitNumber("#16-43"), getCcaSet(), + EMPTY_MEET_DATE, getTagSet("family")), + new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Birthday("01-01-1999"), + new LevelOfFriendship("7"), new UnitNumber("#16-41"), getCcaSet(), + EMPTY_MEET_DATE, getTagSet("classmates")), + new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Birthday("2/04/1995"), + new LevelOfFriendship("10"), new UnitNumber("#6-43"), getCcaSet("Computing club", "Anime Club"), + EMPTY_MEET_DATE, getTagSet("colleagues")) }; } @@ -56,6 +58,18 @@ public static ReadOnlyAddressBook getSampleAddressBook() { } } + /** + * Returns a cca set containing the list of strings given. + */ + public static Set getCcaSet(String... strings) { + HashSet ccas = new HashSet<>(); + for (String s : strings) { + ccas.add(new Cca(s)); + } + + return ccas; + } + /** * Returns a tag set containing the list of strings given. */ diff --git a/src/main/java/seedu/address/storage/XmlAdaptedCca.java b/src/main/java/seedu/address/storage/XmlAdaptedCca.java new file mode 100644 index 000000000000..880c4e7cdb41 --- /dev/null +++ b/src/main/java/seedu/address/storage/XmlAdaptedCca.java @@ -0,0 +1,62 @@ +package seedu.address.storage; + +import javax.xml.bind.annotation.XmlValue; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.person.Cca; + +/** + * JAXB-friendly adapted version of the Cca. + */ +public class XmlAdaptedCca { + + @XmlValue + private String ccaName; + + /** + * Constructs an XmlAdaptedCca. + * This is the no-arg constructor that is required by JAXB. + */ + public XmlAdaptedCca() {} + + /** + * Constructs a {@code XmlAdaptedCca} with the given {@code ccaName}. + */ + public XmlAdaptedCca(String ccaName) { + this.ccaName = ccaName; + } + + /** + * Converts a given Tag into this class for JAXB use. + * + * @param source future changes to this will not affect the created + */ + public XmlAdaptedCca(Cca source) { + ccaName = source.ccaName; + } + + /** + * Converts this jaxb-friendly adapted cca object into the model's Cca object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted person + */ + public Cca toModelType() throws IllegalValueException { + if (!Cca.isValidCcaName(ccaName)) { + throw new IllegalValueException(Cca.MESSAGE_CCA_CONSTRAINTS); + } + return new Cca(ccaName); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof XmlAdaptedCca)) { + return false; + } + + return ccaName.equals(((XmlAdaptedCca) other).ccaName); + } +} diff --git a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java index 338bf69bf4f8..194d4cb3899d 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java @@ -9,12 +9,14 @@ import javax.xml.bind.annotation.XmlElement; import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; +import seedu.address.model.person.Birthday; +import seedu.address.model.person.Cca; +import seedu.address.model.person.LevelOfFriendship; import seedu.address.model.person.Meet; import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.person.UnitNumber; import seedu.address.model.tag.Tag; /** @@ -29,12 +31,16 @@ public class XmlAdaptedPerson { @XmlElement(required = true) private String phone; @XmlElement(required = true) - private String email; + private String birthday; @XmlElement(required = true) - private String address; + private String levelOfFriendship; + @XmlElement(required = true) + private String unitNumber; @XmlElement(required = true) private String meetDate; + @XmlElement + private List ccas = new ArrayList<>(); @XmlElement private List tagged = new ArrayList<>(); @@ -47,11 +53,16 @@ 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 phone, String birthday, String levelOfFriendship, String unitNumber, + List ccas, List tagged) { this.name = name; this.phone = phone; - this.email = email; - this.address = address; + this.birthday = birthday; + this.levelOfFriendship = levelOfFriendship; + this.unitNumber = unitNumber; + if (ccas != null) { + this.ccas = new ArrayList<>(ccas); + } if (tagged != null) { this.tagged = new ArrayList<>(tagged); } @@ -65,8 +76,13 @@ public XmlAdaptedPerson(String name, String phone, String email, String address, public XmlAdaptedPerson(Person source) { name = source.getName().fullName; phone = source.getPhone().value; - email = source.getEmail().value; - address = source.getAddress().value; + birthday = source.getBirthday().value; + levelOfFriendship = source.getLevelOfFriendship().value; + unitNumber = source.getUnitNumber().value; + ccas = new ArrayList<>(); + for (Cca cca : source.getCcas()) { + ccas.add(new XmlAdaptedCca(cca)); + } tagged = new ArrayList<>(); meetDate = source.getMeetDate().value; for (Tag tag : source.getTags()) { @@ -80,6 +96,10 @@ public XmlAdaptedPerson(Person source) { * @throws IllegalValueException if there were any data constraints violated in the adapted person */ public Person toModelType() throws IllegalValueException { + final List personCcas = new ArrayList<>(); + for (XmlAdaptedCca cca : ccas) { + personCcas.add(cca.toModelType()); + } final List personTags = new ArrayList<>(); for (XmlAdaptedTag tag : tagged) { personTags.add(tag.toModelType()); @@ -101,26 +121,39 @@ public Person toModelType() throws IllegalValueException { } final Phone phone = new Phone(this.phone); - if (this.email == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName())); + if (this.birthday == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + Birthday.class.getSimpleName())); } - if (!Email.isValidEmail(this.email)) { - throw new IllegalValueException(Email.MESSAGE_EMAIL_CONSTRAINTS); + if (!Birthday.isValidBirthday(this.birthday)) { + throw new IllegalValueException(Birthday.MESSAGE_BIRTHDAY_CONSTRAINTS); } - final Email email = new Email(this.email); + final Birthday birthday = new Birthday(this.birthday); - if (this.address == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName())); + if (this.levelOfFriendship == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, LevelOfFriendship + .class.getSimpleName())); } - if (!Address.isValidAddress(this.address)) { - throw new IllegalValueException(Address.MESSAGE_ADDRESS_CONSTRAINTS); + if (!LevelOfFriendship.isValidLevelOfFriendship(this.levelOfFriendship)) { + throw new IllegalValueException(LevelOfFriendship.MESSAGE_LEVEL_OF_FRIENDSHIP_CONSTRAINTS); } - final Address address = new Address(this.address); + final LevelOfFriendship levelOfFriendship = new LevelOfFriendship(this.levelOfFriendship); final Meet meetDate = new Meet(this.meetDate); + if (this.unitNumber == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + UnitNumber.class.getSimpleName())); + } + if (!UnitNumber.isValidUnitNumber(this.unitNumber)) { + throw new IllegalValueException(UnitNumber.MESSAGE_UNIT_NUMBER_CONSTRAINTS); + } + final UnitNumber unitNumber = new UnitNumber(this.unitNumber); + final Set ccas = new HashSet<>(personCcas); + //final Meet meetDate = new Meet(""); + // TODO: To be fixed in later commit final Set tags = new HashSet<>(personTags); - return new Person(name, phone, email, address, meetDate, tags); + return new Person(name, phone, birthday, levelOfFriendship, unitNumber, ccas, meetDate, tags); } @Override @@ -136,8 +169,10 @@ public boolean equals(Object other) { XmlAdaptedPerson otherPerson = (XmlAdaptedPerson) other; return Objects.equals(name, otherPerson.name) && Objects.equals(phone, otherPerson.phone) - && Objects.equals(email, otherPerson.email) - && Objects.equals(address, otherPerson.address) + && Objects.equals(birthday, otherPerson.birthday) + && Objects.equals(levelOfFriendship, otherPerson.levelOfFriendship) + && Objects.equals(unitNumber, otherPerson.unitNumber) + && ccas.equals(otherPerson.ccas) && tagged.equals(otherPerson.tagged); } } diff --git a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java b/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java index dc820896c312..257ba73efc70 100644 --- a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java +++ b/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java @@ -20,6 +20,8 @@ public class XmlSerializableAddressBook { @XmlElement private List persons; @XmlElement + private List ccas; + @XmlElement private List tags; /** @@ -28,6 +30,7 @@ public class XmlSerializableAddressBook { */ public XmlSerializableAddressBook() { persons = new ArrayList<>(); + ccas = new ArrayList<>(); tags = new ArrayList<>(); } @@ -37,6 +40,7 @@ public XmlSerializableAddressBook() { public XmlSerializableAddressBook(ReadOnlyAddressBook src) { this(); persons.addAll(src.getPersonList().stream().map(XmlAdaptedPerson::new).collect(Collectors.toList())); + ccas.addAll(src.getCcaList().stream().map(XmlAdaptedCca::new).collect(Collectors.toList())); tags.addAll(src.getTagList().stream().map(XmlAdaptedTag::new).collect(Collectors.toList())); } @@ -44,10 +48,13 @@ public XmlSerializableAddressBook(ReadOnlyAddressBook src) { * Converts this addressbook into the model's {@code AddressBook} object. * * @throws IllegalValueException if there were any data constraints violated or duplicates in the - * {@code XmlAdaptedPerson} or {@code XmlAdaptedTag}. + * {@code XmlAdaptedPerson}or {@code XmlAdaptedCca} or {@code XmlAdaptedTag}. */ public AddressBook toModelType() throws IllegalValueException { AddressBook addressBook = new AddressBook(); + for (XmlAdaptedCca c : ccas) { + addressBook.addCca(c.toModelType()); + } for (XmlAdaptedTag t : tags) { addressBook.addTag(t.toModelType()); } @@ -68,6 +75,6 @@ public boolean equals(Object other) { } XmlSerializableAddressBook otherAb = (XmlSerializableAddressBook) other; - return persons.equals(otherAb.persons) && tags.equals(otherAb.tags); + return persons.equals(otherAb.persons) && ccas.equals(otherAb.ccas) && tags.equals(otherAb.tags); } } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index 20168dc81c4f..393136f765af 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -1,12 +1,17 @@ package seedu.address.ui; +import java.util.Iterator; +import java.util.Set; + import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.FlowPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Region; +import seedu.address.model.person.Cca; import seedu.address.model.person.Person; + /** * An UI component that displays information of a {@code Person}. */ @@ -34,9 +39,13 @@ public class PersonCard extends UiPart { @FXML private Label phone; @FXML - private Label address; + private Label birthday; + @FXML + private Label levelOfFriendship; @FXML - private Label email; + private Label unitNumber; + @FXML + private Label ccas; @FXML private Label meetDate; @FXML @@ -48,8 +57,10 @@ public PersonCard(Person person, int displayedIndex) { id.setText(displayedIndex + ". "); name.setText(person.getName().fullName); phone.setText(person.getPhone().value); - address.setText(person.getAddress().value); - email.setText(person.getEmail().value); + birthday.setText(person.getBirthday().value); + levelOfFriendship.setText(changeLevelOfFriendshipToHeart(person.getLevelOfFriendship().value)); + unitNumber.setText(person.getUnitNumber().value); + ccas.setText(getCcasInString(person.getCcas())); meetDate.setText(person.getMeetDate().value); initTags(person); } @@ -74,6 +85,27 @@ private void initTags(Person person) { }); } + private String getCcasInString(Set ccas) { + String ccasValue = ""; + Iterator iterator = ccas.iterator(); + while (iterator.hasNext()) { + ccasValue = ccasValue + iterator.next().toString() + " "; + } + return ccasValue; + } + + /** + * Takes in @param value representing the level of friendship value + * @return a number of hearts string. + */ + public static String changeLevelOfFriendshipToHeart(String value) { + int intValue = Integer.parseInt(value); + String heartString = ""; + for (int i = 0; i < intValue; i++) { + heartString = heartString + '\u2665' + " "; + } + return heartString; + } @Override public boolean equals(Object other) { // short circuit if same object diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 1dadb95b6ffe..b6f60b6a9559 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -33,6 +33,7 @@ + diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index e4554046178c..1910e943714f 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -29,8 +29,10 @@