Skip to content

Commit 082592d

Browse files
committed
OPENNLP-1888: Add StringUtil.isBlank following the toolkit whitespace definition
A blank check under the toolkit's whitespace definition, which unlike String.isBlank covers the no-break spaces, so annotators validating labels and identifiers share one predicate instead of each carrying a private copy. Reads whole code points; tests pin the no-break and figure spaces, the empty string, and a supplementary-plane letter.
1 parent 1404a50 commit 082592d

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

opennlp-api/src/main/java/opennlp/tools/util/StringUtil.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,27 @@ public static boolean isEmpty(CharSequence theString) {
268268
return theString.length() == 0;
269269
}
270270

271+
/**
272+
* Determines whether a {@link CharSequence} is blank: empty, or made up entirely of
273+
* code points that {@link #isWhitespace(int)} accepts. Unlike
274+
* {@link String#isBlank()}, this follows the toolkit's whitespace definition, which
275+
* includes the no-break spaces the JDK predicate leaves out, so a value spelled
276+
* entirely from them cannot pass a blank check as content.
277+
*
278+
* @param theString The {@link CharSequence} to examine. Must not be {@code null}.
279+
* @return {@code true} if {@code theString} is empty or all whitespace.
280+
*/
281+
public static boolean isBlank(CharSequence theString) {
282+
for (int i = 0; i < theString.length(); ) {
283+
final int codePoint = Character.codePointAt(theString, i);
284+
if (!isWhitespace(codePoint)) {
285+
return false;
286+
}
287+
i += Character.charCount(codePoint);
288+
}
289+
return true;
290+
}
291+
271292
/**
272293
* Get the minimum of three values.
273294
*

opennlp-tools/src/test/java/opennlp/tools/util/StringUtilTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,4 +679,23 @@ void testLowercaseBeyondBMP() {
679679
String lc = StringUtil.toLowerCase(input);
680680
Assertions.assertArrayEquals(expectedCodePoints, lc.codePoints().toArray());
681681
}
682+
683+
/**
684+
* Verifies the blank check against the toolkit's whitespace definition: the
685+
* no-break space is blank here although the JDK's own check does not cover it,
686+
* whitespace-only and empty values are blank, and any non-whitespace code point,
687+
* supplementary ones included, makes a value non-blank.
688+
*/
689+
@Test
690+
void testIsBlankFollowsTheToolkitWhitespaceDefinition() {
691+
Assertions.assertTrue(StringUtil.isBlank(""));
692+
Assertions.assertTrue(StringUtil.isBlank(" \t\n"));
693+
// U+00A0 no-break space and U+2007 figure space: JDK String.isBlank says false
694+
Assertions.assertTrue(StringUtil.isBlank("\u00A0"));
695+
Assertions.assertTrue(StringUtil.isBlank(" \u00A0\u2007 "));
696+
Assertions.assertFalse(StringUtil.isBlank("a"));
697+
Assertions.assertFalse(StringUtil.isBlank(" a "));
698+
// U+10428, a supplementary-plane letter read as one code point, not two chars
699+
Assertions.assertFalse(StringUtil.isBlank("\uD801\uDC28"));
700+
}
682701
}

0 commit comments

Comments
 (0)