Skip to content

Commit

Permalink
Merge pull request #124 from yyccbb/enhance-util-classes
Browse files Browse the repository at this point in the history
Refactor StringUtil into StatefulStringUtil
  • Loading branch information
wongkj12 authored Apr 5, 2024
2 parents 6c69139 + 6dde01a commit bc58c57
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 63 deletions.
12 changes: 6 additions & 6 deletions src/main/java/seedu/address/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import seedu.address.commons.core.Version;
import seedu.address.commons.exceptions.DataLoadingException;
import seedu.address.commons.util.ConfigUtil;
import seedu.address.commons.util.StringUtil;
import seedu.address.commons.util.StatefulStringUtil;
import seedu.address.logic.Logic;
import seedu.address.logic.LogicManager;
import seedu.address.logic.parser.StatefulParserUtil;
Expand Down Expand Up @@ -45,7 +45,7 @@ public class MainApp extends Application {
protected Logic logic;
protected Storage storage;
protected Model model;
protected StringUtil stringUtil;
protected StatefulStringUtil statefulStringUtil;
protected Config config;

@Override
Expand All @@ -68,7 +68,7 @@ public void init() throws Exception {

ui = new UiManager(logic);

StringUtil.initalize(model);
StatefulStringUtil.initialize(model);

Check warning on line 71 in src/main/java/seedu/address/MainApp.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/MainApp.java#L71

Added line #L71 was not covered by tests

StatefulParserUtil.initialize(model);

Check warning on line 73 in src/main/java/seedu/address/MainApp.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/MainApp.java#L73

Added line #L73 was not covered by tests
}
Expand Down Expand Up @@ -139,7 +139,7 @@ protected Config initConfig(Path configFilePath) {
try {
ConfigUtil.saveConfig(initializedConfig, configFilePathUsed);
} catch (IOException e) {
logger.warning("Failed to save config file : " + StringUtil.getDetails(e));
logger.warning("Failed to save config file : " + StatefulStringUtil.getDetails(e));

Check warning on line 142 in src/main/java/seedu/address/MainApp.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/MainApp.java#L142

Added line #L142 was not covered by tests
}
return initializedConfig;
}
Expand Down Expand Up @@ -170,7 +170,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
try {
storage.saveUserPrefs(initializedPrefs);
} catch (IOException e) {
logger.warning("Failed to save config file : " + StringUtil.getDetails(e));
logger.warning("Failed to save config file : " + StatefulStringUtil.getDetails(e));

Check warning on line 173 in src/main/java/seedu/address/MainApp.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/MainApp.java#L173

Added line #L173 was not covered by tests
}

return initializedPrefs;
Expand All @@ -188,7 +188,7 @@ public void stop() {
try {
storage.saveUserPrefs(model.getUserPrefs());
} catch (IOException e) {
logger.severe("Failed to save preferences " + StringUtil.getDetails(e));
logger.severe("Failed to save preferences " + StatefulStringUtil.getDetails(e));

Check warning on line 191 in src/main/java/seedu/address/MainApp.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/MainApp.java#L191

Added line #L191 was not covered by tests
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,26 @@
/**
* Helper functions for handling strings.
*/
public class StringUtil {
private static StringUtil instance = null;
private static ObservableList<TutorialTag> validTutorials;
public class StatefulStringUtil {
private static StatefulStringUtil instance = null;
private Model model;

private StringUtil(Model model) {
private StatefulStringUtil(Model model) {
this.model = model;
}

Check warning on line 25 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L23-L25

Added lines #L23 - L25 were not covered by tests

/**
* Initializes the StringUtil instance.
* Initializes the StatefulStringUtil instance.
*/
public static void initalize(Model model) {
public static void initialize(Model model) {
if (instance == null) {
instance = new StringUtil(model);
instance = new StatefulStringUtil(model);

Check warning on line 32 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L32

Added line #L32 was not covered by tests
}
}

Check warning on line 34 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L34

Added line #L34 was not covered by tests

public static StringUtil getInstance() {
public static StatefulStringUtil getInstance() {
if (instance == null) {
throw new NullPointerException("StringUtil has not been initialized");
throw new IllegalStateException("StatefulStringUtil has not been initialized");

Check warning on line 38 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L38

Added line #L38 was not covered by tests
}
return instance;

Check warning on line 40 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L40

Added line #L40 was not covered by tests
}
Expand Down Expand Up @@ -82,7 +81,8 @@ public static boolean tagContainsWordIgnoreCase(Tag tag, String word) {
String tagName = tag.getTagName().toLowerCase();
String preppedWord = word.trim();

Check warning on line 82 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L81-L82

Added lines #L81 - L82 were not covered by tests
checkArgument(!preppedWord.isEmpty(), "Word parameter cannot be empty");
validTutorials = instance.model.getTutorialTagList();
ObservableList<TutorialTag> validTutorials =
StatefulStringUtil.getInstance().model.getTutorialTagList();

Check warning on line 85 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L85

Added line #L85 was not covered by tests

for (TutorialTag tutorial : validTutorials) {
String tutorialGroup = tutorial.getTagName().toLowerCase();

Check warning on line 88 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L88

Added line #L88 was not covered by tests
Expand All @@ -106,7 +106,9 @@ public static boolean containsTutorialGroup(Tag tag, String tutorialGroup) {
String tagName = tag.getTagName();

Check warning on line 106 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L106

Added line #L106 was not covered by tests
checkArgument(!tutorialGroup.isEmpty(), "Tutorial group parameter cannot be empty");
checkArgument(!tutorialGroup.contains(" "), "Only use one word for tutorial group parameter");
validTutorials = instance.model.getTutorialTagList();

ObservableList<TutorialTag> validTutorials =
StatefulStringUtil.getInstance().model.getTutorialTagList();

Check warning on line 111 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L111

Added line #L111 was not covered by tests

for (TutorialTag tutorial : validTutorials) {
String validTutorialGroupTag = tutorial.getTagName();

Check warning on line 114 in src/main/java/seedu/address/commons/util/StatefulStringUtil.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/commons/util/StatefulStringUtil.java#L114

Added line #L114 was not covered by tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.util.stream.Stream;

import seedu.address.commons.core.index.Index;
import seedu.address.commons.util.StringUtil;
import seedu.address.commons.util.StatefulStringUtil;
import seedu.address.logic.Messages;
import seedu.address.logic.commands.EditTutTagListCommand;
import seedu.address.logic.parser.exceptions.ParseException;
Expand Down Expand Up @@ -63,7 +63,7 @@ public static StatefulParserUtil getInstance() {
*/
public static Index parseIndex(String oneBasedIndex) throws ParseException {
String trimmedIndex = oneBasedIndex.trim();
if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
if (!StatefulStringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
throw new ParseException(MESSAGE_INVALID_INDEX);
}
return Index.fromOneBased(Integer.parseInt(trimmedIndex));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.List;
import java.util.function.Predicate;

import seedu.address.commons.util.StringUtil;
import seedu.address.commons.util.StatefulStringUtil;
import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.parser.Prefix;

Expand Down Expand Up @@ -42,23 +42,28 @@ public FieldContainsKeywordsPredicate(List<String> keywords) {
public boolean test(Person person) {
if (this.prefix == null) { // type
return keywords.stream()
.anyMatch(keyword -> StringUtil.containsSubwordIgnoreCase(person.getType().name(), keyword));
.anyMatch(keyword -> StatefulStringUtil
.containsSubwordIgnoreCase(person.getType().name(), keyword));
} else if (this.prefix.equals(PREFIX_NAME)) {
return keywords.stream()
.anyMatch(keyword -> StringUtil.containsSubwordIgnoreCase(person.getName().fullName, keyword));
.anyMatch(keyword -> StatefulStringUtil
.containsSubwordIgnoreCase(person.getName().fullName, keyword));
} else if (this.prefix.equals(PREFIX_ID)) {
return keywords.stream()
.anyMatch(keyword -> StringUtil.containsSubwordIgnoreCase(person.getId().value, keyword));
.anyMatch(keyword -> StatefulStringUtil
.containsSubwordIgnoreCase(person.getId().value, keyword));

Check warning on line 54 in src/main/java/seedu/address/model/person/FieldContainsKeywordsPredicate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/model/person/FieldContainsKeywordsPredicate.java#L53-L54

Added lines #L53 - L54 were not covered by tests
} else if (this.prefix.equals(PREFIX_PHONE)) {
return keywords.stream()
.anyMatch(keyword -> StringUtil.containsSubwordIgnoreCase(person.getPhone().value, keyword));
.anyMatch(keyword -> StatefulStringUtil
.containsSubwordIgnoreCase(person.getPhone().value, keyword));

Check warning on line 58 in src/main/java/seedu/address/model/person/FieldContainsKeywordsPredicate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/model/person/FieldContainsKeywordsPredicate.java#L57-L58

Added lines #L57 - L58 were not covered by tests
} else if (this.prefix.equals(PREFIX_EMAIL)) {
return keywords.stream()
.anyMatch(keyword -> StringUtil.containsSubwordIgnoreCase(person.getEmail().value, keyword));
.anyMatch(keyword -> StatefulStringUtil
.containsSubwordIgnoreCase(person.getEmail().value, keyword));

Check warning on line 62 in src/main/java/seedu/address/model/person/FieldContainsKeywordsPredicate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/model/person/FieldContainsKeywordsPredicate.java#L61-L62

Added lines #L61 - L62 were not covered by tests
} else if (this.prefix.equals(PREFIX_TAG)) {
return keywords.stream()
.anyMatch(keyword -> person.getTags().stream()
.anyMatch(tag -> StringUtil.tagContainsWordIgnoreCase(tag, keyword)));
.anyMatch(tag -> StatefulStringUtil.tagContainsWordIgnoreCase(tag, keyword)));

Check warning on line 66 in src/main/java/seedu/address/model/person/FieldContainsKeywordsPredicate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/model/person/FieldContainsKeywordsPredicate.java#L65-L66

Added lines #L65 - L66 were not covered by tests
} else {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.function.Predicate;

import seedu.address.commons.util.StringUtil;
import seedu.address.commons.util.StatefulStringUtil;
import seedu.address.commons.util.ToStringBuilder;


Expand All @@ -19,7 +19,7 @@ public TutorialTagContainsGroupPredicate(String tutorialGroup) {
@Override
public boolean test(Person person) {
return person.getTags().stream()
.anyMatch(tag -> StringUtil.containsTutorialGroup(tag, tutorialGroup));
.anyMatch(tag -> StatefulStringUtil.containsTutorialGroup(tag, tutorialGroup));

Check warning on line 22 in src/main/java/seedu/address/model/person/TutorialTagContainsGroupPredicate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/model/person/TutorialTagContainsGroupPredicate.java#L21-L22

Added lines #L21 - L22 were not covered by tests
}

@Override
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/seedu/address/ui/UiManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import javafx.stage.Stage;
import seedu.address.MainApp;
import seedu.address.commons.core.LogsCenter;
import seedu.address.commons.util.StringUtil;
import seedu.address.commons.util.StatefulStringUtil;
import seedu.address.logic.Logic;

/**
Expand Down Expand Up @@ -45,7 +45,7 @@ public void start(Stage primaryStage) {
mainWindow.fillInnerParts();

} catch (Throwable e) {
logger.severe(StringUtil.getDetails(e));
logger.severe(StatefulStringUtil.getDetails(e));

Check warning on line 48 in src/main/java/seedu/address/ui/UiManager.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/ui/UiManager.java#L48

Added line #L48 was not covered by tests
showFatalErrorDialogAndShutdown("Fatal error during initializing", e);
}
}
Expand Down Expand Up @@ -79,7 +79,7 @@ private static void showAlertDialogAndWait(Stage owner, AlertType type, String t
* and exits the application after the user has closed the alert dialog.
*/
private void showFatalErrorDialogAndShutdown(String title, Throwable e) {
logger.severe(title + " " + e.getMessage() + StringUtil.getDetails(e));
logger.severe(title + " " + e.getMessage() + StatefulStringUtil.getDetails(e));

Check warning on line 82 in src/main/java/seedu/address/ui/UiManager.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/ui/UiManager.java#L82

Added line #L82 was not covered by tests
showAlertDialogAndWait(Alert.AlertType.ERROR, title, e.getMessage(), e.toString());
Platform.exit();
System.exit(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,42 @@
import org.junit.jupiter.api.Test;


public class StringUtilTest {
public class StatefulStringUtilTest {
//---------------- Tests for isNonZeroUnsignedInteger --------------------------------------
protected StringUtil testStringUtil;
protected StatefulStringUtil testStatefulStringUtil;


@Test
public void isNonZeroUnsignedInteger() {

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

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

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

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

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

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

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

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


Expand All @@ -59,24 +59,26 @@ public void isNonZeroUnsignedInteger() {

@Test
public void containsWordIgnoreCase_nullWord_throwsNullPointerException() {
assertThrows(NullPointerException.class, () -> StringUtil.containsSubwordIgnoreCase("typical sentence", null));
assertThrows(NullPointerException.class, () -> StatefulStringUtil
.containsSubwordIgnoreCase("typical sentence", null));
}

@Test
public void containsWordIgnoreCase_emptyWord_throwsIllegalArgumentException() {
assertThrows(IllegalArgumentException.class, "Word parameter cannot be empty", ()
-> StringUtil.containsSubwordIgnoreCase("typical sentence", " "));
-> StatefulStringUtil.containsSubwordIgnoreCase("typical sentence", " "));
}

@Test
public void containsWordIgnoreCase_multipleWords_throwsIllegalArgumentException() {
assertThrows(IllegalArgumentException.class, "Word parameter should be a single word", ()
-> StringUtil.containsSubwordIgnoreCase("typical sentence", "aaa BBB"));
-> StatefulStringUtil.containsSubwordIgnoreCase("typical sentence", "aaa BBB"));
}

@Test
public void containsWordIgnoreCase_nullSentence_throwsNullPointerException() {
assertThrows(NullPointerException.class, () -> StringUtil.containsSubwordIgnoreCase(null, "abc"));
assertThrows(NullPointerException.class, () -> StatefulStringUtil
.containsSubwordIgnoreCase(null, "abc"));
}

/*
Expand Down Expand Up @@ -108,23 +110,29 @@ public void containsWordIgnoreCase_nullSentence_throwsNullPointerException() {
public void containsWordIgnoreCase_validInputs_correctResult() {

// Empty sentence
assertFalse(StringUtil.containsSubwordIgnoreCase("", "abc")); // Boundary case
assertFalse(StringUtil.containsSubwordIgnoreCase(" ", "123"));
assertFalse(StatefulStringUtil.containsSubwordIgnoreCase("", "abc")); // Boundary case
assertFalse(StatefulStringUtil.containsSubwordIgnoreCase(" ", "123"));

// Matches a partial word only
assertTrue(StringUtil.containsSubwordIgnoreCase("aaa bbb ccc", "bb")); // Sentence word bigger than query word
assertFalse(StringUtil
assertTrue(StatefulStringUtil
.containsSubwordIgnoreCase("aaa bbb ccc", "bb")); // Sentence word bigger than query word
assertFalse(StatefulStringUtil
.containsSubwordIgnoreCase("aaa bbb ccc", "bbbb")); // Query word bigger than sentence word

// Matches word in the sentence, different upper/lower case letters
assertTrue(StringUtil.containsSubwordIgnoreCase("aaa bBb ccc", "Bbb")); // First word (boundary case)
assertTrue(StringUtil.containsSubwordIgnoreCase("aaa bBb ccc@1", "CCc@1")); // Last word (boundary case)
assertTrue(StringUtil.containsSubwordIgnoreCase(" AAA bBb ccc ", "aaa")); // Sentence has extra spaces
assertTrue(StringUtil.containsSubwordIgnoreCase("Aaa", "aaa")); // Only one word in sentence (boundary case)
assertTrue(StringUtil.containsSubwordIgnoreCase("aaa bbb ccc", " ccc ")); // Leading/trailing spaces
assertTrue(StatefulStringUtil
.containsSubwordIgnoreCase("aaa bBb ccc", "Bbb")); // First word (boundary case)
assertTrue(StatefulStringUtil
.containsSubwordIgnoreCase("aaa bBb ccc@1", "CCc@1")); // Last word (boundary case)
assertTrue(StatefulStringUtil
.containsSubwordIgnoreCase(" AAA bBb ccc ", "aaa")); // Sentence has extra spaces
assertTrue(StatefulStringUtil
.containsSubwordIgnoreCase("Aaa", "aaa")); // Only one word in sentence (boundary case)
assertTrue(StatefulStringUtil
.containsSubwordIgnoreCase("aaa bbb ccc", " ccc ")); // Leading/trailing spaces

// Matches multiple words in sentence
assertTrue(StringUtil.containsSubwordIgnoreCase("AAA bBb ccc bbb", "bbB"));
assertTrue(StatefulStringUtil.containsSubwordIgnoreCase("AAA bBb ccc bbb", "bbB"));
}

//---------------- Tests for getDetails --------------------------------------
Expand All @@ -135,20 +143,20 @@ public void containsWordIgnoreCase_validInputs_correctResult() {

@Test
public void getDetails_exceptionGiven() {
assertTrue(StringUtil.getDetails(new FileNotFoundException("file not found"))
assertTrue(StatefulStringUtil.getDetails(new FileNotFoundException("file not found"))
.contains("java.io.FileNotFoundException: file not found"));
}

@Test
public void getDetails_nullGiven_throwsNullPointerException() {
assertThrows(NullPointerException.class, () -> StringUtil.getDetails(null));
assertThrows(NullPointerException.class, () -> StatefulStringUtil.getDetails(null));
}


//---------------- Tests for tagContainsWordIgnoreCase --------------------------------------

@Test
public void testTagContainsWordIgnoreCase_nullWord_throwsNullPointerException() {
assertThrows(NullPointerException.class, () -> testStringUtil.tagContainsWordIgnoreCase(WED10, null));
assertThrows(NullPointerException.class, () -> testStatefulStringUtil.tagContainsWordIgnoreCase(WED10, null));
}
}

0 comments on commit bc58c57

Please sign in to comment.