From cdaa666c76b9917968fa3f89184e0f26226031b1 Mon Sep 17 00:00:00 2001 From: BunnyHoppp Date: Thu, 24 Oct 2024 02:47:04 +0800 Subject: [PATCH 1/8] Add comparator for each person attribute Allow user to compare each person based on their different attribute --- .../seedu/address/model/person/EcName.java | 6 +++- .../seedu/address/model/person/EcNumber.java | 17 +++++++++- .../seedu/address/model/person/Email.java | 6 +++- .../seedu/address/model/person/Phone.java | 14 +++++++- .../address/model/person/RegisterNumber.java | 13 +++++++- .../java/seedu/address/model/person/Sex.java | 7 +++- .../address/model/person/StudentClass.java | 6 +++- .../person/comparator/AddressCompare.java | 15 +++++++++ .../person/comparator/EcNameCompare.java | 15 +++++++++ .../person/comparator/EcNumberCompare.java | 15 +++++++++ .../model/person/comparator/EmailCompare.java | 15 +++++++++ .../model/person/comparator/NameCompare.java | 15 +++++++++ .../person/comparator/PersonCompare.java | 12 +++++++ .../model/person/comparator/PhoneCompare.java | 13 ++++++++ .../comparator/RegisterNumberCompare.java | 15 +++++++++ .../model/person/comparator/SexCompare.java | 15 +++++++++ .../comparator/StudentClassCompare.java | 15 +++++++++ .../address/model/person/EcNumberTest.java | 15 +++++++++ .../seedu/address/model/person/PhoneTest.java | 10 ++++++ .../model/person/RegisterNumberTest.java | 10 ++++++ .../person/comparator/AddressCompareTest.java | 33 +++++++++++++++++++ .../person/comparator/EcNameCompareTest.java | 33 +++++++++++++++++++ .../comparator/EcNumberCompareTest.java | 33 +++++++++++++++++++ .../person/comparator/EmailCompareTest.java | 33 +++++++++++++++++++ .../person/comparator/NameCompareTest.java | 33 +++++++++++++++++++ .../person/comparator/PhoneCompareTest.java | 33 +++++++++++++++++++ .../comparator/RegisterNumberCompareTest.java | 33 +++++++++++++++++++ .../person/comparator/SexCompareTest.java | 33 +++++++++++++++++++ .../comparator/StudentClassCompareTest.java | 33 +++++++++++++++++++ 29 files changed, 539 insertions(+), 7 deletions(-) create mode 100644 src/main/java/seedu/address/model/person/comparator/AddressCompare.java create mode 100644 src/main/java/seedu/address/model/person/comparator/EcNameCompare.java create mode 100644 src/main/java/seedu/address/model/person/comparator/EcNumberCompare.java create mode 100644 src/main/java/seedu/address/model/person/comparator/EmailCompare.java create mode 100644 src/main/java/seedu/address/model/person/comparator/NameCompare.java create mode 100644 src/main/java/seedu/address/model/person/comparator/PersonCompare.java create mode 100644 src/main/java/seedu/address/model/person/comparator/PhoneCompare.java create mode 100644 src/main/java/seedu/address/model/person/comparator/RegisterNumberCompare.java create mode 100644 src/main/java/seedu/address/model/person/comparator/SexCompare.java create mode 100644 src/main/java/seedu/address/model/person/comparator/StudentClassCompare.java create mode 100644 src/test/java/seedu/address/model/person/comparator/AddressCompareTest.java create mode 100644 src/test/java/seedu/address/model/person/comparator/EcNameCompareTest.java create mode 100644 src/test/java/seedu/address/model/person/comparator/EcNumberCompareTest.java create mode 100644 src/test/java/seedu/address/model/person/comparator/EmailCompareTest.java create mode 100644 src/test/java/seedu/address/model/person/comparator/NameCompareTest.java create mode 100644 src/test/java/seedu/address/model/person/comparator/PhoneCompareTest.java create mode 100644 src/test/java/seedu/address/model/person/comparator/RegisterNumberCompareTest.java create mode 100644 src/test/java/seedu/address/model/person/comparator/SexCompareTest.java create mode 100644 src/test/java/seedu/address/model/person/comparator/StudentClassCompareTest.java diff --git a/src/main/java/seedu/address/model/person/EcName.java b/src/main/java/seedu/address/model/person/EcName.java index f5a860bdab1..69ad820b580 100644 --- a/src/main/java/seedu/address/model/person/EcName.java +++ b/src/main/java/seedu/address/model/person/EcName.java @@ -7,7 +7,7 @@ * Represents a person's emergency contact name in the address book * The name can be empty or contain only alphanumeric characters and spaces. */ -public class EcName { +public class EcName implements Comparable { public static final String MESSAGE_CONSTRAINTS = "Emergency contact names should only contain alphanumeric characters and spaces, " @@ -64,4 +64,8 @@ public int hashCode() { return value.hashCode(); } + @Override + public int compareTo(EcName e) { + return this.toString().compareTo(e.toString()); + } } diff --git a/src/main/java/seedu/address/model/person/EcNumber.java b/src/main/java/seedu/address/model/person/EcNumber.java index 1d019ea32cf..5a199c88933 100644 --- a/src/main/java/seedu/address/model/person/EcNumber.java +++ b/src/main/java/seedu/address/model/person/EcNumber.java @@ -7,7 +7,7 @@ * Represents a Person's emergency phone number in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidEcNumber(String)} */ -public class EcNumber { +public class EcNumber implements Comparable { public static final String MESSAGE_CONSTRAINTS = "Emergency contact numbers should contain numbers that are 8 digits long\n" @@ -33,6 +33,16 @@ public static boolean isValidEcNumber(String number) { return number != null && (number.matches(VALIDATION_REGEX) || number.isEmpty()); } + /** + * Returns the integer representation of EcNumber + */ + public Integer toInt() { + if (value.isEmpty()) { + return Integer.MAX_VALUE; + } + return Integer.valueOf(this.value); + } + @Override public String toString() { return value; @@ -58,4 +68,9 @@ public int hashCode() { return value.hashCode(); } + @Override + public int compareTo(EcNumber e) { + return this.toInt().compareTo(e.toInt()); + } + } diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/person/Email.java index c62e512bc29..89dda94206e 100644 --- a/src/main/java/seedu/address/model/person/Email.java +++ b/src/main/java/seedu/address/model/person/Email.java @@ -7,7 +7,7 @@ * Represents a Person's email in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)} */ -public class Email { +public class Email implements Comparable { private static final String SPECIAL_CHARACTERS = "+_.-"; public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain " @@ -76,4 +76,8 @@ public int hashCode() { return value.hashCode(); } + @Override + public int compareTo(Email email) { + return this.toString().compareTo(email.toString()); + } } diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/person/Phone.java index d733f63d739..715aa4dfac1 100644 --- a/src/main/java/seedu/address/model/person/Phone.java +++ b/src/main/java/seedu/address/model/person/Phone.java @@ -7,7 +7,7 @@ * Represents a Person's phone number in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)} */ -public class Phone { +public class Phone implements Comparable { public static final String MESSAGE_CONSTRAINTS = @@ -33,6 +33,13 @@ public static boolean isValidPhone(String test) { return test.matches(VALIDATION_REGEX); } + /** + * Returns the integer representation of Phone + */ + public Integer toInt() { + return Integer.valueOf(this.value); + } + @Override public String toString() { return value; @@ -58,4 +65,9 @@ public int hashCode() { return value.hashCode(); } + @Override + public int compareTo(Phone phone) { + return this.toInt().compareTo(phone.toInt()); + } + } diff --git a/src/main/java/seedu/address/model/person/RegisterNumber.java b/src/main/java/seedu/address/model/person/RegisterNumber.java index d1f5b0c9847..543b4f5b5c1 100644 --- a/src/main/java/seedu/address/model/person/RegisterNumber.java +++ b/src/main/java/seedu/address/model/person/RegisterNumber.java @@ -7,7 +7,7 @@ * Represents a Person's register value in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidRegisterNumber(String)} */ -public class RegisterNumber { +public class RegisterNumber implements Comparable { public static final String MESSAGE_CONSTRAINTS = "Register value should be a value between 1 and 40."; @@ -34,6 +34,12 @@ public static boolean isValidRegisterNumber(String test) { return test.matches(VALIDATION_REGEX); } + /** + * Returns the integer representation of RegisterNumber + */ + public Integer toInt() { + return Integer.valueOf(this.value); + } @Override public String toString() { @@ -60,4 +66,9 @@ public int hashCode() { return value.hashCode(); } + @Override + public int compareTo(RegisterNumber r) { + return this.toInt().compareTo(r.toInt()); + } + } diff --git a/src/main/java/seedu/address/model/person/Sex.java b/src/main/java/seedu/address/model/person/Sex.java index c229a2c7c0c..565252f630d 100644 --- a/src/main/java/seedu/address/model/person/Sex.java +++ b/src/main/java/seedu/address/model/person/Sex.java @@ -7,7 +7,7 @@ * Represents a Person's sex in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidSex(String)} */ -public class Sex { +public class Sex implements Comparable { public static final String MESSAGE_CONSTRAINTS = "Sex can only take \"M\" or \"F\""; @@ -62,4 +62,9 @@ public int hashCode() { return value.hashCode(); } + @Override + public int compareTo(Sex s) { + return this.toString().compareTo(s.toString()); + } + } diff --git a/src/main/java/seedu/address/model/person/StudentClass.java b/src/main/java/seedu/address/model/person/StudentClass.java index 0c39d6bd72b..2a1e4348811 100644 --- a/src/main/java/seedu/address/model/person/StudentClass.java +++ b/src/main/java/seedu/address/model/person/StudentClass.java @@ -7,7 +7,7 @@ * Represents a Person's class in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidStudentClass(String)} */ -public class StudentClass { +public class StudentClass implements Comparable { public static final String MESSAGE_CONSTRAINTS = "Classes should a non-zero digit followed by an alphabet"; @@ -62,4 +62,8 @@ public int hashCode() { return value.hashCode(); } + @Override + public int compareTo(StudentClass s) { + return this.toString().compareTo(s.toString()); + } } diff --git a/src/main/java/seedu/address/model/person/comparator/AddressCompare.java b/src/main/java/seedu/address/model/person/comparator/AddressCompare.java new file mode 100644 index 00000000000..fc78e9d7643 --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/AddressCompare.java @@ -0,0 +1,15 @@ +package seedu.address.model.person.comparator; + +import seedu.address.model.person.Person; + +/** + * A class to compare two Person objects with their Address + */ +public class AddressCompare extends PersonCompare { + + @Override + public int compare(Person p1, Person p2) { + return p1.getAddress().compareTo(p2.getAddress()); + } + +} diff --git a/src/main/java/seedu/address/model/person/comparator/EcNameCompare.java b/src/main/java/seedu/address/model/person/comparator/EcNameCompare.java new file mode 100644 index 00000000000..2f1015c74f3 --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/EcNameCompare.java @@ -0,0 +1,15 @@ +package seedu.address.model.person.comparator; + +import seedu.address.model.person.Person; + +/** + * A class to compare two Person objects based on their EcName + */ +public class EcNameCompare extends PersonCompare { + + @Override + public int compare(Person p1, Person p2) { + return p1.getEcName().compareTo(p2.getEcName()); + } + +} diff --git a/src/main/java/seedu/address/model/person/comparator/EcNumberCompare.java b/src/main/java/seedu/address/model/person/comparator/EcNumberCompare.java new file mode 100644 index 00000000000..16e5c88e37b --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/EcNumberCompare.java @@ -0,0 +1,15 @@ +package seedu.address.model.person.comparator; + +import seedu.address.model.person.Person; + +/** + * A class to compare two Person objects based on their EcNumber + */ +public class EcNumberCompare extends PersonCompare { + + @Override + public int compare(Person p1, Person p2) { + return p1.getEcNumber().compareTo(p2.getEcNumber()); + } + +} diff --git a/src/main/java/seedu/address/model/person/comparator/EmailCompare.java b/src/main/java/seedu/address/model/person/comparator/EmailCompare.java new file mode 100644 index 00000000000..60549b56b07 --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/EmailCompare.java @@ -0,0 +1,15 @@ +package seedu.address.model.person.comparator; + +import seedu.address.model.person.Person; + +/** + * A class to compare two Person objects based on Email + */ +public class EmailCompare extends PersonCompare { + + @Override + public int compare(Person p1, Person p2) { + return p1.getEmail().compareTo(p2.getEmail()); + } + +} diff --git a/src/main/java/seedu/address/model/person/comparator/NameCompare.java b/src/main/java/seedu/address/model/person/comparator/NameCompare.java new file mode 100644 index 00000000000..d6020106964 --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/NameCompare.java @@ -0,0 +1,15 @@ +package seedu.address.model.person.comparator; + +import seedu.address.model.person.Person; + +/** + * A class to compare two Person objects based on name + */ +public class NameCompare extends PersonCompare { + + @Override + public int compare(Person p1, Person p2) { + return p1.getName().compareTo(p2.getName()); + } + +} diff --git a/src/main/java/seedu/address/model/person/comparator/PersonCompare.java b/src/main/java/seedu/address/model/person/comparator/PersonCompare.java new file mode 100644 index 00000000000..40568842ecd --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/PersonCompare.java @@ -0,0 +1,12 @@ +package seedu.address.model.person.comparator; + +import java.util.Comparator; + +import seedu.address.model.person.Person; + +/** + * Represents a class to compare two Person objects based on the specific attribute + */ +public abstract class PersonCompare implements Comparator { + +} diff --git a/src/main/java/seedu/address/model/person/comparator/PhoneCompare.java b/src/main/java/seedu/address/model/person/comparator/PhoneCompare.java new file mode 100644 index 00000000000..4d14f2a1b1b --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/PhoneCompare.java @@ -0,0 +1,13 @@ +package seedu.address.model.person.comparator; + +import seedu.address.model.person.Person; + +/** + * A class to compare two Person objects based on their phone number + */ +public class PhoneCompare extends PersonCompare { + @Override + public int compare(Person p1, Person p2) { + return p1.getPhone().compareTo(p2.getPhone()); + } +} diff --git a/src/main/java/seedu/address/model/person/comparator/RegisterNumberCompare.java b/src/main/java/seedu/address/model/person/comparator/RegisterNumberCompare.java new file mode 100644 index 00000000000..86ab06bae50 --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/RegisterNumberCompare.java @@ -0,0 +1,15 @@ +package seedu.address.model.person.comparator; + +import seedu.address.model.person.Person; + +/** + * A class to compare two Person objects using RegisterNumber + */ +public class RegisterNumberCompare extends PersonCompare { + + @Override + public int compare(Person p1, Person p2) { + return p1.getRegisterNumber().compareTo(p2.getRegisterNumber()); + } + +} diff --git a/src/main/java/seedu/address/model/person/comparator/SexCompare.java b/src/main/java/seedu/address/model/person/comparator/SexCompare.java new file mode 100644 index 00000000000..1bbe9edc993 --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/SexCompare.java @@ -0,0 +1,15 @@ +package seedu.address.model.person.comparator; + +import seedu.address.model.person.Person; + +/** + * A class to compare two Person objects with their Sex + */ +public class SexCompare extends PersonCompare { + + @Override + public int compare(Person p1, Person p2) { + return p1.getSex().compareTo(p2.getSex()); + } + +} diff --git a/src/main/java/seedu/address/model/person/comparator/StudentClassCompare.java b/src/main/java/seedu/address/model/person/comparator/StudentClassCompare.java new file mode 100644 index 00000000000..5dd7c74c497 --- /dev/null +++ b/src/main/java/seedu/address/model/person/comparator/StudentClassCompare.java @@ -0,0 +1,15 @@ +package seedu.address.model.person.comparator; + +import seedu.address.model.person.Person; + +/** + * A class to compare two Person objects with their StudentClass + */ +public class StudentClassCompare extends PersonCompare { + + @Override + public int compare(Person p1, Person p2) { + return p1.getStudentClass().compareTo(p2.getStudentClass()); + } + +} diff --git a/src/test/java/seedu/address/model/person/EcNumberTest.java b/src/test/java/seedu/address/model/person/EcNumberTest.java index b8cea53843b..68fb960a806 100644 --- a/src/test/java/seedu/address/model/person/EcNumberTest.java +++ b/src/test/java/seedu/address/model/person/EcNumberTest.java @@ -1,6 +1,8 @@ package seedu.address.model.person; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.testutil.Assert.assertThrows; @@ -36,6 +38,19 @@ public void isValidEcNumber() { assertTrue(EcNumber.isValidEcNumber("93121534")); // exactly 8 numbers } + @Test + public void toInt() { + EcNumber ecNumber = new EcNumber("91234567"); + + assertEquals(ecNumber.toInt(), 91234567); + assertNotEquals(ecNumber.toInt(), 98765432); + + // empty ecNumber + ecNumber = new EcNumber(""); + assertEquals(ecNumber.toInt(), Integer.MAX_VALUE); + assertNotEquals(ecNumber.toInt(), 0); + } + @Test public void equals() { EcNumber ecNumber = new EcNumber("91234567"); diff --git a/src/test/java/seedu/address/model/person/PhoneTest.java b/src/test/java/seedu/address/model/person/PhoneTest.java index deaaa5ba190..3043c38f134 100644 --- a/src/test/java/seedu/address/model/person/PhoneTest.java +++ b/src/test/java/seedu/address/model/person/PhoneTest.java @@ -1,6 +1,8 @@ package seedu.address.model.person; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.testutil.Assert.assertThrows; @@ -38,6 +40,14 @@ public void isValidPhone() { assertTrue(Phone.isValidPhone("124293842033123")); // long phone numbers } + @Test + public void toInt() { + Phone phone = new Phone("999"); + + assertEquals(phone.toInt(), 999); + assertNotEquals(phone.toInt(), 000); + } + @Test public void equals() { Phone phone = new Phone("999"); diff --git a/src/test/java/seedu/address/model/person/RegisterNumberTest.java b/src/test/java/seedu/address/model/person/RegisterNumberTest.java index b00aa2b79e5..adbd84235c0 100644 --- a/src/test/java/seedu/address/model/person/RegisterNumberTest.java +++ b/src/test/java/seedu/address/model/person/RegisterNumberTest.java @@ -1,6 +1,8 @@ package seedu.address.model.person; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.testutil.Assert.assertThrows; @@ -37,6 +39,14 @@ public void isValidRegisterNumber() { assertTrue(RegisterNumber.isValidRegisterNumber("32")); // double digit } + @Test + public void toInt() { + RegisterNumber registerNumber = new RegisterNumber("1"); + + assertEquals(registerNumber.toInt(), 1); + assertNotEquals(registerNumber.toInt(), 2); + } + @Test public void equals() { RegisterNumber registerNumber = new RegisterNumber("1"); diff --git a/src/test/java/seedu/address/model/person/comparator/AddressCompareTest.java b/src/test/java/seedu/address/model/person/comparator/AddressCompareTest.java new file mode 100644 index 00000000000..894736b66c9 --- /dev/null +++ b/src/test/java/seedu/address/model/person/comparator/AddressCompareTest.java @@ -0,0 +1,33 @@ +package seedu.address.model.person.comparator; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BOB; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.person.Person; + +public class AddressCompareTest { + + private final AddressCompare comparator = new AddressCompare(); + private final Person p1 = ALICE; + private final Person p2 = BOB; + + @Test + public void compare_equal() { + assertTrue(comparator.compare(p1, p1) == 0); + assertTrue(comparator.compare(p2, p2) == 0); + } + + @Test + public void compare_lessThan() { + assertTrue(comparator.compare(p1, p2) <= -1); + } + + @Test + public void compare_greaterThan() { + assertTrue(comparator.compare(p2, p1) >= 1); + } + +} diff --git a/src/test/java/seedu/address/model/person/comparator/EcNameCompareTest.java b/src/test/java/seedu/address/model/person/comparator/EcNameCompareTest.java new file mode 100644 index 00000000000..aae1162b471 --- /dev/null +++ b/src/test/java/seedu/address/model/person/comparator/EcNameCompareTest.java @@ -0,0 +1,33 @@ +package seedu.address.model.person.comparator; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BOB; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.person.Person; + +public class EcNameCompareTest { + + private final EcNameCompare comparator = new EcNameCompare(); + private final Person p1 = ALICE; + private final Person p2 = BOB; + + @Test + public void compare_equal() { + assertTrue(comparator.compare(p1, p1) == 0); + assertTrue(comparator.compare(p2, p2) == 0); + } + + @Test + public void compare_lessThan() { + assertTrue(comparator.compare(p1, p2) <= -1); + } + + @Test + public void compare_greaterThan() { + assertTrue(comparator.compare(p2, p1) >= 1); + } + +} diff --git a/src/test/java/seedu/address/model/person/comparator/EcNumberCompareTest.java b/src/test/java/seedu/address/model/person/comparator/EcNumberCompareTest.java new file mode 100644 index 00000000000..c162ff50567 --- /dev/null +++ b/src/test/java/seedu/address/model/person/comparator/EcNumberCompareTest.java @@ -0,0 +1,33 @@ +package seedu.address.model.person.comparator; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BOB; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.person.Person; + +public class EcNumberCompareTest { + + private final EcNumberCompare comparator = new EcNumberCompare(); + private final Person p1 = ALICE; + private final Person p2 = BOB; + + @Test + public void compare_equal() { + assertTrue(comparator.compare(p1, p1) == 0); + assertTrue(comparator.compare(p2, p2) == 0); + } + + @Test + public void compare_lessThan() { + assertTrue(comparator.compare(p1, p2) <= -1); + } + + @Test + public void compare_greaterThan() { + assertTrue(comparator.compare(p2, p1) >= 1); + } + +} diff --git a/src/test/java/seedu/address/model/person/comparator/EmailCompareTest.java b/src/test/java/seedu/address/model/person/comparator/EmailCompareTest.java new file mode 100644 index 00000000000..4bf175c17de --- /dev/null +++ b/src/test/java/seedu/address/model/person/comparator/EmailCompareTest.java @@ -0,0 +1,33 @@ +package seedu.address.model.person.comparator; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BOB; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.person.Person; + +public class EmailCompareTest { + + private final EmailCompare comparator = new EmailCompare(); + private final Person p1 = ALICE; + private final Person p2 = BOB; + + @Test + public void compare_equal() { + assertTrue(comparator.compare(p1, p1) == 0); + assertTrue(comparator.compare(p2, p2) == 0); + } + + @Test + public void compare_lessThan() { + assertTrue(comparator.compare(p1, p2) <= -1); + } + + @Test + public void compare_greaterThan() { + assertTrue(comparator.compare(p2, p1) >= 1); + } + +} diff --git a/src/test/java/seedu/address/model/person/comparator/NameCompareTest.java b/src/test/java/seedu/address/model/person/comparator/NameCompareTest.java new file mode 100644 index 00000000000..44d21083aa3 --- /dev/null +++ b/src/test/java/seedu/address/model/person/comparator/NameCompareTest.java @@ -0,0 +1,33 @@ +package seedu.address.model.person.comparator; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BOB; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.person.Person; + +public class NameCompareTest { + + private final NameCompare comparator = new NameCompare(); + private final Person p1 = ALICE; + private final Person p2 = BOB; + + @Test + public void compare_equal() { + assertTrue(comparator.compare(p1, p1) == 0); + assertTrue(comparator.compare(p2, p2) == 0); + } + + @Test + public void compare_lessThan() { + assertTrue(comparator.compare(p1, p2) <= -1); + } + + @Test + public void compare_greaterThan() { + assertTrue(comparator.compare(p2, p1) >= 1); + } + +} diff --git a/src/test/java/seedu/address/model/person/comparator/PhoneCompareTest.java b/src/test/java/seedu/address/model/person/comparator/PhoneCompareTest.java new file mode 100644 index 00000000000..305eb72eca7 --- /dev/null +++ b/src/test/java/seedu/address/model/person/comparator/PhoneCompareTest.java @@ -0,0 +1,33 @@ +package seedu.address.model.person.comparator; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BOB; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.person.Person; + +public class PhoneCompareTest { + + private final PhoneCompare comparator = new PhoneCompare(); + private final Person p1 = ALICE; + private final Person p2 = BOB; + + @Test + public void compare_equal() { + assertTrue(comparator.compare(p1, p1) == 0); + assertTrue(comparator.compare(p2, p2) == 0); + } + + @Test + public void compare_lessThan() { + assertTrue(comparator.compare(p2, p1) <= -1); + } + + @Test + public void compare_greaterThan() { + assertTrue(comparator.compare(p1, p2) >= 1); + } + +} diff --git a/src/test/java/seedu/address/model/person/comparator/RegisterNumberCompareTest.java b/src/test/java/seedu/address/model/person/comparator/RegisterNumberCompareTest.java new file mode 100644 index 00000000000..fb861b5b5e5 --- /dev/null +++ b/src/test/java/seedu/address/model/person/comparator/RegisterNumberCompareTest.java @@ -0,0 +1,33 @@ +package seedu.address.model.person.comparator; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BOB; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.person.Person; + +public class RegisterNumberCompareTest { + + private final RegisterNumberCompare comparator = new RegisterNumberCompare(); + private final Person p1 = ALICE; + private final Person p2 = BOB; + + @Test + public void compare_equal() { + assertTrue(comparator.compare(p1, p1) == 0); + assertTrue(comparator.compare(p2, p2) == 0); + } + + @Test + public void compare_lessThan() { + assertTrue(comparator.compare(p2, p1) <= -1); + } + + @Test + public void compare_greaterThan() { + assertTrue(comparator.compare(p1, p2) >= 1); + } + +} diff --git a/src/test/java/seedu/address/model/person/comparator/SexCompareTest.java b/src/test/java/seedu/address/model/person/comparator/SexCompareTest.java new file mode 100644 index 00000000000..6a595efc699 --- /dev/null +++ b/src/test/java/seedu/address/model/person/comparator/SexCompareTest.java @@ -0,0 +1,33 @@ +package seedu.address.model.person.comparator; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BOB; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.person.Person; + +public class SexCompareTest { + + private final SexCompare comparator = new SexCompare(); + private final Person p1 = ALICE; + private final Person p2 = BOB; + + @Test + public void compare_equal() { + assertTrue(comparator.compare(p1, p1) == 0); + assertTrue(comparator.compare(p2, p2) == 0); + } + + @Test + public void compare_lessThan() { + assertTrue(comparator.compare(p1, p2) <= -1); + } + + @Test + public void compare_greaterThan() { + assertTrue(comparator.compare(p2, p1) >= 1); + } + +} diff --git a/src/test/java/seedu/address/model/person/comparator/StudentClassCompareTest.java b/src/test/java/seedu/address/model/person/comparator/StudentClassCompareTest.java new file mode 100644 index 00000000000..ca234275077 --- /dev/null +++ b/src/test/java/seedu/address/model/person/comparator/StudentClassCompareTest.java @@ -0,0 +1,33 @@ +package seedu.address.model.person.comparator; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BOB; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.person.Person; + +public class StudentClassCompareTest { + + private final StudentClassCompare comparator = new StudentClassCompare(); + private final Person p1 = ALICE; + private final Person p2 = BOB; + + @Test + public void compare_equal() { + assertTrue(comparator.compare(p1, p1) == 0); + assertTrue(comparator.compare(p2, p2) == 0); + } + + @Test + public void compare_lessThan() { + assertTrue(comparator.compare(p1, p2) <= -1); + } + + @Test + public void compare_greaterThan() { + assertTrue(comparator.compare(p2, p1) >= 1); + } + +} From 7d9e3021e5f87741ebbe9ebf7b19ace91bb46c76 Mon Sep 17 00:00:00 2001 From: BunnyHoppp Date: Thu, 24 Oct 2024 03:56:02 +0800 Subject: [PATCH 2/8] Add sorting functionality Allow users to sort by any attribute that the person has. --- .../address/logic/commands/SortCommand.java | 106 ++++++++++++++++++ .../logic/parser/AddressBookParser.java | 4 + .../address/logic/parser/ParserUtil.java | 47 ++++++++ .../logic/parser/SortCommandParser.java | 32 ++++++ src/main/java/seedu/address/model/Model.java | 7 ++ .../seedu/address/model/ModelManager.java | 14 ++- .../seedu/address/model/person/Address.java | 7 +- .../java/seedu/address/model/person/Name.java | 6 +- .../address/testutil/TypicalPersons.java | 7 +- 9 files changed, 225 insertions(+), 5 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/SortCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/SortCommandParser.java diff --git a/src/main/java/seedu/address/logic/commands/SortCommand.java b/src/main/java/seedu/address/logic/commands/SortCommand.java new file mode 100644 index 00000000000..a4bd000999b --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/SortCommand.java @@ -0,0 +1,106 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import java.util.Comparator; + +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.parser.ParserUtil.SortAttribute; +import seedu.address.model.Model; +import seedu.address.model.person.Person; +import seedu.address.model.person.comparator.AddressCompare; +import seedu.address.model.person.comparator.EcNameCompare; +import seedu.address.model.person.comparator.EcNumberCompare; +import seedu.address.model.person.comparator.EmailCompare; +import seedu.address.model.person.comparator.NameCompare; +import seedu.address.model.person.comparator.PhoneCompare; +import seedu.address.model.person.comparator.RegisterNumberCompare; +import seedu.address.model.person.comparator.SexCompare; +import seedu.address.model.person.comparator.StudentClassCompare; + +/** + * Sorts the list of contacts based on the attribute + */ +public class SortCommand extends Command { + + public static final String COMMAND_WORD = "sort"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Sorts the list based on the attribute\n" + + "Attributes: name, phone, email, address, register number, sex, \n" + + "student class, emergency contact name, emergency contact number"; + + public static final String MESSAGE_SUCCESS = "Sorted the list based on %1$s"; + public static final String MESSAGE_SORT_ATTRIBUTE_NOT_SPECIFIED = "The sort attribute is not specified!"; + private final SortAttribute sortAttribute; + + /** + * @param sortAttribute attribute to sort the persons in the list + */ + public SortCommand(SortAttribute sortAttribute) { + requireNonNull(sortAttribute); + this.sortAttribute = sortAttribute; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + Comparator comparator = this.getComparator(); + model.sortFilteredPersonList(comparator); + return new CommandResult(String.format(MESSAGE_SUCCESS, this.sortAttribute)); + } + + + /** + * Retrieves the comparator needed to sort the list. + * @throws CommandException if the comparator cannot be found. + */ + public Comparator getComparator() throws CommandException { + + switch (sortAttribute) { + + case NAME: + return new NameCompare(); + + case PHONE: + return new PhoneCompare(); + + case EMAIL: + return new EmailCompare(); + + case ADDRESS: + return new AddressCompare(); + + case REGISTERNUMBER: + return new RegisterNumberCompare(); + + case SEX: + return new SexCompare(); + + case STUDENTCLASS: + return new StudentClassCompare(); + + case EMERGENCYCONTACTNAME: + return new EcNameCompare(); + + case EMERGENCYCONTACTNUMBER: + return new EcNumberCompare(); + + default: + throw new CommandException(MESSAGE_SORT_ATTRIBUTE_NOT_SPECIFIED); + } + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof SortCommand)) { + return false; + } + + SortCommand s = (SortCommand) other; + return sortAttribute.equals(s.sortAttribute); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 95d2000b67a..e590c331246 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -19,6 +19,7 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.SortCommand; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -85,6 +86,9 @@ public Command parseCommand(String userInput) throws ParseException { case AddEcNumberCommand.COMMAND_WORD: return new AddEcNumberCommandParser().parse(arguments); + case SortCommand.COMMAND_WORD: + return new SortCommandParser().parse(arguments); + default: logger.finer("This user input caused a ParseException: " + userInput); throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index debaa6df955..7c6b24fdb13 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -201,4 +201,51 @@ public static Set parseTags(Collection tags) throws ParseException } return tagSet; } + + /** + * Parse {@code String attribute} into a {@code SortAttribute}. + * All whitespaces will be trimmed + * + * @throws ParseException if the given {@code SortAttribute} is invalid. + */ + public static SortAttribute parseSortAttribute(String attribute) throws ParseException { + requireNonNull(attribute); + String trimmedAttribute = attribute.replaceAll("\\s+", ""); + String upperCaseAttribute = trimmedAttribute.toUpperCase(); + SortAttribute sortAttribute; + try { + sortAttribute = SortAttribute.valueOf(upperCaseAttribute); + } catch (IllegalArgumentException e) { + throw new ParseException(SortAttribute.MESSAGE_CONSTRAINTS); + } + return sortAttribute; + } + + /** + * Enum to encapsulate all the possible attributes to sort the list by. + */ + public enum SortAttribute { + NAME("name"), + PHONE("phone"), + EMAIL("email"), + ADDRESS("address"), + REGISTERNUMBER("register number"), + SEX("sex"), + STUDENTCLASS("student class"), + EMERGENCYCONTACTNAME("emergency contact name"), + EMERGENCYCONTACTNUMBER("emergency contact number"), + NOTATTRIBUTE(""); + + public static final String MESSAGE_CONSTRAINTS = "Sorting Attribute is invalid"; + + private final String attribute; + SortAttribute(String attribute) { + this.attribute = attribute; + } + + @Override + public String toString() { + return this.attribute; + } + } } diff --git a/src/main/java/seedu/address/logic/parser/SortCommandParser.java b/src/main/java/seedu/address/logic/parser/SortCommandParser.java new file mode 100644 index 00000000000..7345b635885 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/SortCommandParser.java @@ -0,0 +1,32 @@ +package seedu.address.logic.parser; + +import static java.util.Objects.requireNonNull; +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.logic.commands.SortCommand; +import seedu.address.logic.parser.ParserUtil.SortAttribute; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new SortCommand object + */ +public class SortCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the SortCommand + * and returns a SortCommand object for execution. + * @throws ParseException if the user input does not conform the expected format. + */ + public SortCommand parse(String args) throws ParseException { + requireNonNull(args); + SortAttribute sortAttribute; + try { + sortAttribute = ParserUtil.parseSortAttribute(args); + } catch (IllegalValueException ive) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + SortCommand.MESSAGE_USAGE), ive); + } + return new SortCommand(sortAttribute); + } +} diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index d54df471c1f..4a786a9ccaa 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -1,6 +1,7 @@ package seedu.address.model; import java.nio.file.Path; +import java.util.Comparator; import java.util.function.Predicate; import javafx.collections.ObservableList; @@ -84,4 +85,10 @@ public interface Model { * @throws NullPointerException if {@code predicate} is null. */ void updateFilteredPersonList(Predicate predicate); + + /** + * Sorts the filteredPersonList using the comparator. + * @param comparator to sort the list. + */ + void sortFilteredPersonList(Comparator comparator); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 57bc563fde6..83c8e7c09bf 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -4,11 +4,13 @@ import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.nio.file.Path; +import java.util.Comparator; import java.util.function.Predicate; import java.util.logging.Logger; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; +import javafx.collections.transformation.SortedList; import seedu.address.commons.core.GuiSettings; import seedu.address.commons.core.LogsCenter; import seedu.address.model.person.Person; @@ -22,6 +24,9 @@ public class ModelManager implements Model { private final AddressBook addressBook; private final UserPrefs userPrefs; private final FilteredList filteredPersons; + private final SortedList sortedPersons; + + private ObservableList personList; /** * Initializes a ModelManager with the given addressBook and userPrefs. @@ -34,6 +39,7 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs this.addressBook = new AddressBook(addressBook); this.userPrefs = new UserPrefs(userPrefs); filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); + sortedPersons = new SortedList<>(filteredPersons); } public ModelManager() { @@ -119,7 +125,7 @@ public void setPerson(Person target, Person editedPerson) { */ @Override public ObservableList getFilteredPersonList() { - return filteredPersons; + return sortedPersons; } @Override @@ -128,6 +134,12 @@ public void updateFilteredPersonList(Predicate predicate) { filteredPersons.setPredicate(predicate); } + @Override + public void sortFilteredPersonList(Comparator comparator) { + requireNonNull(comparator); + sortedPersons.setComparator(comparator); + } + @Override public boolean equals(Object other) { if (other == this) { diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/person/Address.java index df802a90597..e8c465d8129 100644 --- a/src/main/java/seedu/address/model/person/Address.java +++ b/src/main/java/seedu/address/model/person/Address.java @@ -7,7 +7,7 @@ * Represents a Person's address in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)} */ -public class Address { +public class Address implements Comparable
{ public static final String MESSAGE_CONSTRAINTS = "Addresses can take any values, and it should not be blank"; @@ -62,4 +62,9 @@ public int hashCode() { return value.hashCode(); } + @Override + public int compareTo(Address a) { + return this.toString().compareTo(a.toString()); + } + } diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/person/Name.java index 173f15b9b00..2b5ce8854f0 100644 --- a/src/main/java/seedu/address/model/person/Name.java +++ b/src/main/java/seedu/address/model/person/Name.java @@ -7,7 +7,7 @@ * Represents a Person's name in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidName(String)} */ -public class Name { +public class Name implements Comparable { public static final String MESSAGE_CONSTRAINTS = "Names should only contain alphanumeric characters and spaces, and it should not be blank"; @@ -64,4 +64,8 @@ public int hashCode() { return fullName.hashCode(); } + @Override + public int compareTo(Name name) { + return this.toString().compareTo(name.toString()); + } } diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index f91aaffa54c..a9609c9fad3 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -4,6 +4,8 @@ import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_ECNAME_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_ECNAME_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_ECNUMBER_AMY; +import static seedu.address.logic.commands.CommandTestUtil.VALID_ECNUMBER_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY; @@ -70,11 +72,12 @@ public class TypicalPersons { public static final Person AMY = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY) .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withRegisterNumber(VALID_REGISTER_NUMBER_AMY) .withSex(VALID_SEX_AMY).withStudentClass(VALID_STUDENT_CLASS_AMY) - .withEcName(VALID_ECNAME_AMY).withTags(VALID_TAG_FRIEND).build(); + .withEcName(VALID_ECNAME_AMY).withEcNumber(VALID_ECNUMBER_AMY).withTags(VALID_TAG_FRIEND).build(); public static final Person BOB = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withRegisterNumber(VALID_REGISTER_NUMBER_BOB) .withSex(VALID_SEX_BOB).withStudentClass(VALID_STUDENT_CLASS_BOB) - .withEcName(VALID_ECNAME_BOB).withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build(); + .withEcName(VALID_ECNAME_BOB).withEcNumber(VALID_ECNUMBER_BOB) + .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build(); public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER From 9b9351d32da5ae9fe179c8814c8bbd19d5b11830 Mon Sep 17 00:00:00 2001 From: BunnyHoppp Date: Thu, 24 Oct 2024 03:56:40 +0800 Subject: [PATCH 3/8] Add unit tests for the changes Test code written for SortCommand --- .../logic/commands/AddCommandTest.java | 6 + .../logic/commands/SortCommandTest.java | 155 ++++++++++++++++++ .../logic/parser/AddressBookParserTest.java | 9 + .../address/logic/parser/ParserUtilTest.java | 44 +++-- .../logic/parser/SortCommandParserTest.java | 34 ++++ 5 files changed, 238 insertions(+), 10 deletions(-) create mode 100644 src/test/java/seedu/address/logic/commands/SortCommandTest.java create mode 100644 src/test/java/seedu/address/logic/parser/SortCommandParserTest.java diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 90e8253f48e..3a1e05f8274 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -10,6 +10,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.function.Predicate; import org.junit.jupiter.api.Test; @@ -157,6 +158,11 @@ public ObservableList getFilteredPersonList() { public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + + @Override + public void sortFilteredPersonList(Comparator comparator) { + throw new AssertionError("This method should not be called"); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/SortCommandTest.java b/src/test/java/seedu/address/logic/commands/SortCommandTest.java new file mode 100644 index 00000000000..d6a1399ef5b --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/SortCommandTest.java @@ -0,0 +1,155 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; + +import java.util.Comparator; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.parser.ParserUtil; +import seedu.address.model.AddressBook; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.person.Person; +import seedu.address.model.person.comparator.AddressCompare; +import seedu.address.model.person.comparator.EcNameCompare; +import seedu.address.model.person.comparator.EcNumberCompare; +import seedu.address.model.person.comparator.EmailCompare; +import seedu.address.model.person.comparator.NameCompare; +import seedu.address.model.person.comparator.PhoneCompare; +import seedu.address.model.person.comparator.RegisterNumberCompare; +import seedu.address.model.person.comparator.SexCompare; +import seedu.address.model.person.comparator.StudentClassCompare; + +/** + * Contains integration tests (interaction with the Model) and unit tests for SortCommand. + */ +public class SortCommandTest { + + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void execute_validSortAttribute_success() { + + Comparator comparator; + SortCommand command; + Model expectedModel; + String expectedMessage; + ParserUtil.SortAttribute sortAttribute; + + // compare name + sortAttribute = ParserUtil.SortAttribute.NAME; + command = new SortCommand(sortAttribute); + comparator = new NameCompare(); + expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + + // compare phone + sortAttribute = ParserUtil.SortAttribute.PHONE; + command = new SortCommand(sortAttribute); + comparator = new PhoneCompare(); + expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + + // compare address + sortAttribute = ParserUtil.SortAttribute.ADDRESS; + command = new SortCommand(sortAttribute); + comparator = new AddressCompare(); + expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + + // compare EcName + sortAttribute = ParserUtil.SortAttribute.EMERGENCYCONTACTNAME; + command = new SortCommand(sortAttribute); + comparator = new EcNameCompare(); + expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + + // compare EcNumber + sortAttribute = ParserUtil.SortAttribute.EMERGENCYCONTACTNUMBER; + command = new SortCommand(sortAttribute); + comparator = new EcNumberCompare(); + expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + + // compare email + sortAttribute = ParserUtil.SortAttribute.EMAIL; + command = new SortCommand(sortAttribute); + comparator = new EmailCompare(); + expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + + // compare register number + sortAttribute = ParserUtil.SortAttribute.REGISTERNUMBER; + command = new SortCommand(sortAttribute); + comparator = new RegisterNumberCompare(); + expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + + // compare sex + sortAttribute = ParserUtil.SortAttribute.SEX; + command = new SortCommand(sortAttribute); + comparator = new SexCompare(); + expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + + // compare student class + sortAttribute = ParserUtil.SortAttribute.STUDENTCLASS; + command = new SortCommand(sortAttribute); + comparator = new StudentClassCompare(); + expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + + } + + @Test + public void execute_invalidSortAttribute_failure() { + ParserUtil.SortAttribute sortAttribute = ParserUtil.SortAttribute.NOTATTRIBUTE; + SortCommand command = new SortCommand(sortAttribute); + assertCommandFailure(command, model, SortCommand.MESSAGE_SORT_ATTRIBUTE_NOT_SPECIFIED); + } + + @Test + public void equals() { + final SortCommand standardCommand = new SortCommand(ParserUtil.SortAttribute.NAME); + + // same values -> returns true + SortCommand commandWithSameValues = new SortCommand(ParserUtil.SortAttribute.NAME); + assertTrue(standardCommand.equals(commandWithSameValues)); + + // same object -> returns true + assertTrue(standardCommand.equals(standardCommand)); + + // null -> returns false + assertFalse(standardCommand.equals(null)); + + // different types -> returns false + assertFalse(standardCommand.equals(new ClearCommand())); + + // different SortAttribute -> returns false + assertFalse(standardCommand.equals(new SortCommand(ParserUtil.SortAttribute.PHONE))); + } +} diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 8d0e1187d40..daafc22b840 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -26,6 +26,7 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.SortCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.EcName; import seedu.address.model.person.EcNumber; @@ -126,6 +127,14 @@ public void parseCommand_addEcNumber() throws Exception { assertEquals(expected, command); } + @Test + public void parseCommand_sort() throws Exception { + SortCommand expected = new SortCommand(ParserUtil.SortAttribute.REGISTERNUMBER); + SortCommand command = (SortCommand) parser.parseCommand( + SortCommand.COMMAND_WORD + " register number"); + assertEquals(expected, command); + } + @Test public void parseCommand_unrecognisedInput_throwsParseException() { assertThrows(ParseException.class, String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE), () diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java index 7c05d6b337e..53e3f5e1031 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java @@ -34,8 +34,9 @@ public class ParserUtilTest { private static final String INVALID_SEX = "H"; private static final String INVALID_STUDENT_CLASS = "A1"; private static final String INVALID_EMERGENCY_CONTACT_NAME = "--"; - private static final String INVALID_EMERGENCY_PHONE = "1234"; + private static final String INVALID_EMERGENCY_CONTACT_NUMBER = "1234"; private static final String INVALID_TAG = "#friend"; + private static final String INVALID_SORT_ATTRIBUTE = "names"; private static final String VALID_NAME = "Rachel Walker"; private static final String VALID_PHONE = "123456"; @@ -45,9 +46,10 @@ public class ParserUtilTest { private static final String VALID_SEX = "F"; private static final String VALID_STUDENT_CLASS = "1A"; private static final String VALID_EMERGENCY_CONTACT_NAME = "Joe Walker"; - private static final String VALID_EMERGENCY_PHONE = "91234567"; + private static final String VALID_EMERGENCY_CONTACT_NUMBER = "91234567"; private static final String VALID_TAG_1 = "friend"; private static final String VALID_TAG_2 = "neighbour"; + private static final String VALID_SORT_ATTRIBUTE = "register number"; private static final String WHITESPACE = " \t\r\n"; @@ -262,21 +264,20 @@ public void parseEcNumber_null_throwsNullPointerException() { @Test public void parseEcNumber_invalidValue_throwsParseException() { - assertThrows(ParseException.class, () -> ParserUtil.parseEcNumber(INVALID_EMERGENCY_PHONE)); + assertThrows(ParseException.class, () -> ParserUtil.parseEcNumber(INVALID_EMERGENCY_CONTACT_NUMBER)); } @Test - public void parseEcNumber_validValueWithoutWhitespace_returnsStudentClass() throws Exception { - EcNumber expectedEcNumber = new EcNumber(VALID_EMERGENCY_PHONE); - assertEquals(expectedEcNumber, ParserUtil.parseEcNumber(VALID_EMERGENCY_PHONE)); + public void parseEcNumber_validValueWithoutWhitespace_returnsEcNumber() throws Exception { + EcNumber expectedEcNumber = new EcNumber(VALID_EMERGENCY_CONTACT_NUMBER); + assertEquals(expectedEcNumber, ParserUtil.parseEcNumber(VALID_EMERGENCY_CONTACT_NUMBER)); } @Test - public void parseEcNumber_validValueWithWhitespace_returnsTrimmedStudentClass() throws Exception { - String ecNumberWithWhitespace = WHITESPACE + VALID_EMERGENCY_PHONE + WHITESPACE; - EcNumber expectedEcNumber = new EcNumber(VALID_EMERGENCY_PHONE); + public void parseEcNumber_validValueWithWhitespace_returnsTrimmedEcNumber() throws Exception { + String ecNumberWithWhitespace = WHITESPACE + VALID_EMERGENCY_CONTACT_NUMBER + WHITESPACE; + EcNumber expectedEcNumber = new EcNumber(VALID_EMERGENCY_CONTACT_NUMBER); assertEquals(expectedEcNumber, ParserUtil.parseEcNumber(ecNumberWithWhitespace)); - } @Test @@ -324,4 +325,27 @@ public void parseTags_collectionWithValidTags_returnsTagSet() throws Exception { assertEquals(expectedTagSet, actualTagSet); } + + @Test + public void parseSortAttribute_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> ParserUtil.parseSortAttribute((String) null)); + } + + @Test + public void parseSortAttribute_invalidValue_throwsParseException() { + assertThrows(ParseException.class, () -> ParserUtil.parseSortAttribute(INVALID_SORT_ATTRIBUTE)); + } + + @Test + public void parseSortAttribute_validValueWithoutWhitespace_returnsSortAttribute() throws Exception { + ParserUtil.SortAttribute expectedSortAttribute = ParserUtil.SortAttribute.REGISTERNUMBER; + assertEquals(expectedSortAttribute, ParserUtil.parseSortAttribute(VALID_SORT_ATTRIBUTE)); + } + + @Test + public void parseSortAttribute_validValueWithWhitespace_returnsTrimmedSortAttribute() throws Exception { + String sortAttributeWithWhiteSpace = WHITESPACE + VALID_SORT_ATTRIBUTE + WHITESPACE; + ParserUtil.SortAttribute expectedSortAttribute = ParserUtil.SortAttribute.REGISTERNUMBER; + assertEquals(expectedSortAttribute, ParserUtil.parseSortAttribute(sortAttributeWithWhiteSpace)); + } } diff --git a/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java b/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java new file mode 100644 index 00000000000..a5b894cf0e0 --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java @@ -0,0 +1,34 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.commands.SortCommand; + +public class SortCommandParserTest { + + private static final String MESSAGE_INVALID_FORMAT = + String.format(MESSAGE_INVALID_COMMAND_FORMAT, SortCommand.MESSAGE_USAGE); + + private SortCommandParser parser = new SortCommandParser(); + + @Test + public void parse_emptyArg_throwsParseException() { + assertParseFailure(parser, " ", MESSAGE_INVALID_FORMAT); + } + + @Test + public void parse_validArgs_returnsSortCommand() { + SortCommand expectedSortCommand = new SortCommand(ParserUtil.SortAttribute.REGISTERNUMBER); + + // multiple white spaces + assertParseSuccess(parser, " register number ", expectedSortCommand); + + // no white spaces + expectedSortCommand = new SortCommand(ParserUtil.SortAttribute.ADDRESS); + assertParseSuccess(parser, "address", expectedSortCommand); + } +} From b74ada8330a6c08b95a90cb4d4f73013657590db Mon Sep 17 00:00:00 2001 From: BunnyHoppp Date: Thu, 24 Oct 2024 04:02:44 +0800 Subject: [PATCH 4/8] Update User Guide Users will know how to use the sort command --- docs/UserGuide.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index ee8d2e6f223..241a4f0033d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -183,6 +183,23 @@ Examples: * `addEcNumber 1 ep/91234567` to add the emergency contact's number 91234567 to the 1st person in the list. * `addEcNumber 2 ep/` to delete the emergency contact's number from the 2nd person in the list. +### Sorting the list : `sort` + +Sorts the list of students based on the students attributes. + +Format: `sort [ATTRIBUTE]` + + + +**Tip:** Students attributes include: name, phone, email, address, sex, register number, student class, emergency contact name, emergency contact number. + + +* Sorts the list based on the ATTRIBUTE + +Examples: +* `sort name` to sort the list based on student's names +* `sort register number` to sort the list based on student's register numbers + ### Clearing all entries : `clear` Clears all entries from the address book. @@ -241,4 +258,5 @@ Action | Format, Examples **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` **List** | `list` **Help** | `help` -**Add Emergency Phone Number** | `EcNumber INDEX [ep/EMERGENCY_PHONE_NUMBER]`
e.g., `EcNumber 2 ep/91231234` +**Add Emergency Phone Number** | `addEcNumber INDEX [ep/EMERGENCY_PHONE_NUMBER]`
e.g., `addEcNumber 2 ep/91231234` +**Sort** | `sort [ATTRIBUTE]`
e.g., `sort student class` From 6dad1f45b8314e44e16816e38a718e64ecf2ee0a Mon Sep 17 00:00:00 2001 From: BunnyHoppp Date: Thu, 24 Oct 2024 04:41:57 +0800 Subject: [PATCH 5/8] Add unsort feature Allow users to see the original list Users have the flexibility to change the sorting --- docs/UserGuide.md | 2 ++ .../address/logic/commands/SortCommand.java | 25 ++++++++------ .../address/logic/parser/ParserUtil.java | 2 +- .../seedu/address/model/ModelManager.java | 11 +++---- .../seedu/address/model/person/EcNumber.java | 1 + .../model/person/comparator/NameCompare.java | 2 +- .../model/person/comparator/PhoneCompare.java | 3 +- .../logic/commands/SortCommandTest.java | 33 +++++++++---------- .../logic/parser/SortCommandParserTest.java | 4 +++ 9 files changed, 46 insertions(+), 37 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 356d1029eb3..872f28e6bca 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -226,10 +226,12 @@ Format: `sort [ATTRIBUTE]` * Sorts the list based on the ATTRIBUTE +* Unsort the list when the attribute is `none` Examples: * `sort name` to sort the list based on student's names * `sort register number` to sort the list based on student's register numbers +* `sort none` to unsort the list ### Clearing all entries : `clear` diff --git a/src/main/java/seedu/address/logic/commands/SortCommand.java b/src/main/java/seedu/address/logic/commands/SortCommand.java index a4bd000999b..f82a0d63f88 100644 --- a/src/main/java/seedu/address/logic/commands/SortCommand.java +++ b/src/main/java/seedu/address/logic/commands/SortCommand.java @@ -1,10 +1,10 @@ package seedu.address.logic.commands; +import static java.util.Objects.isNull; import static java.util.Objects.requireNonNull; import java.util.Comparator; -import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.logic.parser.ParserUtil.SortAttribute; import seedu.address.model.Model; import seedu.address.model.person.Person; @@ -29,9 +29,11 @@ public class SortCommand extends Command { + "Attributes: name, phone, email, address, register number, sex, \n" + "student class, emergency contact name, emergency contact number"; - public static final String MESSAGE_SUCCESS = "Sorted the list based on %1$s"; - public static final String MESSAGE_SORT_ATTRIBUTE_NOT_SPECIFIED = "The sort attribute is not specified!"; + public static final String MESSAGE_SORTED_SUCCESS = "Sorted the list based on %1$s"; + public static final String MESSAGE_UNSORTED_SUCCESS = "Your list is now unsorted and back to the original!"; + private final SortAttribute sortAttribute; + private Comparator comparator; /** * @param sortAttribute attribute to sort the persons in the list @@ -42,19 +44,22 @@ public SortCommand(SortAttribute sortAttribute) { } @Override - public CommandResult execute(Model model) throws CommandException { + public CommandResult execute(Model model) { requireNonNull(model); - Comparator comparator = this.getComparator(); - model.sortFilteredPersonList(comparator); - return new CommandResult(String.format(MESSAGE_SUCCESS, this.sortAttribute)); + this.comparator = this.getComparator(); + model.sortFilteredPersonList(this.comparator); + return new CommandResult(this.generateSuccessMessage()); } + public String generateSuccessMessage() { + return isNull(comparator) ? MESSAGE_UNSORTED_SUCCESS : String.format(MESSAGE_SORTED_SUCCESS, sortAttribute); + } /** * Retrieves the comparator needed to sort the list. - * @throws CommandException if the comparator cannot be found. + * Returns null to unsort. */ - public Comparator getComparator() throws CommandException { + public Comparator getComparator() { switch (sortAttribute) { @@ -86,7 +91,7 @@ public Comparator getComparator() throws CommandException { return new EcNumberCompare(); default: - throw new CommandException(MESSAGE_SORT_ATTRIBUTE_NOT_SPECIFIED); + return null; } } diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 012e2bfa3f0..31d0e790dfb 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -265,7 +265,7 @@ public enum SortAttribute { STUDENTCLASS("student class"), EMERGENCYCONTACTNAME("emergency contact name"), EMERGENCYCONTACTNUMBER("emergency contact number"), - NOTATTRIBUTE(""); + NONE("none"); public static final String MESSAGE_CONSTRAINTS = "Sorting Attribute is invalid"; diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 83c8e7c09bf..5064a1146ae 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -24,9 +24,7 @@ public class ModelManager implements Model { private final AddressBook addressBook; private final UserPrefs userPrefs; private final FilteredList filteredPersons; - private final SortedList sortedPersons; - - private ObservableList personList; + private final SortedList sortedAndFilteredPersons; /** * Initializes a ModelManager with the given addressBook and userPrefs. @@ -39,7 +37,7 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs this.addressBook = new AddressBook(addressBook); this.userPrefs = new UserPrefs(userPrefs); filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); - sortedPersons = new SortedList<>(filteredPersons); + sortedAndFilteredPersons = new SortedList<>(filteredPersons); } public ModelManager() { @@ -125,7 +123,7 @@ public void setPerson(Person target, Person editedPerson) { */ @Override public ObservableList getFilteredPersonList() { - return sortedPersons; + return sortedAndFilteredPersons; } @Override @@ -136,8 +134,7 @@ public void updateFilteredPersonList(Predicate predicate) { @Override public void sortFilteredPersonList(Comparator comparator) { - requireNonNull(comparator); - sortedPersons.setComparator(comparator); + sortedAndFilteredPersons.setComparator(comparator); } @Override diff --git a/src/main/java/seedu/address/model/person/EcNumber.java b/src/main/java/seedu/address/model/person/EcNumber.java index 5a199c88933..a5be0bcdd62 100644 --- a/src/main/java/seedu/address/model/person/EcNumber.java +++ b/src/main/java/seedu/address/model/person/EcNumber.java @@ -38,6 +38,7 @@ public static boolean isValidEcNumber(String number) { */ public Integer toInt() { if (value.isEmpty()) { + // max value when empty so that it goes to the bottom when sorted return Integer.MAX_VALUE; } return Integer.valueOf(this.value); diff --git a/src/main/java/seedu/address/model/person/comparator/NameCompare.java b/src/main/java/seedu/address/model/person/comparator/NameCompare.java index d6020106964..41496242717 100644 --- a/src/main/java/seedu/address/model/person/comparator/NameCompare.java +++ b/src/main/java/seedu/address/model/person/comparator/NameCompare.java @@ -3,7 +3,7 @@ import seedu.address.model.person.Person; /** - * A class to compare two Person objects based on name + * A class to compare two Person objects based on Name */ public class NameCompare extends PersonCompare { diff --git a/src/main/java/seedu/address/model/person/comparator/PhoneCompare.java b/src/main/java/seedu/address/model/person/comparator/PhoneCompare.java index 4d14f2a1b1b..7bb09a476d8 100644 --- a/src/main/java/seedu/address/model/person/comparator/PhoneCompare.java +++ b/src/main/java/seedu/address/model/person/comparator/PhoneCompare.java @@ -3,11 +3,12 @@ import seedu.address.model.person.Person; /** - * A class to compare two Person objects based on their phone number + * A class to compare two Person objects based on their Phone */ public class PhoneCompare extends PersonCompare { @Override public int compare(Person p1, Person p2) { return p1.getPhone().compareTo(p2.getPhone()); } + } diff --git a/src/test/java/seedu/address/logic/commands/SortCommandTest.java b/src/test/java/seedu/address/logic/commands/SortCommandTest.java index d6a1399ef5b..056ca63e196 100644 --- a/src/test/java/seedu/address/logic/commands/SortCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/SortCommandTest.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; @@ -35,7 +34,6 @@ public class SortCommandTest { @Test public void execute_validSortAttribute_success() { - Comparator comparator; SortCommand command; Model expectedModel; @@ -46,7 +44,7 @@ public void execute_validSortAttribute_success() { sortAttribute = ParserUtil.SortAttribute.NAME; command = new SortCommand(sortAttribute); comparator = new NameCompare(); - expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedMessage = String.format(SortCommand.MESSAGE_SORTED_SUCCESS, sortAttribute); expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); expectedModel.sortFilteredPersonList(comparator); assertCommandSuccess(command, model, expectedMessage, expectedModel); @@ -55,7 +53,7 @@ public void execute_validSortAttribute_success() { sortAttribute = ParserUtil.SortAttribute.PHONE; command = new SortCommand(sortAttribute); comparator = new PhoneCompare(); - expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedMessage = String.format(SortCommand.MESSAGE_SORTED_SUCCESS, sortAttribute); expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); expectedModel.sortFilteredPersonList(comparator); assertCommandSuccess(command, model, expectedMessage, expectedModel); @@ -64,7 +62,7 @@ public void execute_validSortAttribute_success() { sortAttribute = ParserUtil.SortAttribute.ADDRESS; command = new SortCommand(sortAttribute); comparator = new AddressCompare(); - expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedMessage = String.format(SortCommand.MESSAGE_SORTED_SUCCESS, sortAttribute); expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); expectedModel.sortFilteredPersonList(comparator); assertCommandSuccess(command, model, expectedMessage, expectedModel); @@ -73,7 +71,7 @@ public void execute_validSortAttribute_success() { sortAttribute = ParserUtil.SortAttribute.EMERGENCYCONTACTNAME; command = new SortCommand(sortAttribute); comparator = new EcNameCompare(); - expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedMessage = String.format(SortCommand.MESSAGE_SORTED_SUCCESS, sortAttribute); expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); expectedModel.sortFilteredPersonList(comparator); assertCommandSuccess(command, model, expectedMessage, expectedModel); @@ -82,7 +80,7 @@ public void execute_validSortAttribute_success() { sortAttribute = ParserUtil.SortAttribute.EMERGENCYCONTACTNUMBER; command = new SortCommand(sortAttribute); comparator = new EcNumberCompare(); - expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedMessage = String.format(SortCommand.MESSAGE_SORTED_SUCCESS, sortAttribute); expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); expectedModel.sortFilteredPersonList(comparator); assertCommandSuccess(command, model, expectedMessage, expectedModel); @@ -91,7 +89,7 @@ public void execute_validSortAttribute_success() { sortAttribute = ParserUtil.SortAttribute.EMAIL; command = new SortCommand(sortAttribute); comparator = new EmailCompare(); - expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedMessage = String.format(SortCommand.MESSAGE_SORTED_SUCCESS, sortAttribute); expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); expectedModel.sortFilteredPersonList(comparator); assertCommandSuccess(command, model, expectedMessage, expectedModel); @@ -100,7 +98,7 @@ public void execute_validSortAttribute_success() { sortAttribute = ParserUtil.SortAttribute.REGISTERNUMBER; command = new SortCommand(sortAttribute); comparator = new RegisterNumberCompare(); - expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedMessage = String.format(SortCommand.MESSAGE_SORTED_SUCCESS, sortAttribute); expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); expectedModel.sortFilteredPersonList(comparator); assertCommandSuccess(command, model, expectedMessage, expectedModel); @@ -109,7 +107,7 @@ public void execute_validSortAttribute_success() { sortAttribute = ParserUtil.SortAttribute.SEX; command = new SortCommand(sortAttribute); comparator = new SexCompare(); - expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedMessage = String.format(SortCommand.MESSAGE_SORTED_SUCCESS, sortAttribute); expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); expectedModel.sortFilteredPersonList(comparator); assertCommandSuccess(command, model, expectedMessage, expectedModel); @@ -118,19 +116,20 @@ public void execute_validSortAttribute_success() { sortAttribute = ParserUtil.SortAttribute.STUDENTCLASS; command = new SortCommand(sortAttribute); comparator = new StudentClassCompare(); - expectedMessage = String.format(SortCommand.MESSAGE_SUCCESS, sortAttribute); + expectedMessage = String.format(SortCommand.MESSAGE_SORTED_SUCCESS, sortAttribute); expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); expectedModel.sortFilteredPersonList(comparator); assertCommandSuccess(command, model, expectedMessage, expectedModel); + // unsorting success + sortAttribute = ParserUtil.SortAttribute.NONE; + command = new SortCommand(sortAttribute); + comparator = null; + expectedMessage = SortCommand.MESSAGE_UNSORTED_SUCCESS; + expectedModel.sortFilteredPersonList(comparator); + assertCommandSuccess(command, model, expectedMessage, expectedModel); } - @Test - public void execute_invalidSortAttribute_failure() { - ParserUtil.SortAttribute sortAttribute = ParserUtil.SortAttribute.NOTATTRIBUTE; - SortCommand command = new SortCommand(sortAttribute); - assertCommandFailure(command, model, SortCommand.MESSAGE_SORT_ATTRIBUTE_NOT_SPECIFIED); - } @Test public void equals() { diff --git a/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java b/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java index a5b894cf0e0..45e0d1b2f0d 100644 --- a/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java @@ -20,6 +20,10 @@ public void parse_emptyArg_throwsParseException() { assertParseFailure(parser, " ", MESSAGE_INVALID_FORMAT); } + @Test + public void parse_invalidArgs_throwsParseException() { + assertParseFailure(parser, "name and number", MESSAGE_INVALID_FORMAT); + } @Test public void parse_validArgs_returnsSortCommand() { SortCommand expectedSortCommand = new SortCommand(ParserUtil.SortAttribute.REGISTERNUMBER); From 653bb0634f044c937bfb14407c0607c1ff4a8dbf Mon Sep 17 00:00:00 2001 From: BunnyHoppp Date: Thu, 24 Oct 2024 04:55:44 +0800 Subject: [PATCH 6/8] Add more logging and assertion Practise defensive coding --- .../java/seedu/address/logic/commands/SortCommand.java | 9 +++++++-- .../seedu/address/logic/parser/SortCommandParser.java | 8 ++++++++ src/main/java/seedu/address/model/ModelManager.java | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/SortCommand.java b/src/main/java/seedu/address/logic/commands/SortCommand.java index f82a0d63f88..1edf49912b2 100644 --- a/src/main/java/seedu/address/logic/commands/SortCommand.java +++ b/src/main/java/seedu/address/logic/commands/SortCommand.java @@ -4,7 +4,10 @@ import static java.util.Objects.requireNonNull; import java.util.Comparator; +import java.util.logging.Level; +import java.util.logging.Logger; +import seedu.address.commons.core.LogsCenter; import seedu.address.logic.parser.ParserUtil.SortAttribute; import seedu.address.model.Model; import seedu.address.model.person.Person; @@ -31,10 +34,11 @@ public class SortCommand extends Command { public static final String MESSAGE_SORTED_SUCCESS = "Sorted the list based on %1$s"; public static final String MESSAGE_UNSORTED_SUCCESS = "Your list is now unsorted and back to the original!"; - + private static final Logger logger = LogsCenter.getLogger(SortCommand.class); private final SortAttribute sortAttribute; private Comparator comparator; + /** * @param sortAttribute attribute to sort the persons in the list */ @@ -48,6 +52,7 @@ public CommandResult execute(Model model) { requireNonNull(model); this.comparator = this.getComparator(); model.sortFilteredPersonList(this.comparator); + logger.log(Level.INFO, "SortCommand has been executed"); return new CommandResult(this.generateSuccessMessage()); } @@ -60,7 +65,7 @@ public String generateSuccessMessage() { * Returns null to unsort. */ public Comparator getComparator() { - + assert sortAttribute != null; switch (sortAttribute) { case NAME: diff --git a/src/main/java/seedu/address/logic/parser/SortCommandParser.java b/src/main/java/seedu/address/logic/parser/SortCommandParser.java index 7345b635885..23b1910d48a 100644 --- a/src/main/java/seedu/address/logic/parser/SortCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/SortCommandParser.java @@ -3,6 +3,10 @@ import static java.util.Objects.requireNonNull; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import java.util.logging.Level; +import java.util.logging.Logger; + +import seedu.address.commons.core.LogsCenter; import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.logic.commands.SortCommand; import seedu.address.logic.parser.ParserUtil.SortAttribute; @@ -13,6 +17,8 @@ */ public class SortCommandParser implements Parser { + private static final Logger logger = LogsCenter.getLogger(SortCommandParser.class); + /** * Parses the given {@code String} of arguments in the context of the SortCommand * and returns a SortCommand object for execution. @@ -27,6 +33,8 @@ public SortCommand parse(String args) throws ParseException { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, SortCommand.MESSAGE_USAGE), ive); } + assert sortAttribute != null; + logger.log(Level.INFO, "parsed sort command without exception"); return new SortCommand(sortAttribute); } } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 5064a1146ae..412d2fd7c82 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -130,11 +130,13 @@ public ObservableList getFilteredPersonList() { public void updateFilteredPersonList(Predicate predicate) { requireNonNull(predicate); filteredPersons.setPredicate(predicate); + logger.fine("Person list is filtered"); } @Override public void sortFilteredPersonList(Comparator comparator) { sortedAndFilteredPersons.setComparator(comparator); + logger.fine("Person list is sorted"); } @Override From fb2cf89238875d73b783c0566c623f9a96e6f14c Mon Sep 17 00:00:00 2001 From: BunnyHoppp Date: Thu, 24 Oct 2024 18:51:50 +0800 Subject: [PATCH 7/8] Change name of jar file Users are clear on the product they use --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 30aece18c7e..431a38c4019 100644 --- a/build.gradle +++ b/build.gradle @@ -70,7 +70,7 @@ dependencies { } shadowJar { - archiveFileName = 'addressbook.jar' + archiveFileName = 'studentmanagerpro.jar' } defaultTasks 'clean', 'test' From 40dc0d2b4b6bafea9d41cb0fe337ab43b8d280bc Mon Sep 17 00:00:00 2001 From: BunnyHoppp Date: Thu, 24 Oct 2024 18:58:19 +0800 Subject: [PATCH 8/8] Change GUI Modify the title when the GUI is open so users know it is StudentManagerPro --- src/main/resources/view/MainWindow.fxml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 7778f666a0a..bb6ba42a746 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -12,7 +12,7 @@ + title="StudentManagerPro" minWidth="450" minHeight="600" onCloseRequest="#handleExit">