Skip to content

Commit 57d8e2c

Browse files
committed
OPENNLP-1875: Address review: comment sweep, StringUtil.isUnicodeWhitespace facade
1 parent 9fd57a8 commit 57d8e2c

30 files changed

Lines changed: 111 additions & 177 deletions

File tree

opennlp-api/src/main/java/opennlp/tools/namefind/NameSample.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,6 @@ private static String errorTokenWithContext(String[] sentence, int index) {
262262
return errorString.toString();
263263
}
264264

265-
// Annotation-markup parsing: the <START:type> tag grammar itself excludes ASCII
266-
// whitespace in type names; this is the markup format, not user-text classification.
267265
private static final Pattern START_TAG_PATTERN = Pattern.compile("<START(:([^:>\\s]*))?>");
268266

269267

@@ -294,10 +292,6 @@ public static NameSample parse(String taggedTokens, boolean clearAdaptiveData) t
294292
public static NameSample parse(String taggedTokens, String defaultType, boolean clearAdaptiveData)
295293
throws IOException {
296294

297-
// Sample parsing deliberately shares the runtime WhitespaceTokenizer, so training samples
298-
// split exactly like inference input (Unicode White_Space since 3.0): annotation lines
299-
// containing U+0085 or U+001C..U+001F yield correspondingly shifted tokens and name
300-
// indices, pinned in NameSampleTest.
301295
String[] parts = WhitespaceTokenizer.INSTANCE.tokenize(taggedTokens);
302296

303297
List<String> tokenList = new ArrayList<>(parts.length);

opennlp-api/src/main/java/opennlp/tools/parser/Parse.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ public class Parse implements Cloneable, Comparable<Parse> {
119119

120120
/**
121121
* The patter used to identify tokens in Penn Treebank labeled constituents.
122-
* Format parsing: the bracketed PTB syntax is ASCII-whitespace delimited by definition.
123122
*/
124123
private static final Pattern tokenPattern = Pattern.compile("^[^ ()]+ ([^ ()]+)\\s*\\)");
125124

opennlp-api/src/main/java/opennlp/tools/postag/POSSample.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,6 @@ public String toString() {
162162
*/
163163
public static POSSample parse(String sentenceString) throws InvalidFormatException {
164164

165-
// Sample parsing deliberately shares the runtime WhitespaceTokenizer, so training samples
166-
// split exactly like inference input (Unicode White_Space since 3.0): lines containing
167-
// U+0085 or U+001C..U+001F yield correspondingly shifted word_tag pairs.
168165
String[] tokenTags = WhitespaceTokenizer.INSTANCE.tokenize(sentenceString);
169166

170167
String[] sentence = new String[tokenTags.length];

opennlp-api/src/main/java/opennlp/tools/tokenize/BertNormalization.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,9 @@ static boolean isControl(int codePoint) {
6363
* A whitespace character in the BERT sense: space, tab, newline, carriage
6464
* return, or Unicode space separators ({@code Zs}).
6565
*
66-
* <p>Intentional exception to the Unicode {@code White_Space} migration: this definition
67-
* is fixed by the reference BERT implementation, and pre-trained BERT vocabularies were
68-
* built with exactly this tokenization. It therefore excludes the {@code White_Space}
69-
* members {@code U+000B}, {@code U+000C}, {@code U+0085}, {@code U+2028} and
70-
* {@code U+2029} on purpose. Pinned by {@code BertNormalizationWhitespaceTest}.</p>
66+
* <p>Deliberately not the Unicode {@code White_Space} set: this definition is fixed by
67+
* the reference BERT implementation, and pre-trained vocabularies depend on it. Pinned by
68+
* {@code BertNormalizationWhitespaceTest}.</p>
7169
*/
7270
static boolean isWhitespace(int codePoint) {
7371
if (codePoint == ' ' || codePoint == '\t' || codePoint == '\n' || codePoint == '\r') {

opennlp-api/src/main/java/opennlp/tools/tokenize/TokenSample.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,6 @@ public static TokenSample parse(String sampleString, String separatorChars) {
179179
Objects.requireNonNull(sampleString, "sampleString must not be null");
180180
Objects.requireNonNull(separatorChars, "separatorChars must not be null");
181181

182-
// Sample parsing deliberately shares the runtime WhitespaceTokenizer, so training samples
183-
// split exactly like inference input (Unicode White_Space since 3.0): sample lines
184-
// containing U+0085 or U+001C..U+001F yield correspondingly shifted token spans.
185182
Span[] whitespaceTokenSpans = WhitespaceTokenizer.INSTANCE.tokenizePos(sampleString);
186183

187184
// Pre-allocate 20% for newly created tokens

opennlp-api/src/main/java/opennlp/tools/tokenize/WhitespaceTokenizer.java

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,16 @@
2121
import java.util.List;
2222

2323
import opennlp.tools.util.Span;
24-
import opennlp.tools.util.normalizer.UnicodeWhitespace;
24+
import opennlp.tools.util.StringUtil;
2525

2626
/**
2727
* A basic {@link Tokenizer} implementation which performs tokenization
2828
* using white spaces.
2929
* <p>
30-
* Whitespace is the Unicode {@code White_Space} set
31-
* ({@link UnicodeWhitespace#isWhitespace(int)}). Since 3.0 the next line control
32-
* {@code U+0085} separates tokens and the {@code U+001C}..{@code U+001F} information
33-
* separators no longer do, matching the standard instead of the JVM predicates. Token
34-
* boundaries produced for text containing those code points differ from earlier releases,
35-
* which can also shift the candidate spans {@code TokenizerME} scores for such text.
36-
* <p>
37-
* With {@link #setKeepNewLines(boolean)} enabled, the line separator code points
38-
* {@code \n}, {@code \r} and, since 3.0, the next line control {@code U+0085}, the line
39-
* separator {@code U+2028} and the paragraph separator {@code U+2029} are returned as
40-
* tokens of their own; all other whitespace is dropped.
30+
* Since 3.0, whitespace is the Unicode {@code White_Space} set
31+
* ({@link StringUtil#isUnicodeWhitespace(int)}); see OPENNLP-1875 for the delta to earlier
32+
* releases. With {@link #setKeepNewLines(boolean)} enabled, line separator code points are
33+
* returned as tokens of their own.
4134
* <p>
4235
* To obtain an instance of this tokenizer use the static final
4336
* {@link #INSTANCE} field.
@@ -65,7 +58,7 @@ public Span[] tokenizePos(String d) {
6558
// gather potential tokens
6659
int end = d.length();
6760
for (int i = 0; i < end; i++) {
68-
if (UnicodeWhitespace.isWhitespace(d.charAt(i))) {
61+
if (StringUtil.isUnicodeWhitespace(d.charAt(i))) {
6962
if (inTok) {
7063
tokens.add(new Span(tokStart, i));
7164
inTok = false;
@@ -91,10 +84,6 @@ public Span[] tokenizePos(String d) {
9184
return tokens.toArray(new Span[0]);
9285
}
9386

94-
// The line separator code points emitted as tokens under keepNewLines: the ASCII pair,
95-
// plus NEL (U+0085) and the Unicode line and paragraph separators, which count as
96-
// whitespace since 3.0. (The previous version compared against the Character category
97-
// constants LINE_SEPARATOR and LETTER_NUMBER, whose byte values happen to be 13 and 10.)
9887
private boolean isLineSeparator(char character) {
9988
return character == '\n' || character == '\r'
10089
|| character == '\u0085' || character == '\u2028' || character == '\u2029';

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import java.io.Serializable;
2222
import java.util.Objects;
2323

24-
import opennlp.tools.util.normalizer.UnicodeWhitespace;
25-
2624
/**
2725
* Class for storing start and end integer offsets.
2826
*
@@ -259,10 +257,8 @@ public CharSequence getCoveredText(CharSequence text) {
259257
}
260258

261259
/**
262-
* Whitespace here is the Unicode {@code White_Space} set
263-
* ({@link UnicodeWhitespace#isWhitespace(int)}). Since 3.0 this trims the next line
264-
* control {@code U+0085} and no longer trims the {@code U+001C}..{@code U+001F}
265-
* information separators, matching the standard instead of the JVM predicates.
260+
* Since 3.0, whitespace here is the Unicode {@code White_Space} set
261+
* ({@link StringUtil#isUnicodeWhitespace(int)}); see OPENNLP-1875.
266262
*
267263
* @param text The {@link CharSequence text} to analyze.
268264
*
@@ -273,12 +269,12 @@ public Span trim(CharSequence text) {
273269

274270
int newStartOffset = getStart();
275271

276-
for (int i = getStart(); i < getEnd() && UnicodeWhitespace.isWhitespace(text.charAt(i)); i++) {
272+
for (int i = getStart(); i < getEnd() && StringUtil.isUnicodeWhitespace(text.charAt(i)); i++) {
277273
newStartOffset++;
278274
}
279275

280276
int newEndOffset = getEnd();
281-
for (int i = getEnd(); i > getStart() && UnicodeWhitespace.isWhitespace(text.charAt(i - 1)); i--) {
277+
for (int i = getEnd(); i > getStart() && StringUtil.isUnicodeWhitespace(text.charAt(i - 1)); i--) {
282278
newEndOffset--;
283279
}
284280

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

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import org.slf4j.Logger;
2323
import org.slf4j.LoggerFactory;
2424

25+
import opennlp.tools.util.normalizer.UnicodeWhitespace;
26+
2527
public class StringUtil {
2628

2729
private static final Logger logger = LoggerFactory.getLogger(StringUtil.class);
@@ -32,15 +34,10 @@ public class StringUtil {
3234
* category ({@link Character#SPACE_SEPARATOR}), which adds the no-break spaces that
3335
* {@code Character.isWhitespace} excludes.
3436
*
35-
* <p>This predicate is deliberately <em>not</em> the Unicode {@code White_Space} property:
36-
* it additionally treats the information separators {@code U+001C}..{@code U+001F} as
37-
* whitespace and does not cover the next line control {@code U+0085}. It is kept frozen
38-
* because the feature generation of trained models is built on it
39-
* ({@code DefaultSDContextGenerator}, {@code DefaultTokenContextGenerator}); changing its
40-
* semantics would silently change the features generated for existing models. Code that
41-
* classifies whitespace in user text should use the standards-sourced
42-
* {@link opennlp.tools.util.normalizer.UnicodeWhitespace#isWhitespace(int)} or
43-
* {@link opennlp.tools.util.normalizer.CharClass#whitespace()} instead.</p>
37+
* <p>This predicate is deliberately not the Unicode {@code White_Space} property and is
38+
* kept frozen because trained-model feature generation depends on it. Use
39+
* {@link #isUnicodeWhitespace(char)} for whitespace classification in user text
40+
* (OPENNLP-1875).</p>
4441
*
4542
* @param charCode The character to check.
4643
*
@@ -57,15 +54,10 @@ public static boolean isWhitespace(char charCode) {
5754
* category ({@link Character#SPACE_SEPARATOR}), which adds the no-break spaces that
5855
* {@code Character.isWhitespace} excludes.
5956
*
60-
* <p>This predicate is deliberately <em>not</em> the Unicode {@code White_Space} property:
61-
* it additionally treats the information separators {@code U+001C}..{@code U+001F} as
62-
* whitespace and does not cover the next line control {@code U+0085}. It is kept frozen
63-
* because the feature generation of trained models is built on it
64-
* ({@code DefaultSDContextGenerator}, {@code DefaultTokenContextGenerator}); changing its
65-
* semantics would silently change the features generated for existing models. Code that
66-
* classifies whitespace in user text should use the standards-sourced
67-
* {@link opennlp.tools.util.normalizer.UnicodeWhitespace#isWhitespace(int)} or
68-
* {@link opennlp.tools.util.normalizer.CharClass#whitespace()} instead.</p>
57+
* <p>This predicate is deliberately not the Unicode {@code White_Space} property and is
58+
* kept frozen because trained-model feature generation depends on it. Use
59+
* {@link #isUnicodeWhitespace(int)} for whitespace classification in user text
60+
* (OPENNLP-1875).</p>
6961
*
7062
* @param charCode An int representation of a character to check.
7163
*
@@ -76,6 +68,34 @@ public static boolean isWhitespace(int charCode) {
7668
Character.getType(charCode) == Character.SPACE_SEPARATOR;
7769
}
7870

71+
/**
72+
* Determines if the specified {@link Character} is a whitespace under the Unicode
73+
* {@code White_Space} property; delegates to
74+
* {@link opennlp.tools.util.normalizer.UnicodeWhitespace#isWhitespace(int)}.
75+
*
76+
* @param charCode The character to check.
77+
*
78+
* @return {@code true} if {@code charCode} has the {@code White_Space} property,
79+
* {@code false} otherwise.
80+
*/
81+
public static boolean isUnicodeWhitespace(char charCode) {
82+
return UnicodeWhitespace.isWhitespace(charCode);
83+
}
84+
85+
/**
86+
* Determines if the specified code point is a whitespace under the Unicode
87+
* {@code White_Space} property; delegates to
88+
* {@link opennlp.tools.util.normalizer.UnicodeWhitespace#isWhitespace(int)}.
89+
*
90+
* @param charCode An int representation of a character to check.
91+
*
92+
* @return {@code true} if {@code charCode} has the {@code White_Space} property,
93+
* {@code false} otherwise.
94+
*/
95+
public static boolean isUnicodeWhitespace(int charCode) {
96+
return UnicodeWhitespace.isWhitespace(charCode);
97+
}
98+
7999

80100
/**
81101
* Converts a {@link CharSequence} to lower case, independent of the current

opennlp-core/opennlp-cli/src/main/java/opennlp/tools/cmdline/stopword/StopwordFilterTool.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,6 @@ public void run(final String[] args) {
9090
writer.println();
9191
continue;
9292
}
93-
// User text: tokenize on the Unicode White_Space set (WhitespaceTokenizer)
94-
// instead of the ASCII \s regex, so NBSP-style separators split tokens too.
9593
final String[] tokens = WhitespaceTokenizer.INSTANCE.tokenize(line);
9694
final String[] kept = filter.filter(tokens);
9795
writer.println(String.join(" ", kept));

opennlp-core/opennlp-formats/src/main/java/opennlp/tools/formats/ad/ADNameSampleStream.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ public class ADNameSampleStream implements ObjectStream<NameSample> {
7070
* Pattern of a NER tag in Arvores Deitadas
7171
*/
7272
private static final Pattern TAG_PATTERN = Pattern.compile("<(NER:)?(.*?)>");
73-
// Corpus-format parsing: AD tag fields are ASCII-whitespace delimited by the format.
7473
private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+");
7574
private static final Pattern UNDERLINE_PATTERN = Pattern.compile("[_]+");
7675
private static final Pattern HYPHEN_PATTERN =
@@ -402,7 +401,6 @@ private static String getNER(String tags) {
402401
if (tags.contains("<NER2>")) {
403402
return null;
404403
}
405-
// Corpus-format parsing: the AD tag field is ASCII-whitespace delimited by the format.
406404
String[] tag = tags.split("\\s+");
407405
for (String t : tag) {
408406
Matcher matcher = TAG_PATTERN.matcher(t);

0 commit comments

Comments
 (0)