Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/main/java/tutorly/commons/util/StringUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ public static String getDetails(Throwable t) {
}

/**
* Returns true if {@code s} represents a non-zero unsigned integer
* Returns true if {@code s} represents a non-zero unsigned integer, that can be parsed into an integer.
* e.g. 1, 2, 3, ..., {@code Integer.MAX_VALUE} <br>
* Will return false for any other non-null string input
* e.g. empty string, "-1", "0", "+1", and " 2 " (untrimmed), "3 0" (contains whitespace), "1 a" (contains letters)
* @throws NullPointerException if {@code s} is null.
*/
public static boolean isNonZeroUnsignedInteger(String s) {
public static boolean isParsableNonZeroUnsignedInteger(String s) {
requireNonNull(s);

try {
Expand All @@ -66,4 +66,13 @@ public static boolean isNonZeroUnsignedInteger(String s) {
return false;
}
}

/**
* Returns true if {@code s} represents a non-zero unsigned integer.
*/
public static boolean isNonZeroUnsignedInteger(String s) {
requireNonNull(s);
return s.matches("[1-9]\\d*");
}

}
6 changes: 6 additions & 0 deletions src/main/java/tutorly/logic/parser/ParserUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public static Identity parseIdentity(String identity) throws ParseException {
requireNonNull(identity);
String trimmedIdentity = identity.trim().replaceAll("\\s+", " ");
if (StringUtil.isNonZeroUnsignedInteger(trimmedIdentity)) {
if (!StringUtil.isParsableNonZeroUnsignedInteger(trimmedIdentity)) {
return new Identity(Identity.UNKNOWN_ID);
}
return new Identity(Integer.parseInt(trimmedIdentity));
}
if (Name.isValidName(trimmedIdentity)) {
Expand All @@ -80,6 +83,9 @@ public static int parseSessionId(String id) throws ParseException {
if (!StringUtil.isNonZeroUnsignedInteger(trimmedId)) {
throw new ParseException(Session.MESSAGE_INVALID_ID);
}
if (!StringUtil.isParsableNonZeroUnsignedInteger(trimmedId)) {
return Session.UNKNOWN_ID;
}
return Integer.parseInt(trimmedId);
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/tutorly/model/person/Identity.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class Identity {
public static final String MESSAGE_INVALID_IDENTITY =
"STUDENT_IDENTIFIER provided is not a valid student ID or name.";
public static final String MESSAGE_INVALID_ID = "Student ID must be a positive integer.";
public static final int UNKNOWN_ID = Integer.MAX_VALUE;

private int id;
private Name name;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/tutorly/model/session/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class Session {

public static final String MESSAGE_REASSIGNED_ID = "Session ID has already been set for this session.";
public static final String MESSAGE_INVALID_ID = "Session ID must be a positive integer.";
public static final int UNKNOWN_ID = Integer.MAX_VALUE;

private int id; // id field is effectively final
private final Timeslot timeslot;
Expand Down
38 changes: 36 additions & 2 deletions src/test/java/tutorly/commons/util/StringUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,41 @@

public class StringUtilTest {

//---------------- Tests for isParsableNonZeroUnsignedInteger --------------------------------------

@Test
public void isParsableNonZeroUnsignedInteger() {

// EP: empty strings
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger("")); // Boundary value
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger(" "));

// EP: not a number
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger("a"));
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger("aaa"));

// EP: zero
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger("0"));

// EP: zero as prefix
assertTrue(StringUtil.isParsableNonZeroUnsignedInteger("01"));

// EP: signed numbers
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger("-1"));
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger("+1"));

// EP: numbers with white space
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger(" 10 ")); // Leading/trailing spaces
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger("1 0")); // Spaces in the middle

// EP: number larger than Integer.MAX_VALUE
assertFalse(StringUtil.isParsableNonZeroUnsignedInteger(Long.toString(Integer.MAX_VALUE + 1)));

// EP: valid numbers, should return true
assertTrue(StringUtil.isParsableNonZeroUnsignedInteger("1")); // Boundary value
assertTrue(StringUtil.isParsableNonZeroUnsignedInteger("10"));
}

//---------------- Tests for isNonZeroUnsignedInteger --------------------------------------

@Test
Expand All @@ -27,7 +62,7 @@ public void isNonZeroUnsignedInteger() {
assertFalse(StringUtil.isNonZeroUnsignedInteger("0"));

// EP: zero as prefix
assertTrue(StringUtil.isNonZeroUnsignedInteger("01"));
assertFalse(StringUtil.isNonZeroUnsignedInteger("01"));

// EP: signed numbers
assertFalse(StringUtil.isNonZeroUnsignedInteger("-1"));
Expand All @@ -45,7 +80,6 @@ public void isNonZeroUnsignedInteger() {
assertTrue(StringUtil.isNonZeroUnsignedInteger("10"));
}


//---------------- Tests for containsWordIgnoreCase --------------------------------------

/*
Expand Down
17 changes: 11 additions & 6 deletions src/test/java/tutorly/logic/parser/ParserUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class ParserUtilTest {
private static final String WHITESPACE = " \t\r\n";

@Test
public void parseSessionIdentity_null_throwsNullPointerException() {
public void parseIdentity_null_throwsNullPointerException() {
assertThrows(NullPointerException.class, () -> ParserUtil.parseIdentity(null));
}

Expand All @@ -55,7 +55,7 @@ public void parseIdentity_invalidValue_throwsParseSessionException() {
}

@Test
public void parseSessionIdentity_validInput_success() throws Exception {
public void parseIdentity_validInput_success() throws Exception {
// No whitespaces
assertEquals(new Identity(new Name(VALID_NAME)), ParserUtil.parseIdentity(VALID_NAME));
assertEquals(new Identity(1), ParserUtil.parseIdentity("1"));
Expand All @@ -66,6 +66,10 @@ public void parseSessionIdentity_validInput_success() throws Exception {
assertEquals(new Identity(1), ParserUtil.parseIdentity(WHITESPACE + 1 + WHITESPACE));
assertEquals(new Identity(new Name("Bob Charlie")),
ParserUtil.parseIdentity(WHITESPACE + "Bob Charlie" + WHITESPACE));

// Unknown ID
assertEquals(new Identity(Identity.UNKNOWN_ID),
ParserUtil.parseIdentity(Long.toString(Integer.MAX_VALUE + 1L)));
}

@Test
Expand All @@ -74,14 +78,12 @@ public void parseSessionId_null_throwsNullPointerException() {
}

@Test
public void parseId_invalidInput_throwsParseSessionException() {
public void parseSessionId_invalidInput_throwsParseSessionException() {
assertThrows(ParseException.class, () -> ParserUtil.parseSessionId("10 a"));
}

@Test
public void parseId_outOfRangeInput_throwsParseSessionException() {
assertThrows(ParseException.class, Session.MESSAGE_INVALID_ID, ()
-> ParserUtil.parseSessionId(Long.toString(Integer.MAX_VALUE + 1)));
public void parseSessionId_outOfRangeInput_throwsParseSessionException() {
assertThrows(ParseException.class, Session.MESSAGE_INVALID_ID, () -> ParserUtil.parseSessionId("0"));
assertThrows(ParseException.class, Session.MESSAGE_INVALID_ID, () -> ParserUtil.parseSessionId("-1"));
assertThrows(ParseException.class, Session.MESSAGE_INVALID_ID, () -> ParserUtil.parseSessionId("1.1"));
Expand All @@ -94,6 +96,9 @@ public void parseSessionId_validInput_success() throws Exception {

// Leading and trailing whitespaces
assertEquals(1, ParserUtil.parseSessionId(" 1 "));

// Unknown ID
assertEquals(Session.UNKNOWN_ID, ParserUtil.parseSessionId(Long.toString(Integer.MAX_VALUE + 1L)));
}

@Test
Expand Down