From f557e43b1a6388920e70800c58c8899663f83601 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Jul 2025 16:20:48 -0400 Subject: [PATCH 001/265] Bump github/codeql-action from 3.29.1 to 3.29.2 (#679) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.1 to 3.29.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/39edc492dbe16b1465b0cafca41432d857bdb31a...181d5eefc20863364f96762470ba6f862bdef56b) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 481100eedd..9255621e98 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 + uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 + uses: github/codeql-action/autobuild@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 + uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 04df267f5b..4c90c9c49f 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 + uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 with: sarif_file: results.sarif From 235803c80a43c10f07b298a829763a38d7bb3758 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 6 Jul 2025 10:20:09 -0400 Subject: [PATCH 002/265] Reduce vertical whitespace --- pom.xml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/pom.xml b/pom.xml index cc14fb8fcb..d60d1b130a 100644 --- a/pom.xml +++ b/pom.xml @@ -36,28 +36,22 @@ 2025-04-10T21:38:03Z 1.8 1.8 - text text org.apache.commons.text - 1.14.0 1.14.1 (Java 8+) - TEXT 12318221 - text https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content - 3.17.0 1.17.6 1.6 false 1.37 - org.apache.commons.lang3;version="${commons.lang3.version}", @@ -65,7 +59,6 @@ org.apache.commons.lang3.time;version="${commons.lang3.version}", * - 1.13.1 @@ -139,7 +132,6 @@ test - clean verify apache-rat:check japicmp:cmp checkstyle:check spotbugs:check javadoc:javadoc @@ -242,7 +234,6 @@ - @@ -336,9 +327,7 @@ - 2014 - kinow @@ -376,7 +365,6 @@ djones@apache.org - Don Jeba @@ -421,18 +409,15 @@ https://ali-ghanbari.github.io/ - scm:git:https://gitbox.apache.org/repos/asf/commons-text scm:git:https://gitbox.apache.org/repos/asf/commons-text https://gitbox.apache.org/repos/asf?p=commons-text.git - jira https://issues.apache.org/jira/browse/TEXT - apache.website @@ -440,7 +425,6 @@ scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text/ - From 4b2fc1b300e3878664443da764f4307759447e76 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 6 Jul 2025 10:20:27 -0400 Subject: [PATCH 003/265] Add ciManagement element to POM --- pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pom.xml b/pom.xml index d60d1b130a..395b9564af 100644 --- a/pom.xml +++ b/pom.xml @@ -425,6 +425,10 @@ scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text/ + + GitHub + https://github.com/apache/commons-text/actions + From 74a0c2bbc53f0d8627e5ede3847f371ca327781b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 18:38:54 -0400 Subject: [PATCH 004/265] Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 (#680) Bumps org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.18.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 395b9564af..0cc7eebb99 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ text https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content - 3.17.0 + 3.18.0 1.17.6 1.6 false From ee389d16741fcae4856687e3fd988b647bdf770a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 9 Jul 2025 18:40:14 -0400 Subject: [PATCH 005/265] Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #680 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 5e23808a55..60e45fb86a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -56,6 +56,7 @@ The type attribute can be add,update,fix,remove. Bump commons-io:commons-io from 2.18.0 to 2.19.0. Bump graalvm.version from 24.2.0 to 24.2.1 #665. Bump commons.bytebuddy.version from 1.17.5 to 1.17.6 (#677). + Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #680. From b5c843a272ca5bb54d6d80d66d02d592fd994529 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:27:38 -0400 Subject: [PATCH 006/265] Bump graalvm.version from 24.2.1 to 24.2.2 (#681) Bumps `graalvm.version` from 24.2.1 to 24.2.2. Updates `org.graalvm.js:js` from 24.2.1 to 24.2.2 - [Release notes](https://github.com/oracle/graal/releases) - [Commits](https://github.com/oracle/graal/compare/vm-24.2.1...vm-24.2.2) Updates `org.graalvm.js:js-scriptengine` from 24.2.1 to 24.2.2 - [Release notes](https://github.com/graalvm/graaljs/releases) - [Changelog](https://github.com/oracle/graaljs/blob/vm-24.2.2/CHANGELOG.md) - [Commits](https://github.com/graalvm/graaljs/compare/vm-24.2.1...vm-24.2.2) Updates `org.graalvm.js:js-language` from 24.2.1 to 24.2.2 - [Release notes](https://github.com/graalvm/graaljs/releases) - [Changelog](https://github.com/oracle/graaljs/blob/vm-24.2.2/CHANGELOG.md) - [Commits](https://github.com/graalvm/graaljs/compare/vm-24.2.1...vm-24.2.2) Updates `org.graalvm.truffle:truffle-runtime` from 24.2.1 to 24.2.2 - [Release notes](https://github.com/oracle/graal/releases) - [Commits](https://github.com/oracle/graal/compare/vm-24.2.1...vm-24.2.2) --- updated-dependencies: - dependency-name: org.graalvm.js:js dependency-version: 24.2.2 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: org.graalvm.js:js-scriptengine dependency-version: 24.2.2 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: org.graalvm.js:js-language dependency-version: 24.2.2 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: org.graalvm.truffle:truffle-runtime dependency-version: 24.2.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0cc7eebb99..75a095fa7b 100644 --- a/pom.xml +++ b/pom.xml @@ -501,7 +501,7 @@ [22,) - 24.2.1 + 24.2.2 5.2.0 From 3e6476ef7ee1e7dbde9d6c5b8f0599de93a1e11c Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 18 Jul 2025 16:28:51 -0400 Subject: [PATCH 007/265] Bump graalvm.version from 24.2.1 to 24.2.2 #681 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 60e45fb86a..21b8173585 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,7 +54,7 @@ The type attribute can be add,update,fix,remove. Bump org.apache.commons:commons-parent from 81 to 85 #668. Bump commons-io:commons-io from 2.18.0 to 2.19.0. - Bump graalvm.version from 24.2.0 to 24.2.1 #665. + Bump graalvm.version from 24.2.0 to 24.2.2 #665, #681. Bump commons.bytebuddy.version from 1.17.5 to 1.17.6 (#677). Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #680. From 21a726220e4c5d55007bb0c33f1a74224bf26eb8 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 18 Jul 2025 17:52:24 -0400 Subject: [PATCH 008/265] Bump commons-io:commons-io from 2.19.0 to 2.20.0 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 75a095fa7b..ac6cbd3414 100644 --- a/pom.xml +++ b/pom.xml @@ -110,7 +110,7 @@ commons-io commons-io - 2.19.0 + 2.20.0 test diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 21b8173585..197a3d0890 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,7 +53,7 @@ The type attribute can be add,update,fix,remove. Add RandomStringGenerator.Builder.usingRandom(IntUnaryOperator). Bump org.apache.commons:commons-parent from 81 to 85 #668. - Bump commons-io:commons-io from 2.18.0 to 2.19.0. + Bump commons-io:commons-io from 2.18.0 to 2.20.0. Bump graalvm.version from 24.2.0 to 24.2.2 #665, #681. Bump commons.bytebuddy.version from 1.17.5 to 1.17.6 (#677). Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #680. From c28d837cb042014785dce4307d2cdef2779263b8 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:26:57 -0400 Subject: [PATCH 009/265] Sort members --- .../apache/commons/text/RandomStringGeneratorTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java index d52100ac89..3cc5a9e4ef 100644 --- a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java +++ b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java @@ -280,9 +280,9 @@ void testSetLength() { } @Test - void testUsingRandomTextRandomProvider() { + void testUsingRandomIntUnaryOperator() { final char testChar = 'a'; - final TextRandomProvider testRandom = n -> testChar; + final IntUnaryOperator testRandom = n -> testChar; final String str = RandomStringGenerator.builder().usingRandom(testRandom).build().generate(10); for (final char c : str.toCharArray()) { assertEquals(testChar, c); @@ -290,9 +290,9 @@ void testUsingRandomTextRandomProvider() { } @Test - void testUsingRandomIntUnaryOperator() { + void testUsingRandomTextRandomProvider() { final char testChar = 'a'; - final IntUnaryOperator testRandom = n -> testChar; + final TextRandomProvider testRandom = n -> testChar; final String str = RandomStringGenerator.builder().usingRandom(testRandom).build().generate(10); for (final char c : str.toCharArray()) { assertEquals(testChar, c); From f42954511df9a3c16539c7467865bc91b33a3be5 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:27:49 -0400 Subject: [PATCH 010/265] Update description --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 197a3d0890..03df27d21a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -45,7 +45,7 @@ The type attribute can be add,update,fix,remove. Apache Commons Text Changes - + Interface StringLookup now extends UnaryOperator<String>. From 926bdff801062bf50261b4a98503759bdc596094 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:29:34 -0400 Subject: [PATCH 011/265] No longer need to override the version of the Jacoco Maven plugin Pick up the version from the parent POM. --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index ac6cbd3414..679138a15d 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,6 @@ commons.releaseManagerName commons.releaseManagerKey --> - 0.8.12 true 1.00 From 45ca471fb75213b243c9e2da459f38934f4e6317 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:35:41 -0400 Subject: [PATCH 012/265] Fix all PMD UnnecessaryFullyQualifiedName in StringLookupFactory --- src/changes/changes.xml | 1 + .../commons/text/lookup/StringLookupFactory.java | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 03df27d21a..27bdd1f4a0 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,6 +47,7 @@ The type attribute can be add,update,fix,remove. + Fix all PMD UnnecessaryFullyQualifiedName in StringLookupFactory. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java index a323335b4c..448588eb54 100644 --- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java +++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java @@ -691,7 +691,7 @@ public void addDefaultStringLookups(final Map stringLookup * @since 1.5 */ public StringLookup base64DecoderStringLookup() { - return StringLookupFactory.INSTANCE_BASE64_DECODER; + return INSTANCE_BASE64_DECODER; } /** @@ -718,7 +718,7 @@ public StringLookup base64DecoderStringLookup() { * @since 1.6 */ public StringLookup base64EncoderStringLookup() { - return StringLookupFactory.INSTANCE_BASE64_ENCODER; + return INSTANCE_BASE64_ENCODER; } /** @@ -747,7 +747,7 @@ public StringLookup base64EncoderStringLookup() { */ @Deprecated public StringLookup base64StringLookup() { - return StringLookupFactory.INSTANCE_BASE64_DECODER; + return INSTANCE_BASE64_DECODER; } /** @@ -889,7 +889,7 @@ public StringLookup dnsStringLookup() { * @return The EnvironmentVariableStringLookup singleton instance. */ public StringLookup environmentVariableStringLookup() { - return StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES; + return INSTANCE_ENVIRONMENT_VARIABLES; } /** @@ -1185,7 +1185,7 @@ public StringLookup mapStringLookup(final Map map) { * @return The NullStringLookup singleton instance. */ public StringLookup nullStringLookup() { - return StringLookupFactory.INSTANCE_NULL; + return INSTANCE_NULL; } /** @@ -1426,7 +1426,7 @@ public StringLookup scriptStringLookup() { * @return The SystemPropertyStringLookup singleton instance. */ public StringLookup systemPropertyStringLookup() { - return StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES; + return INSTANCE_SYSTEM_PROPERTIES; } /** From bddd6a0ec11f2512bebe699c0870591750d0de60 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:39:11 -0400 Subject: [PATCH 013/265] Fix all PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder --- src/changes/changes.xml | 1 + .../org/apache/commons/text/lookup/StringLookupFactory.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 27bdd1f4a0..5d28354f32 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,6 +48,7 @@ The type attribute can be add,update,fix,remove. Fix all PMD UnnecessaryFullyQualifiedName in StringLookupFactory. + Fix all PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java index 448588eb54..8a8b484fdf 100644 --- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java +++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java @@ -345,8 +345,8 @@ private static Map parseStringLookups(final String str) { * @param props initialization properties */ DefaultStringLookupsHolder(final Properties props) { - final Map lookups = props.containsKey(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY) - ? parseStringLookups(props.getProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY)) + final Map lookups = props.containsKey(DEFAULT_STRING_LOOKUPS_PROPERTY) + ? parseStringLookups(props.getProperty(DEFAULT_STRING_LOOKUPS_PROPERTY)) : createDefaultStringLookups(); defaultStringLookups = Collections.unmodifiableMap(lookups); } From 04deae6a2c069d3bd4c7b5e90027ac221ca1dba5 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:40:33 -0400 Subject: [PATCH 014/265] Fix PMD UnnecessaryFullyQualifiedName in PropertiesStringLookup --- src/changes/changes.xml | 5 +++-- .../apache/commons/text/lookup/PropertiesStringLookup.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 5d28354f32..3aed20341c 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,8 +47,9 @@ The type attribute can be add,update,fix,remove. - Fix all PMD UnnecessaryFullyQualifiedName in StringLookupFactory. - Fix all PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder. + Fix PMD UnnecessaryFullyQualifiedName in StringLookupFactory. + Fix PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder. + Fix PMD UnnecessaryFullyQualifiedName in PropertiesStringLookup. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java b/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java index 7420c407a0..d369ffcf39 100644 --- a/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java @@ -53,7 +53,7 @@ final class PropertiesStringLookup extends AbstractPathFencedLookup { * Creates a lookup key for a given file and key. */ static String toPropertyKey(final String file, final String key) { - return AbstractStringLookup.toLookupKey(file, SEPARATOR, key); + return toLookupKey(file, SEPARATOR, key); } /** From bd83c9aa4ea6da149ec859ff842571f977302a5c Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:41:49 -0400 Subject: [PATCH 015/265] Fix PMD UnnecessaryFullyQualifiedName in JavaPlatformStringLookup --- src/changes/changes.xml | 1 + .../text/lookup/JavaPlatformStringLookup.java | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 3aed20341c..4af56c0b5b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,6 +50,7 @@ The type attribute can be add,update,fix,remove. Fix PMD UnnecessaryFullyQualifiedName in StringLookupFactory. Fix PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder. Fix PMD UnnecessaryFullyQualifiedName in PropertiesStringLookup. + Fix PMD UnnecessaryFullyQualifiedName in JavaPlatformStringLookup. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java index dea176ef39..da1048bbe6 100644 --- a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java @@ -83,12 +83,12 @@ final class JavaPlatformStringLookup extends AbstractStringLookup { */ public static void main(final String[] args) { System.out.println(JavaPlatformStringLookup.class); - System.out.printf("%s = %s%n", KEY_VERSION, JavaPlatformStringLookup.INSTANCE.lookup(KEY_VERSION)); - System.out.printf("%s = %s%n", KEY_RUNTIME, JavaPlatformStringLookup.INSTANCE.lookup(KEY_RUNTIME)); - System.out.printf("%s = %s%n", KEY_VM, JavaPlatformStringLookup.INSTANCE.lookup(KEY_VM)); - System.out.printf("%s = %s%n", KEY_OS, JavaPlatformStringLookup.INSTANCE.lookup(KEY_OS)); - System.out.printf("%s = %s%n", KEY_HARDWARE, JavaPlatformStringLookup.INSTANCE.lookup(KEY_HARDWARE)); - System.out.printf("%s = %s%n", KEY_LOCALE, JavaPlatformStringLookup.INSTANCE.lookup(KEY_LOCALE)); + System.out.printf("%s = %s%n", KEY_VERSION, INSTANCE.lookup(KEY_VERSION)); + System.out.printf("%s = %s%n", KEY_RUNTIME, INSTANCE.lookup(KEY_RUNTIME)); + System.out.printf("%s = %s%n", KEY_VM, INSTANCE.lookup(KEY_VM)); + System.out.printf("%s = %s%n", KEY_OS, INSTANCE.lookup(KEY_OS)); + System.out.printf("%s = %s%n", KEY_HARDWARE, INSTANCE.lookup(KEY_HARDWARE)); + System.out.printf("%s = %s%n", KEY_LOCALE, INSTANCE.lookup(KEY_LOCALE)); } /** From 78a29c9eca551e838fca9cc642c1812bf1b65910 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:42:57 -0400 Subject: [PATCH 016/265] Fix PMD UnnecessaryFullyQualifiedName in StringSubstitutor --- src/changes/changes.xml | 1 + src/main/java/org/apache/commons/text/StringSubstitutor.java | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4af56c0b5b..87e599fbcf 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,7 @@ The type attribute can be add,update,fix,remove. Fix PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder. Fix PMD UnnecessaryFullyQualifiedName in PropertiesStringLookup. Fix PMD UnnecessaryFullyQualifiedName in JavaPlatformStringLookup. + Fix PMD UnnecessaryFullyQualifiedName in StringSubstitutor. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/StringSubstitutor.java b/src/main/java/org/apache/commons/text/StringSubstitutor.java index 601419153d..1780d97223 100644 --- a/src/main/java/org/apache/commons/text/StringSubstitutor.java +++ b/src/main/java/org/apache/commons/text/StringSubstitutor.java @@ -434,8 +434,7 @@ public static String replace(final Object source, final Properties valueProperti if (valueProperties == null) { return source.toString(); } - return StringSubstitutor.replace(source, - valueProperties.stringPropertyNames().stream().collect(Collectors.toMap(Function.identity(), valueProperties::getProperty))); + return replace(source, valueProperties.stringPropertyNames().stream().collect(Collectors.toMap(Function.identity(), valueProperties::getProperty))); } /** @@ -637,7 +636,7 @@ public StringSubstitutor(final StringLookup variableResolver, final StringMatche } /** - * Creates a new instance based on the given StringSubstitutor. + * Creates a new instance based on the given * * @param other The StringSubstitutor used as the source. * @since 1.9 From b488bfc2d4dc2c02e6cb63b0bedb83e4463bf363 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:44:01 -0400 Subject: [PATCH 017/265] Fix PMD UnnecessaryFullyQualifiedName in StrSubstitutor --- src/changes/changes.xml | 1 + src/main/java/org/apache/commons/text/StrSubstitutor.java | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 87e599fbcf..45df800437 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,6 +52,7 @@ The type attribute can be add,update,fix,remove. Fix PMD UnnecessaryFullyQualifiedName in PropertiesStringLookup. Fix PMD UnnecessaryFullyQualifiedName in JavaPlatformStringLookup. Fix PMD UnnecessaryFullyQualifiedName in StringSubstitutor. + Fix PMD UnnecessaryFullyQualifiedName in StrSubstitutor. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/StrSubstitutor.java b/src/main/java/org/apache/commons/text/StrSubstitutor.java index 88570e8530..aa839710d4 100644 --- a/src/main/java/org/apache/commons/text/StrSubstitutor.java +++ b/src/main/java/org/apache/commons/text/StrSubstitutor.java @@ -191,8 +191,7 @@ public static String replace(final Object source, final Properties valueProperti if (valueProperties == null) { return source.toString(); } - return StrSubstitutor.replace(source, - valueProperties.stringPropertyNames().stream().collect(Collectors.toMap(Function.identity(), valueProperties::getProperty))); + return replace(source, valueProperties.stringPropertyNames().stream().collect(Collectors.toMap(Function.identity(), valueProperties::getProperty))); } /** From 1e4931439098999f27099877a0bbdee6e0c561de Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 13:44:45 -0400 Subject: [PATCH 018/265] Fix PMD UnnecessaryFullyQualifiedName in AlphabetConverter --- src/changes/changes.xml | 1 + src/main/java/org/apache/commons/text/AlphabetConverter.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 45df800437..9fdb798d1b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,6 +53,7 @@ The type attribute can be add,update,fix,remove. Fix PMD UnnecessaryFullyQualifiedName in JavaPlatformStringLookup. Fix PMD UnnecessaryFullyQualifiedName in StringSubstitutor. Fix PMD UnnecessaryFullyQualifiedName in StrSubstitutor. + Fix PMD UnnecessaryFullyQualifiedName in AlphabetConverter. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/AlphabetConverter.java b/src/main/java/org/apache/commons/text/AlphabetConverter.java index acbb05b798..46feb8ae3c 100644 --- a/src/main/java/org/apache/commons/text/AlphabetConverter.java +++ b/src/main/java/org/apache/commons/text/AlphabetConverter.java @@ -242,7 +242,7 @@ public static AlphabetConverter createConverterFromChars( final Character[] original, final Character[] encoding, final Character[] doNotEncode) { - return AlphabetConverter.createConverter( + return createConverter( convertCharsToIntegers(original), convertCharsToIntegers(encoding), convertCharsToIntegers(doNotEncode)); From 477a74f5b6b5a31b572f7040fde26da626452979 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 14:09:45 -0400 Subject: [PATCH 019/265] Fix Checkstyle --- src/main/java/org/apache/commons/text/StringSubstitutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/StringSubstitutor.java b/src/main/java/org/apache/commons/text/StringSubstitutor.java index 1780d97223..1cffd67d72 100644 --- a/src/main/java/org/apache/commons/text/StringSubstitutor.java +++ b/src/main/java/org/apache/commons/text/StringSubstitutor.java @@ -636,7 +636,7 @@ public StringSubstitutor(final StringLookup variableResolver, final StringMatche } /** - * Creates a new instance based on the given + * Creates a new instance based on the given. * * @param other The StringSubstitutor used as the source. * @since 1.9 From a84093d8b9746753ddc1e1f3f4e0fb012212d251 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 14:10:46 -0400 Subject: [PATCH 020/265] Fix PMD AvoidBranchingStatementAsLastInLoop in TextStringBuilder --- src/changes/changes.xml | 1 + .../commons/text/TextStringBuilder.java | 46 ++++++++++--------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 9fdb798d1b..e550ad8afa 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,6 +54,7 @@ The type attribute can be add,update,fix,remove. Fix PMD UnnecessaryFullyQualifiedName in StringSubstitutor. Fix PMD UnnecessaryFullyQualifiedName in StrSubstitutor. Fix PMD UnnecessaryFullyQualifiedName in AlphabetConverter. + Fix PMD AvoidBranchingStatementAsLastInLoop in TextStringBuilder. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java index 95616cf02d..939ce1eaf1 100644 --- a/src/main/java/org/apache/commons/text/TextStringBuilder.java +++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java @@ -635,8 +635,8 @@ public TextStringBuilder append(final long value) { /** * Appends an object to this string builder. Appending null will call {@link #appendNull()}. * - * @param obj the object to append - * @return this, to enable chaining + * @param obj the object to append. + * @return this, to enable chaining. */ public TextStringBuilder append(final Object obj) { if (obj == null) { @@ -2128,14 +2128,15 @@ public int indexOf(final String str, int startIndex) { return StringUtils.INDEX_NOT_FOUND; } final char[] thisBuf = buffer; - final int len = size - strLen + 1; - outer: for (int i = startIndex; i < len; i++) { - for (int j = 0; j < strLen; j++) { - if (str.charAt(j) != thisBuf[i + j]) { - continue outer; - } + final int searchLen = size - strLen + 1; + for (int i = startIndex; i < searchLen; i++) { + boolean found = true; + for (int j = 0; j < strLen && found; j++) { + found = str.charAt(j) == thisBuf[i + j]; + } + if (found) { + return i; } - return i; } return StringUtils.INDEX_NOT_FOUND; } @@ -2457,22 +2458,23 @@ public int lastIndexOf(final String str, int startIndex) { return StringUtils.INDEX_NOT_FOUND; } final int strLen = str.length(); - if (strLen > 0 && strLen <= size) { - if (strLen == 1) { - return lastIndexOf(str.charAt(0), startIndex); + if (strLen == 0) { + return startIndex; + } + if (strLen > size) { + return StringUtils.INDEX_NOT_FOUND; + } + if (strLen == 1) { + return lastIndexOf(str.charAt(0), startIndex); + } + for (int i = startIndex - strLen + 1; i >= 0; i--) { + boolean found = true; + for (int j = 0; j < strLen && found; j++) { + found = str.charAt(j) == buffer[i + j]; } - - outer: for (int i = startIndex - strLen + 1; i >= 0; i--) { - for (int j = 0; j < strLen; j++) { - if (str.charAt(j) != buffer[i + j]) { - continue outer; - } - } + if (found) { return i; } - - } else if (strLen == 0) { - return startIndex; } return StringUtils.INDEX_NOT_FOUND; } From 74f18e737332f7e5343fe7ce57694d89b54a954c Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 14:14:04 -0400 Subject: [PATCH 021/265] Fix PMD AvoidBranchingStatementAsLastInLoop in StrBuilder --- src/changes/changes.xml | 1 + .../org/apache/commons/text/StrBuilder.java | 54 ++++++++++--------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e550ad8afa..0d1aa51f71 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -55,6 +55,7 @@ The type attribute can be add,update,fix,remove. Fix PMD UnnecessaryFullyQualifiedName in StrSubstitutor. Fix PMD UnnecessaryFullyQualifiedName in AlphabetConverter. Fix PMD AvoidBranchingStatementAsLastInLoop in TextStringBuilder. + Fix PMD AvoidBranchingStatementAsLastInLoop in StrBuilder. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/StrBuilder.java b/src/main/java/org/apache/commons/text/StrBuilder.java index 25759a7e9c..a89ebec3ac 100644 --- a/src/main/java/org/apache/commons/text/StrBuilder.java +++ b/src/main/java/org/apache/commons/text/StrBuilder.java @@ -1946,9 +1946,9 @@ public int indexOf(final String str) { * @return The first index of the string, or -1 if not found */ public int indexOf(final String str, int startIndex) { - startIndex = Math.max(startIndex, 0); + startIndex = Math.max(0, startIndex); if (str == null || startIndex >= size) { - return -1; + return StringUtils.INDEX_NOT_FOUND; } final int strLen = str.length(); if (strLen == 1) { @@ -1958,19 +1958,20 @@ public int indexOf(final String str, int startIndex) { return startIndex; } if (strLen > size) { - return -1; + return StringUtils.INDEX_NOT_FOUND; } final char[] thisBuf = buffer; - final int len = size - strLen + 1; - outer: for (int i = startIndex; i < len; i++) { - for (int j = 0; j < strLen; j++) { - if (str.charAt(j) != thisBuf[i + j]) { - continue outer; - } + final int searchLen = size - strLen + 1; + for (int i = startIndex; i < searchLen; i++) { + boolean found = true; + for (int j = 0; j < strLen && found; j++) { + found = str.charAt(j) == thisBuf[i + j]; + } + if (found) { + return i; } - return i; } - return -1; + return StringUtils.INDEX_NOT_FOUND; } /** @@ -2282,27 +2283,28 @@ public int lastIndexOf(final String str) { public int lastIndexOf(final String str, int startIndex) { startIndex = startIndex >= size ? size - 1 : startIndex; if (str == null || startIndex < 0) { - return -1; + return StringUtils.INDEX_NOT_FOUND; } final int strLen = str.length(); - if (strLen > 0 && strLen <= size) { - if (strLen == 1) { - return lastIndexOf(str.charAt(0), startIndex); + if (strLen == 0) { + return startIndex; + } + if (strLen > size) { + return StringUtils.INDEX_NOT_FOUND; + } + if (strLen == 1) { + return lastIndexOf(str.charAt(0), startIndex); + } + for (int i = startIndex - strLen + 1; i >= 0; i--) { + boolean found = true; + for (int j = 0; j < strLen && found; j++) { + found = str.charAt(j) == buffer[i + j]; } - - outer: for (int i = startIndex - strLen + 1; i >= 0; i--) { - for (int j = 0; j < strLen; j++) { - if (str.charAt(j) != buffer[i + j]) { - continue outer; - } - } + if (found) { return i; } - - } else if (strLen == 0) { - return startIndex; } - return -1; + return StringUtils.INDEX_NOT_FOUND; } /** From 7a19f816a0694d6818dafdad9ebb084d4a6e8e49 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 19 Jul 2025 14:15:02 -0400 Subject: [PATCH 022/265] Add PMD check to default Maven goal --- pom.xml | 2 +- src/changes/changes.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 679138a15d..5e4ab7a622 100644 --- a/pom.xml +++ b/pom.xml @@ -132,7 +132,7 @@ - clean verify apache-rat:check japicmp:cmp checkstyle:check spotbugs:check javadoc:javadoc + clean verify apache-rat:check japicmp:cmp checkstyle:check pmd:check spotbugs:check javadoc:javadoc diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 0d1aa51f71..272f878ddf 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -60,6 +60,7 @@ The type attribute can be add,update,fix,remove. Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. Add RandomStringGenerator.Builder.usingRandom(IntUnaryOperator). + Add PMD check to default Maven goal. Bump org.apache.commons:commons-parent from 81 to 85 #668. Bump commons-io:commons-io from 2.18.0 to 2.20.0. From 6226b9f603727324a7fbd8af16b49dd43f1a8eb0 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 07:39:26 -0400 Subject: [PATCH 023/265] Reduce vertical whitespace --- .../text/RandomStringGeneratorTest.java | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java index 3cc5a9e4ef..9daea44b56 100644 --- a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java +++ b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.text; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -33,7 +34,6 @@ class RandomStringGeneratorTest { private static final CharacterPredicate A_FILTER = codePoint -> codePoint == 'a'; - private static final CharacterPredicate B_FILTER = codePoint -> codePoint == 'b'; private static int codePointLength(final String s) { @@ -109,10 +109,8 @@ void testInvalidLength() { @Test void testMultipleFilters() { final String str = RandomStringGenerator.builder().withinRange('a', 'd').filteredBy(A_FILTER, B_FILTER).build().generate(5000); - boolean aFound = false; boolean bFound = false; - for (final char c : str.toCharArray()) { if (c == 'a') { aFound = true; @@ -122,7 +120,6 @@ void testMultipleFilters() { fail("Invalid character"); } } - assertTrue(aFound && bFound); } @@ -130,24 +127,19 @@ void testMultipleFilters() { void testNoLoneSurrogates() { final int length = 5000; final String str = RandomStringGenerator.builder().build().generate(length); - char lastChar = str.charAt(0); for (int i = 1; i < str.length(); i++) { final char c = str.charAt(i); - if (Character.isLowSurrogate(c)) { assertTrue(Character.isHighSurrogate(lastChar)); } - if (Character.isHighSurrogate(lastChar)) { assertTrue(Character.isLowSurrogate(c)); } - if (Character.isHighSurrogate(c)) { // test this isn't the last character in the string assertTrue(i + 1 < str.length()); } - lastChar = c; } } @@ -155,12 +147,10 @@ void testNoLoneSurrogates() { @Test void testNoPrivateCharacters() { final int startOfPrivateBMPChars = 0xE000; - // Request a string in an area of the Basic Multilingual Plane that is // largely occupied by private characters final String str = RandomStringGenerator.builder().withinRange(startOfPrivateBMPChars, Character.MIN_SUPPLEMENTARY_CODE_POINT - 1).build() .generate(5000); - int i = 0; do { final int codePoint = str.codePointAt(i); @@ -172,9 +162,7 @@ void testNoPrivateCharacters() { @Test void testRemoveFilters() { final RandomStringGenerator.Builder builder = RandomStringGenerator.builder().withinRange('a', 'z').filteredBy(A_FILTER); - builder.filteredBy(); - final String str = builder.build().generate(100); for (final char c : str.toCharArray()) { if (c != 'a') { @@ -182,7 +170,6 @@ void testRemoveFilters() { return; } } - fail("Filter appears to have remained in place"); } @@ -191,9 +178,7 @@ void testSelectFromCharArray() { final String str = "abc"; final char[] charArray = str.toCharArray(); final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom(charArray).build(); - final String randomText = generator.generate(5); - for (final char c : randomText.toCharArray()) { assertTrue(str.indexOf(c) != -1); } @@ -311,14 +296,11 @@ void testWithinMultipleRanges() { .build(); // @formatter:on final String str = generator.generate(length); - int minimumCodePoint = 0, maximumCodePoint = 0; - for (final char[] pair : pairs) { minimumCodePoint = Math.min(minimumCodePoint, pair[0]); maximumCodePoint = Math.max(maximumCodePoint, pair[1]); } - int i = 0; do { final int codePoint = str.codePointAt(i); @@ -334,7 +316,6 @@ void testWithinRange() { final int maximumCodePoint = 'z'; final RandomStringGenerator generator = RandomStringGenerator.builder().withinRange(minimumCodePoint, maximumCodePoint).build(); final String str = generator.generate(length); - int i = 0; do { final int codePoint = str.codePointAt(i); From d300a983a0cfd8377163ae3d88e469fa327c64ff Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 07:40:23 -0400 Subject: [PATCH 024/265] [Javadoc] Fix formatting in example --- .../java/org/apache/commons/text/RandomStringGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/commons/text/RandomStringGenerator.java b/src/main/java/org/apache/commons/text/RandomStringGenerator.java index 9668a6e2a0..7d1de6a234 100644 --- a/src/main/java/org/apache/commons/text/RandomStringGenerator.java +++ b/src/main/java/org/apache/commons/text/RandomStringGenerator.java @@ -285,9 +285,9 @@ public Builder usingRandom(final TextRandomProvider random) { * For example: *
          * {@code
-         *     char [][] pairs = {{'0','9'}};
-         *     char [][] pairs = {{'a','z'}};
-         *     char [][] pairs = {{'a','z'},{'0','9'}};
+         *     char[][] pairs = {{'0','9'}};
+         *     char[][] pairs = {{'a','z'}};
+         *     char[][] pairs = {{'a','z'},{'0','9'}};
          * }
          * 
* From 73c17bcde26486817083e137221b43026a80d6a3 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 07:49:33 -0400 Subject: [PATCH 025/265] Reduce vertical whitespace --- .../commons/text/RandomStringGenerator.java | 228 ++++++++---------- 1 file changed, 94 insertions(+), 134 deletions(-) diff --git a/src/main/java/org/apache/commons/text/RandomStringGenerator.java b/src/main/java/org/apache/commons/text/RandomStringGenerator.java index 7d1de6a234..3ec2788701 100644 --- a/src/main/java/org/apache/commons/text/RandomStringGenerator.java +++ b/src/main/java/org/apache/commons/text/RandomStringGenerator.java @@ -29,15 +29,12 @@ import org.apache.commons.lang3.Validate; /** - * Generates random Unicode strings containing the specified number of code points. - * Instances are created using a builder class, which allows the - * callers to define the properties of the generator. See the documentation for the - * {@link Builder} class to see available properties. + * Generates random Unicode strings containing the specified number of code points. Instances are created using a builder class, which allows the callers to + * define the properties of the generator. See the documentation for the {@link Builder} class to see available properties. * *
  * // Generates a 20 code point string, using only the letters a-z
- * RandomStringGenerator generator = RandomStringGenerator.builder()
- *     .withinRange('a', 'z').build();
+ * RandomStringGenerator generator = RandomStringGenerator.builder().withinRange('a', 'z').build();
  * String randomLetters = generator.generate(20);
  * 
*
@@ -46,16 +43,15 @@
  * // Generates a 20 code point string, using only the letters a-z
  * RandomStringGenerator generator = RandomStringGenerator.builder()
  *     .withinRange('a', 'z')
- *     .usingRandom(rng::nextInt) // uses Java 8 syntax
+ *     .usingRandom(rng::nextInt)
  *     .build();
  * String randomLetters = generator.generate(20);
  * 
*

- * {@code RandomStringGenerator} instances are thread-safe when using the - * default random number generator (RNG). If a custom RNG is set by calling the method - * {@link Builder#usingRandom(TextRandomProvider) Builder.usingRandom(TextRandomProvider)}, thread-safety - * must be ensured externally. + * {@code RandomStringGenerator} instances are thread-safe when using the default random number generator (RNG). If a custom RNG is set by calling the method + * {@link Builder#usingRandom(TextRandomProvider) Builder.usingRandom(TextRandomProvider)}, thread-safety must be ensured externally. *

+ * * @since 1.1 */ public final class RandomStringGenerator { @@ -63,24 +59,29 @@ public final class RandomStringGenerator { /** * A builder for generating {@code RandomStringGenerator} instances. * - *

The behavior of a generator is controlled by properties set by this - * builder. Each property has a default value, which can be overridden by - * calling the methods defined in this class, prior to calling {@link #build()}.

- * - *

All the property setting methods return the {@code Builder} instance to allow for method chaining.

- * - *

The minimum and maximum code point values are defined using {@link #withinRange(int, int)}. The - * default values are {@code 0} and {@link Character#MAX_CODE_POINT} respectively.

- * - *

The source of randomness can be set using {@link #usingRandom(TextRandomProvider)}, - * otherwise {@link ThreadLocalRandom} is used.

- * - *

The type of code points returned can be filtered using {@link #filteredBy(CharacterPredicate...)}, - * which defines a collection of tests that are applied to the randomly generated code points. - * The code points will only be included in the result if they pass at least one of the tests. - * Some commonly used predicates are provided by the {@link CharacterPredicates} enum.

+ *

+ * The behavior of a generator is controlled by properties set by this builder. Each property has a default value, which can be overridden by calling the + * methods defined in this class, prior to calling {@link #build()}. + *

+ *

+ * All the property setting methods return the {@code Builder} instance to allow for method chaining. + *

+ *

+ * The minimum and maximum code point values are defined using {@link #withinRange(int, int)}. The default values are {@code 0} and + * {@link Character#MAX_CODE_POINT} respectively. + *

+ *

+ * The source of randomness can be set using {@link #usingRandom(TextRandomProvider)}, otherwise {@link ThreadLocalRandom} is used. + *

+ *

+ * The type of code points returned can be filtered using {@link #filteredBy(CharacterPredicate...)}, which defines a collection of tests that are applied + * to the randomly generated code points. The code points will only be included in the result if they pass at least one of the tests. Some commonly used + * predicates are provided by the {@link CharacterPredicates} enum. + *

+ *

+ * This class is not thread safe. + *

* - *

This class is not thread safe.

* @since 1.1 */ public static class Builder implements org.apache.commons.text.Builder { @@ -146,18 +147,15 @@ public RandomStringGenerator build() { } /** - * Limits the characters in the generated string to those that match at - * least one of the predicates supplied. + * Limits the characters in the generated string to those that match at least one of the predicates supplied. * *

- * Passing {@code null} or an empty array to this method will revert to the - * default behavior of allowing any character. Multiple calls to this - * method will replace the previously stored predicates. + * Passing {@code null} or an empty array to this method will revert to the default behavior of allowing any character. Multiple calls to this method + * will replace the previously stored predicates. *

* - * @param predicates - * the predicates, may be {@code null} or empty - * @return {@code this}, to allow method chaining + * @param predicates the predicates, may be {@code null} or empty. + * @return {@code this}, to allow method chaining. */ public Builder filteredBy(final CharacterPredicate... predicates) { if (ArrayUtils.isEmpty(predicates)) { @@ -176,7 +174,7 @@ public Builder filteredBy(final CharacterPredicate... predicates) { /** * Builds a new {@code RandomStringGenerator}. * - * @return A new {@code RandomStringGenerator} + * @return A new {@code RandomStringGenerator}. * @since 1.12.0 */ @Override @@ -185,18 +183,15 @@ public RandomStringGenerator get() { } /** - * Limits the characters in the generated string to those who match at - * supplied list of Character. + * Limits the characters in the generated string to those who match at supplied list of Character. * *

- * Passing {@code null} or an empty array to this method will revert to the - * default behavior of allowing any character. Multiple calls to this - * method will replace the previously stored Character. + * Passing {@code null} or an empty array to this method will revert to the default behavior of allowing any character. Multiple calls to this method + * will replace the previously stored Character. *

* - * @param chars set of predefined Characters for random string generation - * the Character can be, may be {@code null} or empty - * @return {@code this}, to allow method chaining + * @param chars set of predefined Characters for random string generation the Character can be, may be {@code null} or empty + * @return {@code this}, to allow method chaining. * @since 1.2 */ public Builder selectFrom(final char... chars) { @@ -210,15 +205,13 @@ public Builder selectFrom(final char... chars) { } /** - * Overrides the default source of randomness. It is highly - * recommended that a random number generator library like - * Apache Commons RNG - * be used to provide the random number generation. + * Overrides the default source of randomness. It is highly recommended that a random number generator library like + * Apache Commons RNG be used to provide the random number generation. * *

- * {@link TextRandomProvider} is a - * functional interface and need not be explicitly implemented: + * {@link TextRandomProvider} is a functional interface and need not be explicitly implemented: *

+ * *
          * {@code
          *     UniformRandomProvider rng = RandomSource.create(...);
@@ -230,13 +223,11 @@ public Builder selectFrom(final char... chars) {
          * 
* *

- * Passing {@code null} to this method will revert to the default source of - * randomness. + * Passing {@code null} to this method will revert to the default source of randomness. *

* - * @param random - * the source of randomness, may be {@code null} - * @return {@code this}, to allow method chaining + * @param random the source of randomness, may be {@code null}. + * @return {@code this}, to allow method chaining. * @since 1.14.0 */ public Builder usingRandom(final IntUnaryOperator random) { @@ -245,15 +236,13 @@ public Builder usingRandom(final IntUnaryOperator random) { } /** - * Overrides the default source of randomness. It is highly - * recommended that a random number generator library like - * Apache Commons RNG - * be used to provide the random number generation. + * Overrides the default source of randomness. It is highly recommended that a random number generator library like + * Apache Commons RNG be used to provide the random number generation. * *

- * {@link TextRandomProvider} is a - * functional interface and need not be explicitly implemented: + * {@link TextRandomProvider} is a functional interface and need not be explicitly implemented: *

+ * *
          * {@code
          *     UniformRandomProvider rng = RandomSource.create(...);
@@ -265,13 +254,11 @@ public Builder usingRandom(final IntUnaryOperator random) {
          * 
* *

- * Passing {@code null} to this method will revert to the default source of - * randomness. + * Passing {@code null} to this method will revert to the default source of randomness. *

* - * @param random - * the source of randomness, may be {@code null} - * @return {@code this}, to allow method chaining + * @param random the source of randomness, may be {@code null}. + * @return {@code this}, to allow method chaining. */ public Builder usingRandom(final TextRandomProvider random) { this.random = random; @@ -279,15 +266,16 @@ public Builder usingRandom(final TextRandomProvider random) { } /** - * Sets the array of minimum and maximum char allowed in the - * generated string. + * Sets the array of minimum and maximum char allowed in the generated string. * * For example: + * *
          * {@code
-         *     char[][] pairs = {{'0','9'}};
-         *     char[][] pairs = {{'a','z'}};
-         *     char[][] pairs = {{'a','z'},{'0','9'}};
+         *
+         * char[][] pairs = { { '0', '9' } };
+         * char[][] pairs = { { 'a', 'z' } };
+         * char[][] pairs = { { 'a', 'z' }, { '0', '9' } };
          * }
          * 
* @@ -303,39 +291,29 @@ public Builder withinRange(final char[]... pairs) { final int maximumCodePoint = pair[1]; Validate.isTrue(minimumCodePoint <= maximumCodePoint, "Minimum code point %d is larger than maximum code point %d", minimumCodePoint, maximumCodePoint); - for (int index = minimumCodePoint; index <= maximumCodePoint; index++) { characterList.add((char) index); } } } return this; - } /** - * Sets the minimum and maximum code points allowed in the - * generated string. + * Sets the minimum and maximum code points allowed in the generated string. * - * @param minimumCodePoint - * the smallest code point allowed (inclusive) - * @param maximumCodePoint - * the largest code point allowed (inclusive) - * @return {@code this}, to allow method chaining - * @throws IllegalArgumentException - * if {@code maximumCodePoint >} - * {@link Character#MAX_CODE_POINT} - * @throws IllegalArgumentException - * if {@code minimumCodePoint < 0} - * @throws IllegalArgumentException - * if {@code minimumCodePoint > maximumCodePoint} + * @param minimumCodePoint the smallest code point allowed (inclusive). + * @param maximumCodePoint the largest code point allowed (inclusive). + * @return {@code this}, to allow method chaining. + * @throws IllegalArgumentException if {@code maximumCodePoint >} {@link Character#MAX_CODE_POINT}. + * @throws IllegalArgumentException if {@code minimumCodePoint < 0}. + * @throws IllegalArgumentException if {@code minimumCodePoint > maximumCodePoint}. */ public Builder withinRange(final int minimumCodePoint, final int maximumCodePoint) { - Validate.isTrue(minimumCodePoint <= maximumCodePoint, - "Minimum code point %d is larger than maximum code point %d", minimumCodePoint, maximumCodePoint); + Validate.isTrue(minimumCodePoint <= maximumCodePoint, "Minimum code point %d is larger than maximum code point %d", minimumCodePoint, + maximumCodePoint); Validate.isTrue(minimumCodePoint >= 0, "Minimum code point %d is negative", minimumCodePoint); - Validate.isTrue(maximumCodePoint <= Character.MAX_CODE_POINT, - "Value %d is larger than Character.MAX_CODE_POINT.", maximumCodePoint); + Validate.isTrue(maximumCodePoint <= Character.MAX_CODE_POINT, "Value %d is larger than Character.MAX_CODE_POINT.", maximumCodePoint); this.minimumCodePoint = minimumCodePoint; this.maximumCodePoint = maximumCodePoint; return this; @@ -344,6 +322,7 @@ public Builder withinRange(final int minimumCodePoint, final int maximumCodePoin /** * Constructs a new builder. + * * @return a new builder. * @since 1.11.0 */ @@ -379,15 +358,11 @@ public static Builder builder() { /** * Constructs the generator. * - * @param minimumCodePoint - * smallest allowed code point (inclusive) - * @param maximumCodePoint - * largest allowed code point (inclusive) - * @param inclusivePredicates - * filters for code points - * @param random - * source of randomness - * @param characterList list of predefined set of characters. + * @param minimumCodePoint smallest allowed code point (inclusive). + * @param maximumCodePoint largest allowed code point (inclusive). + * @param inclusivePredicates filters for code points. + * @param random source of randomness. + * @param characterList list of predefined set of characters. */ private RandomStringGenerator(final Builder builder) { this.minimumCodePoint = builder.minimumCodePoint; @@ -401,24 +376,17 @@ private RandomStringGenerator(final Builder builder) { * Generates a random string, containing the specified number of code points. * *

- * Code points are randomly selected between the minimum and maximum values defined - * in the generator. - * Surrogate and private use characters are not returned, although the - * resulting string may contain pairs of surrogates that together encode a - * supplementary character. + * Code points are randomly selected between the minimum and maximum values defined in the generator. Surrogate and private use characters are not returned, + * although the resulting string may contain pairs of surrogates that together encode a supplementary character. *

*

- * Note: the number of {@code char} code units generated will exceed - * {@code length} if the string contains supplementary characters. See the - * {@link Character} documentation to understand how Java stores Unicode - * values. + * Note: the number of {@code char} code units generated will exceed {@code length} if the string contains supplementary characters. See the + * {@link Character} documentation to understand how Java stores Unicode values. *

* - * @param length - * the number of code points to generate - * @return The generated string - * @throws IllegalArgumentException - * if {@code length < 0} + * @param length the number of code points to generate. + * @return The generated string. + * @throws IllegalArgumentException if {@code length < 0}. */ public String generate(final int length) { if (length == 0) { @@ -460,34 +428,27 @@ public String generate(final int length) { } /** - * Generates a random string, containing between the minimum (inclusive) and the maximum (inclusive) - * number of code points. + * Generates a random string, containing between the minimum (inclusive) and the maximum (inclusive) number of code points. * - * @param minLengthInclusive - * the minimum (inclusive) number of code points to generate - * @param maxLengthInclusive - * the maximum (inclusive) number of code points to generate - * @return The generated string - * @throws IllegalArgumentException - * if {@code minLengthInclusive < 0}, or {@code maxLengthInclusive < minLengthInclusive} + * @param minLengthInclusive the minimum (inclusive) number of code points to generate. + * @param maxLengthInclusive the maximum (inclusive) number of code points to generate. + * @return The generated string. + * @throws IllegalArgumentException if {@code minLengthInclusive < 0}, or {@code maxLengthInclusive < minLengthInclusive}. * @see RandomStringGenerator#generate(int) * @since 1.2 */ public String generate(final int minLengthInclusive, final int maxLengthInclusive) { Validate.isTrue(minLengthInclusive >= 0, "Minimum length %d is smaller than zero.", minLengthInclusive); - Validate.isTrue(minLengthInclusive <= maxLengthInclusive, - "Maximum length %d is smaller than minimum length %d.", maxLengthInclusive, minLengthInclusive); + Validate.isTrue(minLengthInclusive <= maxLengthInclusive, "Maximum length %d is smaller than minimum length %d.", maxLengthInclusive, + minLengthInclusive); return generate(generateRandomNumber(minLengthInclusive, maxLengthInclusive)); } /** - * Generates a random number within a range, using a {@link ThreadLocalRandom} instance - * or the user-supplied source of randomness. + * Generates a random number within a range, using a {@link ThreadLocalRandom} instance or the user-supplied source of randomness. * - * @param minInclusive - * the minimum value allowed - * @param maxInclusive - * the maximum value allowed + * @param minInclusive the minimum value allowed. + * @param maxInclusive the maximum value allowed. * @return The random number. */ private int generateRandomNumber(final int minInclusive, final int maxInclusive) { @@ -498,8 +459,7 @@ private int generateRandomNumber(final int minInclusive, final int maxInclusive) } /** - * Generates a random number within a range, using a {@link ThreadLocalRandom} instance - * or the user-supplied source of randomness. + * Generates a random number within a range, using a {@link ThreadLocalRandom} instance or the user-supplied source of randomness. * * @param characterList predefined char list. * @return The random number. From 91e7eac4b51c3dc08262285a83e6d4831f8d2410 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 08:41:32 -0400 Subject: [PATCH 026/265] Add org.apache.commons.text.RandomStringGenerator.Builder.setAccumulate(boolean) This is instead of breaking compatibility with https://github.com/apache/commons-text/pull/125 --- src/changes/changes.xml | 1 + .../commons/text/RandomStringGenerator.java | 63 ++++++++++++++----- .../text/RandomStringGeneratorTest.java | 54 ++++++++++++++-- 3 files changed, 100 insertions(+), 18 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 272f878ddf..302829a057 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -61,6 +61,7 @@ The type attribute can be add,update,fix,remove. Interface TextRandomProvider extends IntUnaryOperator. Add RandomStringGenerator.Builder.usingRandom(IntUnaryOperator). Add PMD check to default Maven goal. + Add org.apache.commons.text.RandomStringGenerator.Builder.setAccumulate(boolean). Bump org.apache.commons:commons-parent from 81 to 85 #668. Bump commons-io:commons-io from 2.18.0 to 2.20.0. diff --git a/src/main/java/org/apache/commons/text/RandomStringGenerator.java b/src/main/java/org/apache/commons/text/RandomStringGenerator.java index 3ec2788701..f39212b7e9 100644 --- a/src/main/java/org/apache/commons/text/RandomStringGenerator.java +++ b/src/main/java/org/apache/commons/text/RandomStringGenerator.java @@ -125,7 +125,12 @@ public static class Builder implements org.apache.commons.text.Builder characterList; + private Set characterSet = new HashSet<>(); + + /** + * Whether calls accumulates the source of provided characters. The default is {@code false}. + */ + private boolean accumulate; /** * Creates a new instance. @@ -155,7 +160,7 @@ public RandomStringGenerator build() { *

* * @param predicates the predicates, may be {@code null} or empty. - * @return {@code this}, to allow method chaining. + * @return {@code this} instance. */ public Builder filteredBy(final CharacterPredicate... predicates) { if (ArrayUtils.isEmpty(predicates)) { @@ -182,6 +187,12 @@ public RandomStringGenerator get() { return new RandomStringGenerator(this); } + private void initCharList() { + if (!accumulate) { + characterSet = new HashSet<>(); + } + } + /** * Limits the characters in the generated string to those who match at supplied list of Character. * @@ -191,19 +202,43 @@ public RandomStringGenerator get() { *

* * @param chars set of predefined Characters for random string generation the Character can be, may be {@code null} or empty - * @return {@code this}, to allow method chaining. + * @return {@code this} instance. * @since 1.2 */ public Builder selectFrom(final char... chars) { - characterList = new ArrayList<>(); + initCharList(); if (chars != null) { for (final char c : chars) { - characterList.add(c); + characterSet.add(c); } } return this; } + /** + * Sets whether calls accumulates the source of provided characters. The default is {@code false}. + * + *
+         * {@code
+         *     RandomStringGenerator gen = RandomStringGenerator.builder()
+         *         .setAccumulate(true)
+         *         .withinRange(new char[][] { { 'a', 'z' }, { 'A', 'Z' }, { '0', '9' } })
+         *         .selectFrom('!', '"', '#', '$', '&', '\'', '(', ')', ',', '.', ':', ';', '?', '@', '[',
+         *                     '\\', ']', '^', '_', '`', '{', '|', '}', '~') // punctuation
+         *         // additional builder calls as needed
+         *         .build();
+         * }
+         * 
+ * + * @param accumulate whether calls accumulates the source of provided characters. The default is {@code false}. + * @return {@code this} instance. + * @since 1.14.0 + */ + public Builder setAccumulate(final boolean accumulate) { + this.accumulate = accumulate; + return this; + } + /** * Overrides the default source of randomness. It is highly recommended that a random number generator library like * Apache Commons RNG be used to provide the random number generation. @@ -227,7 +262,7 @@ public Builder selectFrom(final char... chars) { *

* * @param random the source of randomness, may be {@code null}. - * @return {@code this}, to allow method chaining. + * @return {@code this} instance. * @since 1.14.0 */ public Builder usingRandom(final IntUnaryOperator random) { @@ -258,7 +293,7 @@ public Builder usingRandom(final IntUnaryOperator random) { *

* * @param random the source of randomness, may be {@code null}. - * @return {@code this}, to allow method chaining. + * @return {@code this} instance. */ public Builder usingRandom(final TextRandomProvider random) { this.random = random; @@ -272,7 +307,6 @@ public Builder usingRandom(final TextRandomProvider random) { * *
          * {@code
-         *
          * char[][] pairs = { { '0', '9' } };
          * char[][] pairs = { { 'a', 'z' } };
          * char[][] pairs = { { 'a', 'z' }, { '0', '9' } };
@@ -280,10 +314,10 @@ public Builder usingRandom(final TextRandomProvider random) {
          * 
* * @param pairs array of characters array, expected is to pass min, max pairs through this arg. - * @return {@code this}, to allow method chaining. + * @return {@code this} instance. */ public Builder withinRange(final char[]... pairs) { - characterList = new ArrayList<>(); + initCharList(); if (pairs != null) { for (final char[] pair : pairs) { Validate.isTrue(pair.length == 2, "Each pair must contain minimum and maximum code point"); @@ -292,19 +326,20 @@ public Builder withinRange(final char[]... pairs) { Validate.isTrue(minimumCodePoint <= maximumCodePoint, "Minimum code point %d is larger than maximum code point %d", minimumCodePoint, maximumCodePoint); for (int index = minimumCodePoint; index <= maximumCodePoint; index++) { - characterList.add((char) index); + characterSet.add((char) index); } } } return this; } + /** * Sets the minimum and maximum code points allowed in the generated string. * * @param minimumCodePoint the smallest code point allowed (inclusive). * @param maximumCodePoint the largest code point allowed (inclusive). - * @return {@code this}, to allow method chaining. + * @return {@code this} instance. * @throws IllegalArgumentException if {@code maximumCodePoint >} {@link Character#MAX_CODE_POINT}. * @throws IllegalArgumentException if {@code minimumCodePoint < 0}. * @throws IllegalArgumentException if {@code minimumCodePoint > maximumCodePoint}. @@ -362,14 +397,14 @@ public static Builder builder() { * @param maximumCodePoint largest allowed code point (inclusive). * @param inclusivePredicates filters for code points. * @param random source of randomness. - * @param characterList list of predefined set of characters. + * @param characterSet list of predefined set of characters. */ private RandomStringGenerator(final Builder builder) { this.minimumCodePoint = builder.minimumCodePoint; this.maximumCodePoint = builder.maximumCodePoint; this.inclusivePredicates = builder.inclusivePredicates; this.random = builder.random; - this.characterList = builder.characterList; + this.characterList = new ArrayList<>(builder.characterSet); } /** diff --git a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java index 9daea44b56..2352755789 100644 --- a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java +++ b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java @@ -23,13 +23,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import java.util.Arrays; import java.util.function.IntUnaryOperator; +import org.apache.commons.lang3.ArraySorter; import org.apache.commons.text.RandomStringGenerator.Builder; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; /** - * Tests for {@link RandomStringGenerator} + * Tests for {@link RandomStringGenerator}. */ class RandomStringGeneratorTest { @@ -159,6 +163,25 @@ void testNoPrivateCharacters() { } while (i < str.length()); } + @Test + void testPasswordExample() { + final char[] punctuation = ArraySorter + .sort(new char[] { '!', '"', '#', '$', '&', '\'', '(', ')', ',', '.', ':', ';', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~' }); + // @formatter:off + final RandomStringGenerator generator = RandomStringGenerator.builder() + .setAccumulate(true) + .withinRange('a', 'z') + .withinRange('A', 'Z') + .withinRange('0', '9') + .selectFrom(punctuation) + .get(); + // @formatter:on + final String randomText = generator.generate(10); + for (final char c : randomText.toCharArray()) { + assertTrue(Character.isLetter(c) || Character.isDigit(c) || Arrays.binarySearch(punctuation, c) >= 0); + } + } + @Test void testRemoveFilters() { final RandomStringGenerator.Builder builder = RandomStringGenerator.builder().withinRange('a', 'z').filteredBy(A_FILTER); @@ -194,17 +217,19 @@ void testSelectFromCharVarargs() { } } - @Test - void testSelectFromCharVarargs2() { + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void testSelectFromCharVarargs2(final boolean accumulate) { final String str = "abcde"; // @formatter:off final RandomStringGenerator generator = RandomStringGenerator.builder() + .setAccumulate(accumulate) .selectFrom() .selectFrom(null) .selectFrom('a', 'b') .selectFrom('a', 'b', 'c') .selectFrom('a', 'b', 'c', 'd') - .selectFrom('a', 'b', 'c', 'd', 'e') // only this last call matters + .selectFrom('a', 'b', 'c', 'd', 'e') // only this last call matters when accumulate is false .build(); // @formatter:on final String randomText = generator.generate(10); @@ -213,6 +238,27 @@ void testSelectFromCharVarargs2() { } } + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void testSelectFromCharVarargs3(final boolean accumulate) { + final String str = "abcde"; + // @formatter:off + final RandomStringGenerator generator = RandomStringGenerator.builder() + .setAccumulate(accumulate) + .selectFrom('a', 'b', 'c', 'd', 'e') + .selectFrom('a', 'b', 'c', 'd') + .selectFrom('a', 'b', 'c') + .selectFrom('a', 'b') + .selectFrom(null) + .selectFrom() + .get(); + // @formatter:on + final String randomText = generator.generate(10); + for (final char c : randomText.toCharArray()) { + assertEquals(accumulate, str.indexOf(c) != -1); + } + } + @Test void testSelectFromCharVarargSize1() { final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom('a').build(); From 49e02a5fae579a3c83c9bd8ecd1a37cc59d5fdc9 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 08:42:27 -0400 Subject: [PATCH 027/265] Use deprecated methods in specific method --- .../text/RandomStringGeneratorTest.java | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java index 2352755789..0a79af6a49 100644 --- a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java +++ b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java @@ -60,7 +60,7 @@ void testBadMinimumCodePoint() { } @Test - void testChangeOfFilter() { + void testBuildDeprecated() { final RandomStringGenerator.Builder builder = RandomStringGenerator.builder().withinRange('a', 'z').filteredBy(A_FILTER); final String str = builder.filteredBy(B_FILTER).build().generate(100); for (final char c : str.toCharArray()) { @@ -68,11 +68,20 @@ void testChangeOfFilter() { } } + @Test + void testChangeOfFilter() { + final RandomStringGenerator.Builder builder = RandomStringGenerator.builder().withinRange('a', 'z').filteredBy(A_FILTER); + final String str = builder.filteredBy(B_FILTER).get().generate(100); + for (final char c : str.toCharArray()) { + assertEquals('b', c); + } + } + @Test void testGenerateMinMaxLength() { final int minLength = 0; final int maxLength = 3; - final RandomStringGenerator generator = RandomStringGenerator.builder().build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().get(); final String str = generator.generate(minLength, maxLength); final int codePointLength = codePointLength(str); assertTrue(codePointLength >= minLength && codePointLength <= maxLength); @@ -81,7 +90,7 @@ void testGenerateMinMaxLength() { @Test void testGenerateMinMaxLengthInvalidLength() { assertThrowsExactly(IllegalArgumentException.class, () -> { - final RandomStringGenerator generator = RandomStringGenerator.builder().build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().get(); generator.generate(-1, 0); }); } @@ -89,7 +98,7 @@ void testGenerateMinMaxLengthInvalidLength() { @Test void testGenerateMinMaxLengthMinGreaterThanMax() { assertThrowsExactly(IllegalArgumentException.class, () -> { - final RandomStringGenerator generator = RandomStringGenerator.builder().build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().get(); generator.generate(1, 0); }); } @@ -100,19 +109,19 @@ void testGenerateTakingIntThrowsNullPointerException() { final RandomStringGenerator.Builder randomStringGeneratorBuilder = RandomStringGenerator.builder(); final CharacterPredicate[] characterPredicateArray = new CharacterPredicate[2]; randomStringGeneratorBuilder.filteredBy(characterPredicateArray); - final RandomStringGenerator randomStringGenerator = randomStringGeneratorBuilder.build(); + final RandomStringGenerator randomStringGenerator = randomStringGeneratorBuilder.get(); randomStringGenerator.generate(18); }); } @Test void testInvalidLength() { - assertThrowsExactly(IllegalArgumentException.class, () -> RandomStringGenerator.builder().build().generate(-1)); + assertThrowsExactly(IllegalArgumentException.class, () -> RandomStringGenerator.builder().get().generate(-1)); } @Test void testMultipleFilters() { - final String str = RandomStringGenerator.builder().withinRange('a', 'd').filteredBy(A_FILTER, B_FILTER).build().generate(5000); + final String str = RandomStringGenerator.builder().withinRange('a', 'd').filteredBy(A_FILTER, B_FILTER).get().generate(5000); boolean aFound = false; boolean bFound = false; for (final char c : str.toCharArray()) { @@ -130,7 +139,7 @@ void testMultipleFilters() { @Test void testNoLoneSurrogates() { final int length = 5000; - final String str = RandomStringGenerator.builder().build().generate(length); + final String str = RandomStringGenerator.builder().get().generate(length); char lastChar = str.charAt(0); for (int i = 1; i < str.length(); i++) { final char c = str.charAt(i); @@ -153,7 +162,7 @@ void testNoPrivateCharacters() { final int startOfPrivateBMPChars = 0xE000; // Request a string in an area of the Basic Multilingual Plane that is // largely occupied by private characters - final String str = RandomStringGenerator.builder().withinRange(startOfPrivateBMPChars, Character.MIN_SUPPLEMENTARY_CODE_POINT - 1).build() + final String str = RandomStringGenerator.builder().withinRange(startOfPrivateBMPChars, Character.MIN_SUPPLEMENTARY_CODE_POINT - 1).get() .generate(5000); int i = 0; do { @@ -186,7 +195,7 @@ void testPasswordExample() { void testRemoveFilters() { final RandomStringGenerator.Builder builder = RandomStringGenerator.builder().withinRange('a', 'z').filteredBy(A_FILTER); builder.filteredBy(); - final String str = builder.build().generate(100); + final String str = builder.get().generate(100); for (final char c : str.toCharArray()) { if (c != 'a') { // filter was successfully removed @@ -200,7 +209,7 @@ void testRemoveFilters() { void testSelectFromCharArray() { final String str = "abc"; final char[] charArray = str.toCharArray(); - final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom(charArray).build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom(charArray).get(); final String randomText = generator.generate(5); for (final char c : randomText.toCharArray()) { assertTrue(str.indexOf(c) != -1); @@ -210,7 +219,7 @@ void testSelectFromCharArray() { @Test void testSelectFromCharVarargs() { final String str = "abc"; - final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom('a', 'b', 'c').build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom('a', 'b', 'c').get(); final String randomText = generator.generate(5); for (final char c : randomText.toCharArray()) { assertTrue(str.indexOf(c) != -1); @@ -230,7 +239,7 @@ void testSelectFromCharVarargs2(final boolean accumulate) { .selectFrom('a', 'b', 'c') .selectFrom('a', 'b', 'c', 'd') .selectFrom('a', 'b', 'c', 'd', 'e') // only this last call matters when accumulate is false - .build(); + .get(); // @formatter:on final String randomText = generator.generate(10); for (final char c : randomText.toCharArray()) { @@ -261,7 +270,7 @@ void testSelectFromCharVarargs3(final boolean accumulate) { @Test void testSelectFromCharVarargSize1() { - final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom('a').build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom('a').get(); final String randomText = generator.generate(5); for (final char c : randomText.toCharArray()) { assertEquals('a', c); @@ -270,7 +279,7 @@ void testSelectFromCharVarargSize1() { @Test void testSelectFromEmptyCharVarargs() { - final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom().build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom().get(); final String randomText = generator.generate(5); for (final char c : randomText.toCharArray()) { assertTrue(c >= Character.MIN_CODE_POINT && c <= Character.MAX_CODE_POINT); @@ -280,7 +289,7 @@ void testSelectFromEmptyCharVarargs() { @Test void testSelectFromNullCharVarargs() { final int length = 5; - RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom(null).build(); + RandomStringGenerator generator = RandomStringGenerator.builder().selectFrom(null).get(); String randomText = generator.generate(length); assertEquals(length, codePointLength(randomText)); for (final char c : randomText.toCharArray()) { @@ -288,13 +297,13 @@ void testSelectFromNullCharVarargs() { } // final Builder builder = RandomStringGenerator.builder().selectFrom('a'); - generator = builder.build(); + generator = builder.get(); randomText = generator.generate(length); for (final char c : randomText.toCharArray()) { assertEquals('a', c); } // null input resets - generator = builder.selectFrom(null).build(); + generator = builder.selectFrom(null).get(); randomText = generator.generate(length); assertEquals(length, codePointLength(randomText)); for (final char c : randomText.toCharArray()) { @@ -305,7 +314,7 @@ void testSelectFromNullCharVarargs() { @Test void testSetLength() { final int length = 99; - final RandomStringGenerator generator = RandomStringGenerator.builder().build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().get(); final String str = generator.generate(length); assertEquals(length, codePointLength(str)); } @@ -314,7 +323,7 @@ void testSetLength() { void testUsingRandomIntUnaryOperator() { final char testChar = 'a'; final IntUnaryOperator testRandom = n -> testChar; - final String str = RandomStringGenerator.builder().usingRandom(testRandom).build().generate(10); + final String str = RandomStringGenerator.builder().usingRandom(testRandom).get().generate(10); for (final char c : str.toCharArray()) { assertEquals(testChar, c); } @@ -324,7 +333,7 @@ void testUsingRandomIntUnaryOperator() { void testUsingRandomTextRandomProvider() { final char testChar = 'a'; final TextRandomProvider testRandom = n -> testChar; - final String str = RandomStringGenerator.builder().usingRandom(testRandom).build().generate(10); + final String str = RandomStringGenerator.builder().usingRandom(testRandom).get().generate(10); for (final char c : str.toCharArray()) { assertEquals(testChar, c); } @@ -339,7 +348,7 @@ void testWithinMultipleRanges() { .withinRange() .withinRange((char[][]) null) .withinRange(pairs) - .build(); + .get(); // @formatter:on final String str = generator.generate(length); int minimumCodePoint = 0, maximumCodePoint = 0; @@ -360,7 +369,7 @@ void testWithinRange() { final int length = 5000; final int minimumCodePoint = 'a'; final int maximumCodePoint = 'z'; - final RandomStringGenerator generator = RandomStringGenerator.builder().withinRange(minimumCodePoint, maximumCodePoint).build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().withinRange(minimumCodePoint, maximumCodePoint).get(); final String str = generator.generate(length); int i = 0; do { @@ -372,7 +381,7 @@ void testWithinRange() { @Test void testZeroLength() { - final RandomStringGenerator generator = RandomStringGenerator.builder().build(); + final RandomStringGenerator generator = RandomStringGenerator.builder().get(); assertEquals("", generator.generate(0)); } } From aac7e010f9dc31101018414d716ddfb5b439f06d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 09:08:21 -0400 Subject: [PATCH 028/265] org.apache.commons.text.translate.LookupTranslator.LookupTranslator(Map CharSequence>) now throws NullPointerException instead of java.security.InvalidParameterException - Javadoc - Reduce vertical whitespace --- src/changes/changes.xml | 2 ++ .../text/translate/LookupTranslator.java | 23 ++++++------------- .../text/translate/LookupTranslatorTest.java | 3 +-- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 302829a057..bfd08972d2 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -56,6 +56,8 @@ The type attribute can be add,update,fix,remove. Fix PMD UnnecessaryFullyQualifiedName in AlphabetConverter. Fix PMD AvoidBranchingStatementAsLastInLoop in TextStringBuilder. Fix PMD AvoidBranchingStatementAsLastInLoop in StrBuilder. + org.apache.commons.text.translate.LookupTranslator.LookupTranslator(Map CharSequence>) now throws NullPointerException instead of java.security.InvalidParameterException. + Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. diff --git a/src/main/java/org/apache/commons/text/translate/LookupTranslator.java b/src/main/java/org/apache/commons/text/translate/LookupTranslator.java index 400c8d383c..005e36e446 100644 --- a/src/main/java/org/apache/commons/text/translate/LookupTranslator.java +++ b/src/main/java/org/apache/commons/text/translate/LookupTranslator.java @@ -14,14 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.text.translate; import java.io.IOException; import java.io.Writer; -import java.security.InvalidParameterException; import java.util.BitSet; import java.util.HashMap; import java.util.Map; +import java.util.Objects; /** * Translates a value using a lookup table. @@ -32,36 +33,27 @@ public class LookupTranslator extends CharSequenceTranslator { /** The mapping to be used in translation. */ private final Map lookupMap; - /** The first character of each key in the lookupMap. */ private final BitSet prefixSet; - /** The length of the shortest key in the lookupMap. */ private final int shortest; - /** The length of the longest key in the lookupMap. */ private final int longest; /** - * Constructs the lookup table to be used in translation + * Constructs the lookup table to be used in translation. * - * Note that, as of Lang 3.1 (the origin of this code), the key to the lookup - * table is converted to a java.lang.String. This is because we need the key - * to support hashCode and equals(Object), allowing it to be the key for a - * HashMap. See LANG-882. + * Note that, as of Lang 3.1 (the origin of this code), the key to the lookup table is converted to a java.lang.String. This is because we need the key to + * support hashCode and equals(Object), allowing it to be the key for a HashMap. See LANG-882. * - * @param lookupMap Map<CharSequence, CharSequence> table of translator - * mappings + * @param lookupMap Map<CharSequence, CharSequence> table of translator mappings, may not be null. */ public LookupTranslator(final Map lookupMap) { - if (lookupMap == null) { - throw new InvalidParameterException("lookupMap cannot be null"); - } + Objects.requireNonNull(lookupMap, "lookupMap"); this.lookupMap = new HashMap<>(); this.prefixSet = new BitSet(); int currentShortest = Integer.MAX_VALUE; int currentLongest = 0; - for (final Map.Entry pair : lookupMap.entrySet()) { this.lookupMap.put(pair.getKey().toString(), pair.getValue().toString()); this.prefixSet.set(pair.getKey().charAt(0)); @@ -92,7 +84,6 @@ public int translate(final CharSequence input, final int index, final Writer wri for (int i = max; i >= shortest; i--) { final CharSequence subSeq = input.subSequence(index, index + i); final String result = lookupMap.get(subSeq.toString()); - if (result != null) { writer.write(result); return Character.codePointCount(subSeq, 0, subSeq.length()); diff --git a/src/test/java/org/apache/commons/text/translate/LookupTranslatorTest.java b/src/test/java/org/apache/commons/text/translate/LookupTranslatorTest.java index 49281e0cde..11cc0bc2e2 100644 --- a/src/test/java/org/apache/commons/text/translate/LookupTranslatorTest.java +++ b/src/test/java/org/apache/commons/text/translate/LookupTranslatorTest.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.io.StringWriter; -import java.security.InvalidParameterException; import java.util.HashMap; import java.util.Map; @@ -46,7 +45,7 @@ void testBasicLookup() throws IOException { @Test void testFailsToCreateLookupTranslatorThrowsInvalidParameterException() { - assertThrowsExactly(InvalidParameterException.class, () -> new LookupTranslator(null)); + assertThrowsExactly(NullPointerException.class, () -> new LookupTranslator(null)); } // Tests: https://issues.apache.org/jira/browse/LANG-882 From 8b3f623e61e4eda5b9fd51f45fd7d36b30b66efb Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 09:11:04 -0400 Subject: [PATCH 029/265] Javadoc --- .../commons/text/similarity/LevenshteinDistance.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java index cbfbe6d099..553bd8d6cb 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java @@ -34,7 +34,7 @@ public class LevenshteinDistance implements EditDistance { /** - * Singleton instance. + * The singleton instance. */ private static final LevenshteinDistance INSTANCE = new LevenshteinDistance(); @@ -48,7 +48,7 @@ public static LevenshteinDistance getDefaultInstance() { } /** - * Find the Levenshtein distance between two CharSequences if it's less than or equal to a given threshold. + * Finds the Levenshtein distance between two CharSequences if it's less than or equal to a given threshold. * *

* This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance @@ -288,7 +288,7 @@ private static int unlimitedCompare(SimilarityInput left, SimilarityInput private final Integer threshold; /** - * This returns the default instance that uses a version of the algorithm that does not use a threshold parameter. + * Constructs a default instance that uses a version of the algorithm that does not use a threshold parameter. * * @see LevenshteinDistance#getDefaultInstance() * @deprecated Use {@link #getDefaultInstance()}. @@ -299,8 +299,8 @@ public LevenshteinDistance() { } /** - * If the threshold is not null, distance calculations will be limited to a maximum length. If the threshold is null, the unlimited version of the algorithm - * will be used. + * Constructs a new instance. If the threshold is not null, distance calculations will be limited to a maximum length. If the threshold is null, the + * unlimited version of the algorithm will be used. * * @param threshold If this is null then distances calculations will not be limited. This may not be negative. */ From 9fc3ee00bdef269de3d4785a4d2aecabe340d9f4 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 09:16:54 -0400 Subject: [PATCH 030/265] Javadoc --- .../org/apache/commons/text/similarity/LevenshteinDistance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java index 553bd8d6cb..01f3494cb1 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java @@ -392,7 +392,7 @@ public Integer apply(final SimilarityInput left, final SimilarityInput /** * Gets the distance threshold. * - * @return The distance threshold + * @return The distance threshold. */ public Integer getThreshold() { return threshold; From eb479f31be081cfe6a49706091549334705121a5 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 09:29:31 -0400 Subject: [PATCH 031/265] Javadoc --- .../apache/commons/text/similarity/LevenshteinDistance.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java index 01f3494cb1..ced4729771 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java @@ -19,7 +19,8 @@ import java.util.Arrays; /** - * An algorithm for measuring the difference between two character sequences. + * An algorithm for measuring the difference between two character sequences using the Levenshtein + * Distance. * *

* This is the number of changes needed to change one sequence into another, where each change is a single character modification (deletion, insertion or @@ -30,6 +31,8 @@ *

* * @since 1.0 + * @see Levenshtein Distance on Wikipedia + * @see Levenshtein Distance on NIST */ public class LevenshteinDistance implements EditDistance { From 4d26c2d7560e29d5e069f66728e8ecbaf414d79a Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 13:34:00 +0000 Subject: [PATCH 032/265] Prepare for the next release candidate --- README.md | 10 +-- RELEASE-NOTES.txt | 105 +++++++++++++++++--------------- src/changes/changes.xml | 2 +- src/site/xdoc/download_text.xml | 26 ++++---- 4 files changed, 76 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 7487c1f2a9..81333cf313 100644 --- a/README.md +++ b/README.md @@ -45,12 +45,12 @@ Apache Commons Text [![Java CI](https://github.com/apache/commons-text/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/commons-text/actions/workflows/maven.yml) [![Maven Central](https://img.shields.io/maven-central/v/org.apache.commons/commons-text?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.commons/commons-text) -[![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-text/1.13.1.svg)](https://javadoc.io/doc/org.apache.commons/commons-text/1.13.1) +[![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-text/1.14.0.svg)](https://javadoc.io/doc/org.apache.commons/commons-text/1.14.0) [![CodeQL](https://github.com/apache/commons-text/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/apache/commons-text/actions/workflows/codeql-analysis.yml) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/commons-text/badge)](https://api.securityscorecards.dev/projects/github.com/apache/commons-text) -Apache Commons Text is a set of utility functions and reusable components for the purpose of processing - and manipulating text that should be of use in a Java environment. +Apache Commons Text is a set of utility functions and reusable components for processing + and manipulating text in a Java environment. Documentation ------------- @@ -69,7 +69,7 @@ Alternatively, you can pull it from the central Maven repositories: org.apache.commons commons-text - 1.13.1 + 1.14.0 ``` @@ -91,7 +91,7 @@ There are some guidelines which will make applying PRs easier for us: + Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change. + Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running `mvn`. + Before you pushing a PR, run `mvn` (by itself), this runs the default goal, which contains all build checks. -+ To see the code coverage report, regardless of coverage failures, run `mvn clean site -Dcommons.jacoco.haltOnFailure=false` ++ To see the code coverage report, regardless of coverage failures, run `mvn clean site -Dcommons.jacoco.haltOnFailure=false -Pjacoco` If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas). You can learn more about contributing via GitHub in our [contribution guidelines](CONTRIBUTING.md). diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index fdec18aa43..f3e1471648 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -14,6 +14,63 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Apache Commons Text 1.14.0 Release Notes +------------------------------------------------ + +The Apache Commons Text team is pleased to announce the release of Apache Commons Text 1.14.0. + +Apache Commons Text is a set of utility functions and reusable components for processing +and manipulating text in a Java environment. + +Release 1.14.0. Requires Java 8 or above. + + +New features +------------ + +* Interface StringLookup now extends UnaryOperator. Thanks to Gary Gregory. +* Interface TextRandomProvider extends IntUnaryOperator. Thanks to Gary Gregory. +* Add RandomStringGenerator.Builder.usingRandom(IntUnaryOperator). Thanks to Gary Gregory. +* Add PMD check to default Maven goal. Thanks to Gary Gregory. +* Add org.apache.commons.text.RandomStringGenerator.Builder.setAccumulate(boolean). Thanks to Gary Gregory. + +Fixed Bugs +---------- + +* Fix PMD UnnecessaryFullyQualifiedName in StringLookupFactory. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in PropertiesStringLookup. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in JavaPlatformStringLookup. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in StringSubstitutor. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in StrSubstitutor. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in AlphabetConverter. Thanks to Gary Gregory. +* Fix PMD AvoidBranchingStatementAsLastInLoop in TextStringBuilder. Thanks to Gary Gregory. +* Fix PMD AvoidBranchingStatementAsLastInLoop in StrBuilder. Thanks to Gary Gregory. +* org.apache.commons.text.translate.LookupTranslator.LookupTranslator(Map CharSequence>) now throws NullPointerException instead of java.security.InvalidParameterException. Thanks to Gary Gregory. + +Changes +------- + +* Bump org.apache.commons:commons-parent from 81 to 85 #668. Thanks to Dependabot, Gary Gregory. +* Bump commons-io:commons-io from 2.18.0 to 2.20.0. Thanks to Gary Gregory. +* Bump graalvm.version from 24.2.0 to 24.2.2 #665, #681. Thanks to Dependabot, Gary Gregory. +* Bump commons.bytebuddy.version from 1.17.5 to 1.17.6 (#677). Thanks to Dependabot. +* Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #680. Thanks to Dependabot. + + +Historical list of changes: https://commons.apache.org/proper/commons-text/changes.html + +For complete information on Apache Commons Text, including instructions on how to submit bug reports, +patches, or suggestions for improvement, see the Apache Commons Text website: + +https://commons.apache.org/proper/commons-text + +Download page: https://commons.apache.org/proper/commons-text/download_text.cgi + +Have fun! +-Apache Commons Team + +----------------------------------------------------------------------------- Apache Commons Text 1.13.1 Release Notes ---------------------------------------- @@ -53,22 +110,6 @@ Have fun! ----------------------------------------------------------------------------- -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - -https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Apache Commons Text Version 1.13.0 Release Notes ------------------------------------------------ @@ -141,22 +182,6 @@ Have fun! ----------------------------------------------------------------------------- -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - -https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Apache Commons Text Version 1.12.0 Release Notes ------------------------------------------------ @@ -206,22 +231,6 @@ Have fun! ----------------------------------------------------------------------------- -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - -https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Apache Commons Text Version 1.11.0 Release Notes ------------------------------------------------ diff --git a/src/changes/changes.xml b/src/changes/changes.xml index bfd08972d2..5406a31766 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -45,7 +45,7 @@ The type attribute can be add,update,fix,remove. Apache Commons Text Changes - + Fix PMD UnnecessaryFullyQualifiedName in StringLookupFactory. Fix PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder. diff --git a/src/site/xdoc/download_text.xml b/src/site/xdoc/download_text.xml index c16a6f0265..12c6a1a08a 100644 --- a/src/site/xdoc/download_text.xml +++ b/src/site/xdoc/download_text.xml @@ -115,32 +115,32 @@ limitations under the License.

-
+
- - - + + + - - - + + +
commons-text-1.13.1-bin.tar.gzsha512pgpcommons-text-1.14.0-bin.tar.gzsha512pgp
commons-text-1.13.1-bin.zipsha512pgpcommons-text-1.14.0-bin.zipsha512pgp
- - - + + + - - - + + +
commons-text-1.13.1-src.tar.gzsha512pgpcommons-text-1.14.0-src.tar.gzsha512pgp
commons-text-1.13.1-src.zipsha512pgpcommons-text-1.14.0-src.zipsha512pgp
From e96010915ed1c1185b3b7f34dcd231a613c40144 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 13:35:37 +0000 Subject: [PATCH 033/265] Prepare for the release candidate 1.14.0 RC1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5e4ab7a622..c0e5b7e30d 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 85 commons-text - 1.14.0-SNAPSHOT + 1.14.0 Apache Commons Text Apache Commons Text is a set of utility functions and reusable components for processing and manipulating text in a Java environment. @@ -33,7 +33,7 @@ ISO-8859-1 UTF-8 - 2025-04-10T21:38:03Z + 2025-07-20T13:34:14Z 1.8 1.8 text From 3a9488e4fdb22963388a73467215d1f7c7e8c206 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 09:51:11 -0400 Subject: [PATCH 034/265] Fix Javadoc on Java 8 --- .../apache/commons/text/similarity/LevenshteinDistance.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java index ced4729771..3aad1d8d40 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java @@ -31,8 +31,8 @@ *

* * @since 1.0 - * @see Levenshtein Distance on Wikipedia - * @see Levenshtein Distance on NIST + * @see Levenshtein Distance on Wikipedia + * @see Levenshtein Distance on NIST */ public class LevenshteinDistance implements EditDistance { From 3d100309e422d4aa8a7f52415c440f523565e7f4 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:00:37 -0400 Subject: [PATCH 035/265] Javadoc --- .../commons/text/similarity/SimilarityScoreFrom.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java b/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java index 341f9d9d34..470bb713da 100644 --- a/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java +++ b/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java @@ -81,8 +81,8 @@ public SimilarityScoreFrom(final SimilarityScore similarityScore, final CharS * This compares "left" field against the "right" parameter * using the "similarity score" implementation. * - * @param right the second CharSequence - * @return The similarity score between two CharSequences + * @param right the second CharSequence. + * @return The similarity score between two CharSequences. */ public R apply(final CharSequence right) { return similarityScore.apply(left, right); @@ -91,7 +91,7 @@ public R apply(final CharSequence right) { /** * Gets the left parameter. * - * @return The left parameter + * @return The left parameter. */ public CharSequence getLeft() { return left; @@ -100,7 +100,7 @@ public CharSequence getLeft() { /** * Gets the edit distance. * - * @return The edit distance + * @return The edit distance. */ public SimilarityScore getSimilarityScore() { return similarityScore; From 4d585ce9b72cfcb33ccb04285c55915067f87d57 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:00:41 -0400 Subject: [PATCH 036/265] Javadoc --- .../java/org/apache/commons/text/similarity/RegexTokenizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/similarity/RegexTokenizer.java b/src/main/java/org/apache/commons/text/similarity/RegexTokenizer.java index b633d7867f..e566cbaf85 100644 --- a/src/main/java/org/apache/commons/text/similarity/RegexTokenizer.java +++ b/src/main/java/org/apache/commons/text/similarity/RegexTokenizer.java @@ -47,7 +47,7 @@ final class RegexTokenizer implements CharSequenceTokenizer { /** * {@inheritDoc} * - * @throws IllegalArgumentException if the input text is blank + * @throws IllegalArgumentException if the input text is blank. */ @Override public CharSequence[] apply(final CharSequence text) { From a43c1378a6a58b6d8ed9a8b1e0de9db9e890a3ee Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:00:44 -0400 Subject: [PATCH 037/265] Javadoc --- .../LongestCommonSubsequenceDistance.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequenceDistance.java b/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequenceDistance.java index f6ce1e53f5..ed33437ac2 100644 --- a/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequenceDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequenceDistance.java @@ -44,15 +44,14 @@ public LongestCommonSubsequenceDistance() { } /** - * Calculates an edit distance between two {@code CharSequence}'s {@code left} and - * {@code right} as: {@code left.length() + right.length() - 2 * LCS(left, right)}, where - * {@code LCS} is given in {@link LongestCommonSubsequence#apply(CharSequence, CharSequence)}. + * Calculates an edit distance between two {@code CharSequence}'s {@code left} and {@code right} as: + * {@code left.length() + right.length() - 2 * LCS(left, right)}, where {@code LCS} is given in + * {@link LongestCommonSubsequence#apply(CharSequence, CharSequence)}. * - * @param left first character sequence - * @param right second character sequence - * @return distance - * @throws IllegalArgumentException - * if either String input {@code null} + * @param left first character sequence. + * @param right second character sequence. + * @return distance. + * @throws IllegalArgumentException if either String input {@code null}. */ @Override public Integer apply(final CharSequence left, final CharSequence right) { From 0f08e877a9fa83e5a3de3ecfcf1ddbe45df7e5a5 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:00:54 -0400 Subject: [PATCH 038/265] Javadoc --- .../similarity/LongestCommonSubsequence.java | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java b/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java index 86288d4872..04ec48e911 100644 --- a/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java +++ b/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java @@ -65,7 +65,7 @@ public class LongestCommonSubsequence implements SimilarityScore { * * @param left first input sequence. * @param right second input sequence. - * @return last row of the dynamic-programming (DP) table for calculating the LCS of {@code left} and {@code right} + * @return last row of the dynamic-programming (DP) table for calculating the LCS of {@code left} and {@code right}. * @since 1.10.0 */ private static int[] algorithmB(final CharSequence left, final CharSequence right) { @@ -104,7 +104,7 @@ private static int[] algorithmB(final CharSequence left, final CharSequence righ * * @param left first input sequence. * @param right second input sequence. - * @return the LCS of {@code left} and {@code right} + * @return the LCS of {@code left} and {@code right}. * @since 1.10.0 */ private static String algorithmC(final CharSequence left, final CharSequence right) { @@ -144,7 +144,9 @@ private static String algorithmC(final CharSequence left, final CharSequence rig return out.toString(); } - // An auxiliary method for CharSequence reversal + /* + * A method for CharSequence reversal. + */ private static String reverse(final CharSequence s) { return new StringBuilder(s).reverse().toString(); } @@ -170,10 +172,10 @@ public LongestCommonSubsequence() { * An evaluation using JMH revealed that this method is almost two times faster than its previous version. *

* - * @param left first character sequence - * @param right second character sequence - * @return length of the longest common subsequence of {@code left} and {@code right} - * @throws IllegalArgumentException if either String input {@code null} + * @param left first character sequence. + * @param right second character sequence. + * @return length of the longest common subsequence of {@code left} and {@code right}. + * @throws IllegalArgumentException if either String input {@code null}. */ @Override public Integer apply(final CharSequence left, final CharSequence right) { @@ -211,10 +213,10 @@ public Integer apply(final CharSequence left, final CharSequence right) { * elements. *

* - * @param left first character sequence - * @param right second character sequence - * @return the longest common subsequence found - * @throws IllegalArgumentException if either String input {@code null} + * @param left first character sequence. + * @param right second character sequence. + * @return the longest common subsequence found. + * @throws IllegalArgumentException if either String input {@code null}. * @deprecated Deprecated as of 1.2 due to a typo in the method name. * Use {@link #longestCommonSubsequence(CharSequence, CharSequence)} instead. * This method will be removed in 2.0. @@ -247,10 +249,10 @@ public CharSequence logestCommonSubsequence(final CharSequence left, final CharS * elements. *

* - * @param left first character sequence - * @param right second character sequence - * @return the longest common subsequence found - * @throws IllegalArgumentException if either String input {@code null} + * @param left first character sequence. + * @param right second character sequence. + * @return the longest common subsequence found. + * @throws IllegalArgumentException if either String input {@code null}. * @since 1.2 */ public CharSequence longestCommonSubsequence(final CharSequence left, final CharSequence right) { @@ -279,9 +281,9 @@ public CharSequence longestCommonSubsequence(final CharSequence left, final Char * dynamic programming portion of the algorithm, and is the reason for the runtime complexity being * O(m*n), where m=left.length() and n=right.length(). * - * @param left first character sequence - * @param right second character sequence - * @return lcsLengthArray + * @param left first character sequence. + * @param right second character sequence. + * @return longest common substring length array. * @deprecated Deprecated as of 1.10. A more efficient implementation for calculating LCS is now available. * Use {@link #longestCommonSubsequence(CharSequence, CharSequence)} instead to directly calculate the LCS. * This method will be removed in 2.0. From 38a7ae8d751c20e1f4055ebe15a649f003050bcb Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:00:57 -0400 Subject: [PATCH 039/265] Javadoc --- .../text/similarity/LevenshteinResults.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinResults.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinResults.java index 796019077d..37b547798b 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinResults.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinResults.java @@ -54,9 +54,9 @@ public class LevenshteinResults { * Constructs the results for a detailed Levenshtein distance. * * @param distance distance between two character sequences. - * @param insertCount insert character count - * @param deleteCount delete character count - * @param substituteCount substitute character count + * @param insertCount insert character count. + * @param deleteCount delete character count. + * @param substituteCount substitute character count. */ public LevenshteinResults(final Integer distance, final Integer insertCount, final Integer deleteCount, final Integer substituteCount) { @@ -83,7 +83,7 @@ public boolean equals(final Object o) { /** * Gets the number of character deletion needed to change one character sequence to other. * - * @return delete character count + * @return delete character count. */ public Integer getDeleteCount() { return deleteCount; @@ -92,7 +92,7 @@ public Integer getDeleteCount() { /** * Gets the distance between two character sequences. * - * @return distance between two character sequence + * @return distance between two character sequence. */ public Integer getDistance() { return distance; @@ -101,7 +101,7 @@ public Integer getDistance() { /** * Gets the number of insertion needed to change one character sequence into another. * - * @return insert character count + * @return insert character count. */ public Integer getInsertCount() { return insertCount; @@ -110,7 +110,7 @@ public Integer getInsertCount() { /** * Gets the number of character substitution needed to change one character sequence into another. * - * @return substitute character count + * @return substitute character count. */ public Integer getSubstituteCount() { return substituteCount; From 90eb6293905066fd1e26c3768c4e88c2ccab8b1c Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:00 -0400 Subject: [PATCH 040/265] Javadoc --- .../text/similarity/LevenshteinDistance.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java index 3aad1d8d40..787279c6ab 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java @@ -44,7 +44,7 @@ public class LevenshteinDistance implements EditDistance { /** * Gets the default instance. * - * @return The default instance + * @return The default instance. */ public static LevenshteinDistance getDefaultInstance() { return INSTANCE; @@ -72,9 +72,9 @@ public static LevenshteinDistance getDefaultInstance() { * limitedCompare("hippo", "elephant", 6) = -1 * * - * @param left the first SimilarityInput, must not be null - * @param right the second SimilarityInput, must not be null - * @param threshold the target threshold, must not be negative + * @param left the first SimilarityInput, must not be null. + * @param right the second SimilarityInput, must not be null. + * @param threshold the target threshold, must not be negative. * @return result distance, or -1 */ private static int limitedCompare(SimilarityInput left, SimilarityInput right, final int threshold) { // NOPMD @@ -229,10 +229,10 @@ private static int limitedCompare(SimilarityInput left, SimilarityInput * - * @param left the first CharSequence, must not be null - * @param right the second CharSequence, must not be null - * @return result distance, or -1 - * @throws IllegalArgumentException if either CharSequence input is {@code null} + * @param left the first CharSequence, must not be null. + * @param right the second CharSequence, must not be null. + * @return result distance, or -1. + * @throws IllegalArgumentException if either CharSequence input is {@code null}. */ private static int unlimitedCompare(SimilarityInput left, SimilarityInput right) { if (left == null || right == null) { @@ -347,10 +347,10 @@ public LevenshteinDistance(final Integer threshold) { * distance.apply("hello", "hallo") = 1 * * - * @param left the first input, must not be null - * @param right the second input, must not be null - * @return result distance, or -1 - * @throws IllegalArgumentException if either String input {@code null} + * @param left the first input, must not be null. + * @param right the second input, must not be null. + * @return result distance, or -1. + * @throws IllegalArgumentException if either String input {@code null}. */ @Override public Integer apply(final CharSequence left, final CharSequence right) { From a28b9fa39bf83b6e1499493210eb8288a35dba1b Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:03 -0400 Subject: [PATCH 041/265] Javadoc --- .../LevenshteinDetailedDistance.java | 275 +++++++----------- 1 file changed, 110 insertions(+), 165 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java index 0e241efd5f..78505991f9 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.text.similarity; import java.util.Arrays; @@ -22,9 +23,8 @@ * An algorithm for measuring the difference between two character sequences. * *

- * This is the number of changes needed to change one sequence into another, - * where each change is a single character modification (deletion, insertion - * or substitution). + * This is the number of changes needed to change one sequence into another, where each change is a single character modification (deletion, insertion or + * substitution). *

* * @since 1.0 @@ -37,39 +37,29 @@ public class LevenshteinDetailedDistance implements EditDistance The type of similarity score unit. - * @param left character sequence which need to be converted from - * @param right character sequence which need to be converted to - * @param matrix two dimensional array containing - * @param swapped tells whether the value for left character sequence and right - * character sequence were swapped to save memory - * @return result object containing the count of insert, delete and substitute and total count needed + * @param The type of similarity score unit. + * @param left character sequence which need to be converted from. + * @param right character sequence which need to be converted to. + * @param matrix two dimensional array containing. + * @param swapped tells whether the value for left character sequence and right character sequence were swapped to save memory. + * @return result object containing the count of insert, delete and substitute and total count needed. */ - private static LevenshteinResults findDetailedResults(final SimilarityInput left, - final SimilarityInput right, - final int[][] matrix, - final boolean swapped) { - + private static LevenshteinResults findDetailedResults(final SimilarityInput left, final SimilarityInput right, final int[][] matrix, + final boolean swapped) { int delCount = 0; int addCount = 0; int subCount = 0; - int rowIndex = right.length(); int columnIndex = left.length(); - int dataAtLeft = 0; int dataAtTop = 0; int dataAtDiagonal = 0; int data = 0; boolean deleted = false; boolean added = false; - while (rowIndex >= 0 && columnIndex >= 0) { - if (columnIndex == 0) { dataAtLeft = -1; } else { @@ -89,7 +79,6 @@ private static LevenshteinResults findDetailedResults(final SimilarityInput< break; } data = matrix[rowIndex][columnIndex]; - // case in which the character at left and right are the same, // in this case none of the counters will be incremented. if (columnIndex > 0 && rowIndex > 0 && left.at(columnIndex - 1).equals(right.at(rowIndex - 1))) { @@ -97,12 +86,10 @@ private static LevenshteinResults findDetailedResults(final SimilarityInput< rowIndex--; continue; } - // handling insert and delete cases. deleted = false; added = false; - if (data - 1 == dataAtLeft && data <= dataAtDiagonal && data <= dataAtTop - || dataAtDiagonal == -1 && dataAtTop == -1) { // NOPMD + if (data - 1 == dataAtLeft && data <= dataAtDiagonal && data <= dataAtTop || dataAtDiagonal == -1 && dataAtTop == -1) { // NOPMD columnIndex--; if (swapped) { addCount++; @@ -111,8 +98,7 @@ private static LevenshteinResults findDetailedResults(final SimilarityInput< delCount++; deleted = true; } - } else if (data - 1 == dataAtTop && data <= dataAtDiagonal && data <= dataAtLeft - || dataAtDiagonal == -1 && dataAtLeft == -1) { // NOPMD + } else if (data - 1 == dataAtTop && data <= dataAtDiagonal && data <= dataAtLeft || dataAtDiagonal == -1 && dataAtLeft == -1) { // NOPMD rowIndex--; if (swapped) { delCount++; @@ -122,7 +108,6 @@ private static LevenshteinResults findDetailedResults(final SimilarityInput< added = true; } } - // substituted case if (!added && !deleted) { subCount++; @@ -143,15 +128,11 @@ public static LevenshteinDetailedDistance getDefaultInstance() { } /** - * Finds the Levenshtein distance between two CharSequences if it's less than or - * equal to a given threshold. + * Finds the Levenshtein distance between two CharSequences if it's less than or equal to a given threshold. * *

- * This implementation follows from Algorithms on Strings, Trees and - * Sequences by Dan Gusfield and Chas Emerick's implementation of the - * Levenshtein distance algorithm from http://www.merriampark.com/ld.htm + * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance + * algorithm from http://www.merriampark.com/ld.htm *

* *
@@ -168,73 +149,46 @@ public static LevenshteinDetailedDistance getDefaultInstance() {
      * limitedCompare("hippo", "elephant", 6) = -1
      * 
* - * @param The type of similarity score unit. - * @param left the first CharSequence, must not be null - * @param right the second CharSequence, must not be null - * @param threshold the target threshold, must not be negative - * @return result distance, or -1 + * @param The type of similarity score unit. + * @param left the first CharSequence, must not be null. + * @param right the second CharSequence, must not be null. + * @param threshold the target threshold, must not be negative. + * @return result distance, or -1. */ - private static LevenshteinResults limitedCompare(SimilarityInput left, SimilarityInput right, final int threshold) { //NOPMD + private static LevenshteinResults limitedCompare(SimilarityInput left, SimilarityInput right, final int threshold) { // NOPMD if (left == null || right == null) { throw new IllegalArgumentException("CharSequences must not be null"); } if (threshold < 0) { throw new IllegalArgumentException("Threshold must not be negative"); } - /* - * This implementation only computes the distance if it's less than or - * equal to the threshold value, returning -1 if it's greater. The - * advantage is performance: unbounded distance is O(nm), but a bound of - * k allows us to reduce it to O(km) time by only computing a diagonal - * stripe of width 2k + 1 of the cost table. It is also possible to use - * this to compute the unbounded Levenshtein distance by starting the - * threshold at 1 and doubling each time until the distance is found; - * this is O(dm), where d is the distance. + * This implementation only computes the distance if it's less than or equal to the threshold value, returning -1 if it's greater. The advantage is + * performance: unbounded distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only computing a diagonal stripe of width 2k + 1 + * of the cost table. It is also possible to use this to compute the unbounded Levenshtein distance by starting the threshold at 1 and doubling each + * time until the distance is found; this is O(dm), where d is the distance. * - * One subtlety comes from needing to ignore entries on the border of - * our stripe eg. p[] = |#|#|#|* d[] = *|#|#|#| We must ignore the entry - * to the left of the leftmost member We must ignore the entry above the - * rightmost member + * One subtlety comes from needing to ignore entries on the border of our stripe eg. p[] = |#|#|#|* d[] = *|#|#|#| We must ignore the entry to the left + * of the leftmost member We must ignore the entry above the rightmost member * - * Another subtlety comes from our stripe running off the matrix if the - * strings aren't of the same size. Since string s is always swapped to - * be the shorter of the two, the stripe will always run off to the - * upper right instead of the lower left of the matrix. + * Another subtlety comes from our stripe running off the matrix if the strings aren't of the same size. Since string s is always swapped to be the + * shorter of the two, the stripe will always run off to the upper right instead of the lower left of the matrix. * - * As a concrete example, suppose s is of length 5, t is of length 7, - * and our threshold is 1. In this case we're going to walk a stripe of - * length 3. The matrix would look like so: + * As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. In this case we're going to walk a stripe of length 3. The + * matrix would look like so: * - *
-         *    1 2 3 4 5
-         * 1 |#|#| | | |
-         * 2 |#|#|#| | |
-         * 3 | |#|#|#| |
-         * 4 | | |#|#|#|
-         * 5 | | | |#|#|
-         * 6 | | | | |#|
-         * 7 | | | | | |
-         * 
+ *
 1 2 3 4 5 1 |#|#| | | | 2 |#|#|#| | | 3 | |#|#|#| | 4 | | |#|#|#| 5 | | | |#|#| 6 | | | | |#| 7 | | | | | | 
* - * Note how the stripe leads off the table as there is no possible way - * to turn a string of length 5 into one of length 7 in edit distance of - * 1. + * Note how the stripe leads off the table as there is no possible way to turn a string of length 5 into one of length 7 in edit distance of 1. * - * Additionally, this implementation decreases memory usage by using two - * single-dimensional arrays and swapping them back and forth instead of - * allocating an entire n by m matrix. This requires a few minor - * changes, such as immediately returning when it's detected that the - * stripe has run off the matrix and initially filling the arrays with - * large values so that entries we don't compute are ignored. + * Additionally, this implementation decreases memory usage by using two single-dimensional arrays and swapping them back and forth instead of + * allocating an entire n by m matrix. This requires a few minor changes, such as immediately returning when it's detected that the stripe has run off + * the matrix and initially filling the arrays with large values so that entries we don't compute are ignored. * - * See Algorithms on Strings, Trees and Sequences by Dan Gusfield for - * some discussion. + * See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. */ - int n = left.length(); // length of left int m = right.length(); // length of right - // if one string is empty, the edit distance is necessarily the length of the other if (n == 0) { return m <= threshold ? new LevenshteinResults(m, m, 0, 0) : new LevenshteinResults(-1, 0, 0, 0); @@ -242,7 +196,6 @@ private static LevenshteinResults limitedCompare(SimilarityInput left, Si if (m == 0) { return n <= threshold ? new LevenshteinResults(n, 0, n, 0) : new LevenshteinResults(-1, 0, 0, 0); } - boolean swapped = false; if (n > m) { // swap the two strings to consume less memory @@ -253,20 +206,17 @@ private static LevenshteinResults limitedCompare(SimilarityInput left, Si m = right.length(); swapped = true; } - int[] p = new int[n + 1]; // 'previous' cost array, horizontally int[] d = new int[n + 1]; // cost array, horizontally int[] tempD; // placeholder to assist in swapping p and d final int[][] matrix = new int[m + 1][n + 1]; - - //filling the first row and first column values in the matrix + // filling the first row and first column values in the matrix for (int index = 0; index <= n; index++) { matrix[0][index] = index; } for (int index = 0; index <= m; index++) { matrix[index][0] = index; } - // fill in starting table values final int boundary = Math.min(n, threshold) + 1; for (int i = 0; i < boundary; i++) { @@ -276,27 +226,21 @@ private static LevenshteinResults limitedCompare(SimilarityInput left, Si // stripe will be ignored in following loop iterations Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); Arrays.fill(d, Integer.MAX_VALUE); - // iterates through t for (int j = 1; j <= m; j++) { final E rightJ = right.at(j - 1); // jth character of right d[0] = j; - // compute stripe indices, constrain to array size final int min = Math.max(1, j - threshold); - final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min( - n, j + threshold); - + final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); // the stripe may lead off of the table if s and t are of different sizes if (min > max) { return new LevenshteinResults(-1, 0, 0, 0); } - // ignore entry left of leftmost if (min > 1) { d[min - 1] = Integer.MAX_VALUE; } - // iterates through [min, max] in s for (int i = min; i <= max; i++) { if (left.at(i - 1).equals(rightJ)) { @@ -308,13 +252,11 @@ private static LevenshteinResults limitedCompare(SimilarityInput left, Si } matrix[j][i] = d[i]; } - // copy current distance counts to 'previous row' distance counts tempD = p; p = d; d = tempD; } - // if p[n] is greater than the threshold, there's no guarantee on it being the correct distance if (p[n] <= threshold) { return findDetailedResults(left, right, matrix, swapped); @@ -325,15 +267,21 @@ private static LevenshteinResults limitedCompare(SimilarityInput left, Si /** * Finds the Levenshtein distance between two Strings. * - *

A higher score indicates a greater distance.

+ *

+ * A higher score indicates a greater distance. + *

* - *

The previous implementation of the Levenshtein distance algorithm - * was from http://www.merriampark.com/ld.htm

+ *

+ * The previous implementation of the Levenshtein distance algorithm was from + * http://www.merriampark.com/ld.htm + *

* - *

Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError - * which can occur when my Java implementation is used with very large strings.
- * This implementation of the Levenshtein distance algorithm - * is from http://www.merriampark.com/ldjava.htm

+ *

+ * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large + * strings.
+ * This implementation of the Levenshtein distance algorithm is from + * http://www.merriampark.com/ldjava.htm + *

* *
      * unlimitedCompare(null, *)             = IllegalArgumentException
@@ -349,37 +297,29 @@ private static  LevenshteinResults limitedCompare(SimilarityInput left, Si
      * unlimitedCompare("hello", "hallo")    = 1
      * 
* - * @param The type of similarity score unit. - * @param left the first CharSequence, must not be null - * @param right the second CharSequence, must not be null - * @return result distance, or -1 - * @throws IllegalArgumentException if either CharSequence input is {@code null} + * @param The type of similarity score unit. + * @param left the first CharSequence, must not be null. + * @param right the second CharSequence, must not be null. + * @return result distance, or -1. + * @throws IllegalArgumentException if either CharSequence input is {@code null}. */ private static LevenshteinResults unlimitedCompare(SimilarityInput left, SimilarityInput right) { if (left == null || right == null) { throw new IllegalArgumentException("CharSequences must not be null"); } - /* - The difference between this impl. and the previous is that, rather - than creating and retaining a matrix of size s.length() + 1 by t.length() + 1, - we maintain two single-dimensional arrays of length s.length() + 1. The first, d, - is the 'current working' distance array that maintains the newest distance cost - counts as we iterate through the characters of String s. Each time we increment - the index of String t we are comparing, d is copied to p, the second int[]. Doing so - allows us to retain the previous cost counts as required by the algorithm (taking - the minimum of the cost count to the left, up one, and diagonally up and to the left - of the current cost count being calculated). (Note that the arrays aren't really - copied anymore, just switched...this is clearly much better than cloning an array - or doing a System.arraycopy() each time through the outer loop.) - - Effectively, the difference between the two implementations is this one does not - cause an out of memory condition when calculating the LD over two very large strings. + * The difference between this impl. and the previous is that, rather than creating and retaining a matrix of size s.length() + 1 by t.length() + 1, we + * maintain two single-dimensional arrays of length s.length() + 1. The first, d, is the 'current working' distance array that maintains the newest + * distance cost counts as we iterate through the characters of String s. Each time we increment the index of String t we are comparing, d is copied to + * p, the second int[]. Doing so allows us to retain the previous cost counts as required by the algorithm (taking the minimum of the cost count to the + * left, up one, and diagonally up and to the left of the current cost count being calculated). (Note that the arrays aren't really copied anymore, just + * switched...this is clearly much better than cloning an array or doing a System.arraycopy() each time through the outer loop.) + * + * Effectively, the difference between the two implementations is this one does not cause an out of memory condition when calculating the LD over two + * very large strings. */ - int n = left.length(); // length of left int m = right.length(); // length of right - if (n == 0) { return new LevenshteinResults(m, m, 0, 0); } @@ -396,12 +336,10 @@ allows us to retain the previous cost counts as required by the algorithm (takin m = right.length(); swapped = true; } - int[] p = new int[n + 1]; // 'previous' cost array, horizontally int[] d = new int[n + 1]; // cost array, horizontally - int[] tempD; //placeholder to assist in swapping p and d + int[] tempD; // placeholder to assist in swapping p and d final int[][] matrix = new int[m + 1][n + 1]; - // filling the first row and first column values in the matrix for (int index = 0; index <= n; index++) { matrix[0][index] = index; @@ -409,30 +347,24 @@ allows us to retain the previous cost counts as required by the algorithm (takin for (int index = 0; index <= m; index++) { matrix[index][0] = index; } - // indexes into strings left and right int i; // iterates through left int j; // iterates through right - E rightJ; // jth character of right - int cost; // cost for (i = 0; i <= n; i++) { p[i] = i; } - for (j = 1; j <= m; j++) { rightJ = right.at(j - 1); d[0] = j; - for (i = 1; i <= n; i++) { cost = left.at(i - 1).equals(rightJ) ? 0 : 1; // minimum of cell to the left+1, to the top+1, diagonally left and up +cost d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost); - //filling the matrix + // filling the matrix matrix[j][i] = d[i]; } - // copy current distance counts to 'previous row' distance counts tempD = p; p = d; @@ -448,8 +380,7 @@ allows us to retain the previous cost counts as required by the algorithm (takin /** *

- * This returns the default instance that uses a version - * of the algorithm that does not use a threshold parameter. + * This returns the default instance that uses a version of the algorithm that does not use a threshold parameter. *

* * @see LevenshteinDetailedDistance#getDefaultInstance() @@ -463,7 +394,9 @@ public LevenshteinDetailedDistance() { /** * If the threshold is not null, distance calculations will be limited to a maximum length. * - *

If the threshold is null, the unlimited version of the algorithm will be used.

+ *

+ * If the threshold is null, the unlimited version of the algorithm will be used. + *

* * @param threshold If this is null then distances calculations will not be limited. This may not be negative. */ @@ -477,15 +410,21 @@ public LevenshteinDetailedDistance(final Integer threshold) { /** * Computes the Levenshtein distance between two Strings. * - *

A higher score indicates a greater distance.

+ *

+ * A higher score indicates a greater distance. + *

* - *

The previous implementation of the Levenshtein distance algorithm - * was from http://www.merriampark.com/ld.htm

+ *

+ * The previous implementation of the Levenshtein distance algorithm was from + * http://www.merriampark.com/ld.htm + *

* - *

Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError - * which can occur when my Java implementation is used with very large strings.
- * This implementation of the Levenshtein distance algorithm - * is from http://www.merriampark.com/ldjava.htm

+ *

+ * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large + * strings.
+ * This implementation of the Levenshtein distance algorithm is from + * http://www.merriampark.com/ldjava.htm + *

* *
      * distance.apply(null, *)             = IllegalArgumentException
@@ -501,10 +440,10 @@ public LevenshteinDetailedDistance(final Integer threshold) {
      * distance.apply("hello", "hallo")    = 1
      * 
* - * @param left the first input, must not be null - * @param right the second input, must not be null - * @return result distance, or -1 - * @throws IllegalArgumentException if either String input {@code null} + * @param left the first input, must not be null. + * @param right the second input, must not be null. + * @return result distance, or -1. + * @throws IllegalArgumentException if either String input {@code null}. */ @Override public LevenshteinResults apply(final CharSequence left, final CharSequence right) { @@ -514,15 +453,21 @@ public LevenshteinResults apply(final CharSequence left, final CharSequence righ /** * Computes the Levenshtein distance between two Strings. * - *

A higher score indicates a greater distance.

+ *

+ * A higher score indicates a greater distance. + *

* - *

The previous implementation of the Levenshtein distance algorithm - * was from http://www.merriampark.com/ld.htm

+ *

+ * The previous implementation of the Levenshtein distance algorithm was from + * http://www.merriampark.com/ld.htm + *

* - *

Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError - * which can occur when my Java implementation is used with very large strings.
- * This implementation of the Levenshtein distance algorithm - * is from http://www.merriampark.com/ldjava.htm

+ *

+ * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large + * strings.
+ * This implementation of the Levenshtein distance algorithm is from + * http://www.merriampark.com/ldjava.htm + *

* *
      * distance.apply(null, *)             = IllegalArgumentException
@@ -538,11 +483,11 @@ public LevenshteinResults apply(final CharSequence left, final CharSequence righ
      * distance.apply("hello", "hallo")    = 1
      * 
* - * @param The type of similarity score unit. - * @param left the first input, must not be null - * @param right the second input, must not be null - * @return result distance, or -1 - * @throws IllegalArgumentException if either String input {@code null} + * @param The type of similarity score unit. + * @param left the first input, must not be null. + * @param right the second input, must not be null. + * @return result distance, or -1. + * @throws IllegalArgumentException if either String input {@code null}. * @since 1.13.0 */ public LevenshteinResults apply(final SimilarityInput left, final SimilarityInput right) { @@ -555,7 +500,7 @@ public LevenshteinResults apply(final SimilarityInput left, final Similar /** * Gets the distance threshold. * - * @return The distance threshold + * @return The distance threshold. */ public Integer getThreshold() { return threshold; From bd008ff5e5f852e6979c9b5800f24f6a2db0e530 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:08 -0400 Subject: [PATCH 042/265] Javadoc --- .../org/apache/commons/text/similarity/JaroWinklerDistance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java b/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java index f15549878f..5564b07b4e 100644 --- a/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java @@ -81,7 +81,7 @@ public JaroWinklerDistance() { * @param left the first input, must not be null. * @param right the second input, must not be null. * @return result distance. - * @throws IllegalArgumentException if either CharSequence input is {@code null} + * @throws IllegalArgumentException if either CharSequence input is {@code null}. */ @Override public Double apply(final CharSequence left, final CharSequence right) { From 4f9ac340d2a5bc67f7f722cfdde820c411102913 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:11 -0400 Subject: [PATCH 043/265] Javadoc --- .../org/apache/commons/text/similarity/JaccardSimilarity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/JaccardSimilarity.java b/src/main/java/org/apache/commons/text/similarity/JaccardSimilarity.java index 2630728a78..c5291486e0 100644 --- a/src/main/java/org/apache/commons/text/similarity/JaccardSimilarity.java +++ b/src/main/java/org/apache/commons/text/similarity/JaccardSimilarity.java @@ -48,7 +48,7 @@ public JaccardSimilarity() { * * @param left first input sequence. * @param right second input sequence. - * @return index. + * @return The Jaccard Similarity of two set character sequence passed as input. * @throws IllegalArgumentException if either String input {@code null}. */ @Override @@ -63,7 +63,7 @@ public Double apply(final CharSequence left, final CharSequence right) { * @param The type of similarity score unit. * @param left first input sequence. * @param right second input sequence. - * @return index. + * @return The Jaccard Similarity of two set character sequence passed as input. * @since 1.13.0 */ public Double apply(final SimilarityInput left, final SimilarityInput right) { From 1d7b5caeadeeff3329cce283411876fa92315d25 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:14 -0400 Subject: [PATCH 044/265] Javadoc --- .../org/apache/commons/text/similarity/JaccardDistance.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/JaccardDistance.java b/src/main/java/org/apache/commons/text/similarity/JaccardDistance.java index 51c64f4e65..d2042e0659 100644 --- a/src/main/java/org/apache/commons/text/similarity/JaccardDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/JaccardDistance.java @@ -40,7 +40,7 @@ public JaccardDistance() { * * @param left first input sequence. * @param right second input sequence. - * @return index + * @return The Jaccard distance. * @throws IllegalArgumentException if either String input {@code null}. */ @Override @@ -54,7 +54,7 @@ public Double apply(final CharSequence left, final CharSequence right) { * @param The type of similarity score unit. * @param left first input sequence. * @param right second input sequence. - * @return index + * @return index. * @throws IllegalArgumentException if either String input {@code null}. */ public Double apply(final SimilarityInput left, final SimilarityInput right) { From a1f3288ac72897d511b04734eb82bbae121bf0d2 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:18 -0400 Subject: [PATCH 045/265] Javadoc --- .../similarity/IntersectionSimilarity.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/IntersectionSimilarity.java b/src/main/java/org/apache/commons/text/similarity/IntersectionSimilarity.java index 71a31a0094..370b00a296 100644 --- a/src/main/java/org/apache/commons/text/similarity/IntersectionSimilarity.java +++ b/src/main/java/org/apache/commons/text/similarity/IntersectionSimilarity.java @@ -82,7 +82,7 @@ private TinyBag(final int initialCapacity) { /** * Adds a new element to the bag, incrementing its count in the underlying map. * - * @param object the object to add + * @param object the object to add. */ private void add(final T object) { map.computeIfAbsent(object, k -> new BagCount()).count++; @@ -91,7 +91,7 @@ private void add(final T object) { /** * Returns a Set view of the mappings contained in this bag. * - * @return The Set view + * @return The Set view. */ private Set> entrySet() { return map.entrySet(); @@ -101,8 +101,8 @@ private Set> entrySet() { * Returns the number of occurrence of the given element in this bag by * looking up its count in the underlying map. * - * @param object the object to search for - * @return The number of occurrences of the object, zero if not found + * @param object the object to search for. + * @return The number of occurrences of the object, zero if not found. */ private int getCount(final Object object) { return map.getOrDefault(object, BagCount.ZERO).count; @@ -111,7 +111,7 @@ private int getCount(final Object object) { /** * Gets the number of unique elements in the bag. * - * @return The unique element size + * @return The unique element size. */ private int uniqueElementSize() { return map.size(); @@ -122,10 +122,10 @@ private int uniqueElementSize() { * Computes the intersection between two sets. This is the count of all the elements * that are within both sets. * - * @param the type of the elements in the set - * @param setA the set A - * @param setB the set B - * @return The intersection + * @param the type of the elements in the set. + * @param setA the set A. + * @param setB the set B. + * @return The intersection of A and B. */ private static int getIntersection(final Set setA, final Set setB) { int intersection = 0; @@ -149,8 +149,8 @@ private static int getIntersection(final Set setA, final Set setB) { * that will include duplicates in the intersect and union. *

* - * @param converter the converter used to create the elements from the characters - * @throws IllegalArgumentException if the converter is null + * @param converter the converter used to create the elements from the characters. + * @throws IllegalArgumentException if the converter is null. */ public IntersectionSimilarity(final Function> converter) { if (converter == null) { @@ -162,10 +162,10 @@ public IntersectionSimilarity(final Function> conver /** * Calculates the intersection of two character sequences passed as input. * - * @param left first character sequence - * @param right second character sequence - * @return The intersection result - * @throws IllegalArgumentException if either input sequence is {@code null} + * @param left first character sequence. + * @param right second character sequence. + * @return The intersection result. + * @throws IllegalArgumentException if either input sequence is {@code null}. */ @Override public IntersectionResult apply(final CharSequence left, final CharSequence right) { @@ -210,9 +210,9 @@ public IntersectionResult apply(final CharSequence left, final CharSequence righ * Computes the intersection between two bags. This is the sum of the minimum * count of each element that is within both sets. * - * @param bagA the bag A - * @param bagB the bag B - * @return The intersection + * @param bagA the bag A. + * @param bagB the bag B. + * @return The intersection of A and B. */ private int getIntersection(final TinyBag bagA, final TinyBag bagB) { int intersection = 0; @@ -229,8 +229,8 @@ private int getIntersection(final TinyBag bagA, final TinyBag bagB) { * Converts the collection to a bag. The bag will contain the count of each element * in the collection. * - * @param objects the objects - * @return The bag + * @param objects the objects. + * @return The bag. */ private TinyBag toBag(final Collection objects) { final TinyBag bag = new TinyBag(objects.size()); From 74e54eece9d5e77fe7a95bb8f498ce4179420995 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:21 -0400 Subject: [PATCH 046/265] Javadoc --- .../commons/text/similarity/IntersectionResult.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java b/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java index 155a772fd3..01f4f09a2c 100644 --- a/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java +++ b/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java @@ -49,11 +49,11 @@ public class IntersectionResult { /** * Constructs the results for an intersection between two sets. * - * @param sizeA the size of set A ({@code |A|}) - * @param sizeB the size of set B ({@code |B|}) - * @param intersection the size of the intersection of A and B ({@code |A ∩ B|}) + * @param sizeA the size of set A ({@code |A|}). + * @param sizeB the size of set B ({@code |B|}). + * @param intersection the size of the intersection of A and B ({@code |A ∩ B|}). * @throws IllegalArgumentException if the sizes are negative or the intersection is greater - * than the minimum of the two set sizes + * than the minimum of the two set sizes. */ public IntersectionResult(final int sizeA, final int sizeB, final int intersection) { if (sizeA < 0) { From c819ed70bae8cbfebd402d31324caa26faa6f341 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:24 -0400 Subject: [PATCH 047/265] Javadoc --- .../commons/text/similarity/FuzzyScore.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java b/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java index 8355fdba38..78c96affc5 100644 --- a/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java +++ b/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java @@ -43,10 +43,8 @@ public class FuzzyScore { /** * This returns a {@link Locale}-specific {@link FuzzyScore}. * - * @param locale The string matching logic is case insensitive. - A {@link Locale} is necessary to normalize both Strings to lower case. - * @throws IllegalArgumentException - * This is thrown if the {@link Locale} parameter is {@code null}. + * @param locale The string matching logic is case insensitive. A {@link Locale} is necessary to normalize both Strings to lower case. + * @throws IllegalArgumentException This is thrown if the {@link Locale} parameter is {@code null}. */ public FuzzyScore(final Locale locale) { if (locale == null) { @@ -56,8 +54,7 @@ public FuzzyScore(final Locale locale) { } /** - * Find the Fuzzy Score which indicates the similarity score between two - * Strings. + * Find the Fuzzy Score which indicates the similarity score between two Strings. * *
      * score.fuzzyScore(null, null)                          = IllegalArgumentException
@@ -72,11 +69,10 @@ public FuzzyScore(final Locale locale) {
      * score.fuzzyScore("Apache Software Foundation", "asf") = 3
      * 
* - * @param term a full term that should be matched against, must not be null - * @param query the query that will be matched against a term, must not be - * null - * @return result score - * @throws IllegalArgumentException if the term or query is {@code null} + * @param term a full term that should be matched against, must not be null. + * @param query the query that will be matched against a term, must not be null. + * @return result score. + * @throws IllegalArgumentException if the term or query is {@code null}. */ public Integer fuzzyScore(final CharSequence term, final CharSequence query) { if (term == null || query == null) { From 2afc236395968c1bf262f8f3f320bbd20b58da95 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:26 -0400 Subject: [PATCH 048/265] Javadoc --- .../apache/commons/text/similarity/EditDistanceFrom.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/EditDistanceFrom.java b/src/main/java/org/apache/commons/text/similarity/EditDistanceFrom.java index 008ea39c52..ef021dcdd0 100644 --- a/src/main/java/org/apache/commons/text/similarity/EditDistanceFrom.java +++ b/src/main/java/org/apache/commons/text/similarity/EditDistanceFrom.java @@ -80,8 +80,8 @@ public EditDistanceFrom(final EditDistance editDistance, final CharSequence l * Compares "left" field against the "right" parameter * using the "edit distance" implementation. * - * @param right the second CharSequence - * @return The similarity score between two CharSequences + * @param right the second CharSequence. + * @return The similarity score between two CharSequences. */ public R apply(final CharSequence right) { return editDistance.apply(left, right); @@ -90,7 +90,7 @@ public R apply(final CharSequence right) { /** * Gets the edit distance. * - * @return The edit distance + * @return The edit distance. */ public EditDistance getEditDistance() { return editDistance; @@ -99,7 +99,7 @@ public EditDistance getEditDistance() { /** * Gets the left parameter. * - * @return The left parameter + * @return The left parameter. */ public CharSequence getLeft() { return left; From 2f50c4f412612865494ba91cfa42008d3084022e Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:31 -0400 Subject: [PATCH 049/265] Javadoc --- .../text/similarity/CosineSimilarity.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java b/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java index d1adbf2508..dfbfe25b73 100644 --- a/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java +++ b/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java @@ -48,9 +48,9 @@ public CosineSimilarity() { /** * Calculates the cosine similarity for two given vectors. * - * @param leftVector left vector - * @param rightVector right vector - * @return cosine similarity between the two vectors + * @param leftVector left vector. + * @param rightVector right vector. + * @return cosine similarity between the two vectors. */ public Double cosineSimilarity(final Map leftVector, final Map rightVector) { @@ -83,10 +83,10 @@ public Double cosineSimilarity(final Map leftVector, * that if a vector is longer than other, then a smaller part of it will be used to compute * the dot product. * - * @param leftVector left vector - * @param rightVector right vector - * @param intersection common elements - * @return The dot product + * @param leftVector left vector. + * @param rightVector right vector. + * @param intersection common elements. + * @return The dot product. */ private double dot(final Map leftVector, final Map rightVector, final Set intersection) { @@ -100,9 +100,9 @@ private double dot(final Map leftVector, final Map getIntersection(final Map leftVector, final Map rightVector) { From 5fea6e2183e0832ea332a28228bc1fc773b4c647 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:01:51 -0400 Subject: [PATCH 050/265] Javadoc --- .../commons/text/similarity/LevenshteinDetailedDistance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java index 78505991f9..f5f80ad134 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java @@ -314,7 +314,7 @@ private static LevenshteinResults unlimitedCompare(SimilarityInput left, * p, the second int[]. Doing so allows us to retain the previous cost counts as required by the algorithm (taking the minimum of the cost count to the * left, up one, and diagonally up and to the left of the current cost count being calculated). (Note that the arrays aren't really copied anymore, just * switched...this is clearly much better than cloning an array or doing a System.arraycopy() each time through the outer loop.) - * + * * Effectively, the difference between the two implementations is this one does not cause an out of memory condition when calculating the LD over two * very large strings. */ From f7b8d467bb519fc24ff9e518af1bdfae02bafb8d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 10:04:46 -0400 Subject: [PATCH 051/265] Javadoc --- .../org/apache/commons/text/similarity/CosineSimilarity.java | 2 +- .../org/apache/commons/text/similarity/JaccardSimilarity.java | 2 +- .../apache/commons/text/similarity/JaroWinklerSimilarity.java | 2 +- .../commons/text/similarity/LevenshteinDetailedDistance.java | 2 +- .../commons/text/similarity/LongestCommonSubsequence.java | 2 +- .../java/org/apache/commons/text/similarity/RegexTokenizer.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java b/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java index dfbfe25b73..c0dd5c2c1a 100644 --- a/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java +++ b/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java @@ -34,7 +34,7 @@ public class CosineSimilarity { /** - * Singleton instance. + * The singleton instance. */ static final CosineSimilarity INSTANCE = new CosineSimilarity(); diff --git a/src/main/java/org/apache/commons/text/similarity/JaccardSimilarity.java b/src/main/java/org/apache/commons/text/similarity/JaccardSimilarity.java index c5291486e0..61e2b84319 100644 --- a/src/main/java/org/apache/commons/text/similarity/JaccardSimilarity.java +++ b/src/main/java/org/apache/commons/text/similarity/JaccardSimilarity.java @@ -32,7 +32,7 @@ public class JaccardSimilarity implements SimilarityScore { /** - * Singleton instance. + * The singleton instance. */ static final JaccardSimilarity INSTANCE = new JaccardSimilarity(); diff --git a/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java b/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java index c803bd5a47..e42650fe70 100644 --- a/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java +++ b/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java @@ -39,7 +39,7 @@ public class JaroWinklerSimilarity implements SimilarityScore { /** - * Singleton instance. + * The singleton instance. */ static final JaroWinklerSimilarity INSTANCE = new JaroWinklerSimilarity(); diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java index f5f80ad134..a25b988b60 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java @@ -32,7 +32,7 @@ public class LevenshteinDetailedDistance implements EditDistance { /** - * Singleton instance. + * The singleton instance. */ private static final LevenshteinDetailedDistance INSTANCE = new LevenshteinDetailedDistance(); diff --git a/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java b/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java index 04ec48e911..ac6d8d36f0 100644 --- a/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java +++ b/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java @@ -52,7 +52,7 @@ public class LongestCommonSubsequence implements SimilarityScore { /** - * Singleton instance. + * The singleton instance. */ static final LongestCommonSubsequence INSTANCE = new LongestCommonSubsequence(); diff --git a/src/main/java/org/apache/commons/text/similarity/RegexTokenizer.java b/src/main/java/org/apache/commons/text/similarity/RegexTokenizer.java index e566cbaf85..bf895ed8ac 100644 --- a/src/main/java/org/apache/commons/text/similarity/RegexTokenizer.java +++ b/src/main/java/org/apache/commons/text/similarity/RegexTokenizer.java @@ -40,7 +40,7 @@ final class RegexTokenizer implements CharSequenceTokenizer { private static final Pattern PATTERN = Pattern.compile("(\\w)+"); /** - * Singleton instance. + * The singleton instance. */ static final RegexTokenizer INSTANCE = new RegexTokenizer(); From 0a343ae4eec94a028d875d8c2200e7f5620d152c Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 13:32:33 -0400 Subject: [PATCH 052/265] Update the GitHub pull request template for AI Better grammar --- .github/pull_request_template.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e17973cb0c..7578b4da03 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -22,7 +22,9 @@ Thanks for your contribution to [Apache Commons](https://commons.apache.org/)! Y Before you push a pull request, review this list: - [ ] Read the [contribution guidelines](CONTRIBUTING.md) for this project. +- [ ] Read the [ASF Generative Tooling Guidance](https://www.apache.org/legal/generative-tooling.html) if you use Artificial Intelligence (AI). +- [ ] I used AI to create any part of, or all of, this pull request. - [ ] Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself. -- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible but is a best-practice. +- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best-practice. - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. -- [ ] Each commit in the pull request should have a meaningful subject line and body. Note that commits might be squashed by a maintainer on merge. +- [ ] Each commit in the pull request should have a meaningful subject line and body. Note that a maintainer may squash commits during the merge process. From 32ff6b421569ad4d611c60e79b01be64d96a92a6 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 21 Jul 2025 07:12:15 -0400 Subject: [PATCH 053/265] Merge some string literals --- .../java/org/apache/commons/text/StringEscapeUtilsTest.java | 2 +- .../java/org/apache/commons/text/StringSubstitutorTest.java | 4 ++-- .../org/apache/commons/text/lookup/XmlStringLookupTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java b/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java index 99c4755d43..bbebb0f1fe 100644 --- a/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java +++ b/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java @@ -299,7 +299,7 @@ void testEscapeJava() throws IOException { assertEscapeJava("\\uABCD", "\uabcd", "Should use capitalized Unicode hex"); assertEscapeJava("He didn't say, \\\"stop!\\\"", "He didn't say, \"stop!\""); - assertEscapeJava("This space is non-breaking:" + "\\u00A0", "This space is non-breaking:\u00a0", "non-breaking space"); + assertEscapeJava("This space is non-breaking:\\u00A0", "This space is non-breaking:\u00a0", "non-breaking space"); assertEscapeJava("\\uABCD\\u1234\\u012C", "\uABCD\u1234\u012C"); } diff --git a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java index 25ff819341..0f1fbf4339 100644 --- a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java +++ b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java @@ -556,7 +556,7 @@ void testReplaceInVariable() throws IOException { values.put("species", "1"); assertEqualsCharSeq("The fox jumps over the lazy dog.", replace(sub, "The ${animal.${species}} jumps over the ${target}.")); assertEqualsCharSeq("The fox jumps over the lazy dog.", - replace(sub, "The ${unknown.animal.${unknown.species:-1}:-fox} " + "jumps over the ${unknow.target:-lazy dog}.")); + replace(sub, "The ${unknown.animal.${unknown.species:-1}:-fox} jumps over the ${unknow.target:-lazy dog}.")); } /** @@ -1031,7 +1031,7 @@ void testStaticReplaceSystemProperties() { buf.append(", your home directory is "); buf.append(SystemProperties.getUserHome()).append('.'); assertEqualsCharSeq(buf.toString(), - StringSubstitutor.replaceSystemProperties("Hi ${user.name}, you are " + "working with ${os.name}, your home " + "directory is ${user.home}.")); + StringSubstitutor.replaceSystemProperties("Hi ${user.name}, you are " + "working with ${os.name}, your home directory is ${user.home}.")); } /** diff --git a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java index 179f9ff399..40290f0b75 100644 --- a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java @@ -57,7 +57,7 @@ void testBadXPath() { @Test void testMissingXPath() { - assertThrows(IllegalArgumentException.class, () -> XmlStringLookup.INSTANCE.apply(DOC_RELATIVE + ":" + "!JUNK!")); + assertThrows(IllegalArgumentException.class, () -> XmlStringLookup.INSTANCE.apply(DOC_RELATIVE + ":!JUNK!")); } @Test From b6702d61a0766ea7137c1dc53833fbd67287a290 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Thu, 24 Jul 2025 12:03:45 +0000 Subject: [PATCH 054/265] Bump to next development version --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c0e5b7e30d..775344dae0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 85 commons-text - 1.14.0 + 1.14.1-SNAPSHOT Apache Commons Text Apache Commons Text is a set of utility functions and reusable components for processing and manipulating text in a Java environment. @@ -33,7 +33,7 @@ ISO-8859-1 UTF-8 - 2025-07-20T13:34:14Z + 2025-07-24T12:03:40Z 1.8 1.8 text From 88dc3c8e2504a03882d7026e6727b09b8c8a105d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Thu, 24 Jul 2025 12:04:47 +0000 Subject: [PATCH 055/265] Updates for the next release --- src/changes/changes.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 5406a31766..89c8799a00 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -45,6 +45,11 @@ The type attribute can be add,update,fix,remove. Apache Commons Text Changes + + + + + Fix PMD UnnecessaryFullyQualifiedName in StringLookupFactory. From a7ef60c423eaec93b068c7b7d79f9a1ce80d8dba Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Thu, 24 Jul 2025 12:23:54 +0000 Subject: [PATCH 056/265] Updates for the next release --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 775344dae0..dd280d8785 100644 --- a/pom.xml +++ b/pom.xml @@ -39,8 +39,8 @@ text text org.apache.commons.text - 1.14.0 - 1.14.1 + 1.14.1 + 1.14.2 (Java 8+) TEXT 12318221 @@ -61,7 +61,7 @@ - 1.13.1 + 1.14.0 RC1 true scm:svn:https://dist.apache.org/repos/dist/dev/commons/${commons.componentid} From d7dbcacc8fe3e80639b118e00ed6fc93a6d0ac87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Jul 2025 16:18:01 -0400 Subject: [PATCH 057/265] Bump github/codeql-action from 3.29.2 to 3.29.4 (#682) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.2 to 3.29.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/181d5eefc20863364f96762470ba6f862bdef56b...4e828ff8d448a8a6e532957b1811f387a63867e8) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9255621e98..73bf9d5dec 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 + uses: github/codeql-action/init@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 + uses: github/codeql-action/autobuild@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 + uses: github/codeql-action/analyze@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 4c90c9c49f..1542dc9fe1 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 + uses: github/codeql-action/upload-sarif@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 with: sarif_file: results.sarif From 3dfb2c11405a9ce47aff9b10a3b0ef63efd380a1 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 26 Jul 2025 07:40:18 -0400 Subject: [PATCH 058/265] Add macOS file to git ignore file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 92a1b2a4a3..03ca919d66 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ site-content .project .externalToolBuilders /.checkstyle +/.DS_Store From b57a280f86da740d1e22b01a87f19986fe25d31b Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Tue, 29 Jul 2025 19:12:47 +0200 Subject: [PATCH 059/265] feat: Add experimental CycloneDX VEX file (#683) * feat: Add experimental CycloneDX VEX file This commit introduces an experimental CycloneDX VEX document that: * Provides an analysis of **CVE-2025-48924** as it pertains to this library. * Is committed to the **Git repository only** (not published to Maven Central), allowing it to be retrieved via `raw.githubusercontent.com`. This VEX file is intended to support consumers in evaluating the exploitability of known vulnerabilities in Apache Commons Text. * fix: Move files and fix copy/paste problems Moves files as suggested in apache/commons-bcel#446 and fixes copy/paste mistakes. --- src/conf/security/README.md | 61 ++++++++++++++ src/conf/security/VEX.cyclonedx.xml | 124 ++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+) create mode 100644 src/conf/security/README.md create mode 100644 src/conf/security/VEX.cyclonedx.xml diff --git a/src/conf/security/README.md b/src/conf/security/README.md new file mode 100644 index 0000000000..8629f82a7a --- /dev/null +++ b/src/conf/security/README.md @@ -0,0 +1,61 @@ + + +# CycloneDX Documents for Apache Commons Text + +The Apache Commons Text project publishes multiple [CycloneDX](https://cyclonedx.org/) documents to help consumers assess the security of their applications using this library: + +## SBOM (Software Bill of Materials) + +Beginning with version `6.6.0`, Apache Commons Text publishes SBOMs in both **XML** and **JSON** formats to Maven Central. These documents describe all components and dependencies of the library, following standard Maven coordinates: + +* **Group ID:** `org.apache.commons` +* **Artifact ID:** `commons-text` +* **Classifier:** `cyclonedx` +* **Type:** `xml` or `json` + +Each SBOM lists the library’s required and optional dependencies, helping consumers analyze the software supply chain and manage dependency risk. + +> [!NOTE] +> The versions listed in the SBOM reflect the dependencies used during the build and test process for that specific release of Text. +> Your own project may use different versions depending on your dependency management configuration. + +## VEX (Vulnerability Exploitability eXchange) + +An experimental [VEX](https://cyclonedx.org/capabilities/vex/) document is also published: + +👉 [`https://raw.githubusercontent.com/apache/commons-text/refs/heads/master/src/conf/security/VEX.cyclonedx.xml`](VEX.cyclonedx.xml) + +This document provides information about the **exploitability of known vulnerabilities** in the **dependencies** of Apache Commons Text. + +### When is a dependency vulnerability exploitable? + +Because Apache Commons libraries (including Text) do **not** bundle their dependencies, a vulnerability in a dependency is only exploitable if **both** of the following conditions are true: + +1. The vulnerable dependency is included in the consuming project. +2. Apache Commons Text is explicitly listed as affected by the vulnerability. + +### Notes and Limitations + +* This VEX document is **experimental** and provided **as-is**. + The semantics of this document may change in the future. +* The **absence** of a vulnerability entry does **not** indicate that Text is unaffected. +* If a version of Text is not listed under the `affects` section of a vulnerability, that version may still be affected or not. +* Only the **latest major version** of Text is currently assessed for vulnerabilities. +* The `analysis` field in the VEX file uses **Markdown** formatting. + +For more information about CycloneDX, SBOMs, or VEX, visit [cyclonedx.org](https://cyclonedx.org/). diff --git a/src/conf/security/VEX.cyclonedx.xml b/src/conf/security/VEX.cyclonedx.xml new file mode 100644 index 0000000000..7ef177f808 --- /dev/null +++ b/src/conf/security/VEX.cyclonedx.xml @@ -0,0 +1,124 @@ + + + + + + + 2025-07-29T12:26:42Z + + org.apache.commons + commons-text + cpe:2.3:a:apache:commons_text:*:*:*:*:*:*:*:* + pkg:maven/org.apache.commons/commons-text?type=jar + + + The Apache Software Foundation + https://commons.apache.org + + Apache Commons PMC + dev@commons.apache.org + + + Apache Commons Security Team + security@commons.apache.org + + + + + + + CVE-2025-48924 + + + GHSA-j288-q9x7-2f5v + + https://github.com/advisories/GHSA-j288-q9x7-2f5v + + + + + exploitable + + update + + + CVE-2025-48924 is exploitable in Apache Commons Text versions 1.5 and later, but only when all the following conditions are met: + + * The consuming project includes a vulnerable version of Commons Text on the classpath. + As of version `1.14.1`, Commons Text no longer references a vulnerable version of the `commons-lang3` library in its POM file. + * Unvalidated or unsanitized user input is passed to the `StringSubstitutor` or `StringLookup` classes. + * An interpolator lookup created via `StringLookupFactory.interpolatorLookup()` is used. + + If these conditions are satisfied, an attacker may cause an infinite loop by submitting a specially crafted input such as `${const:...}`. + + 2025-07-29T12:26:42Z + 2025-07-29T12:26:42Z + + + + main_component + + + + affected + + + + + + + + + + + + Apache Commons PMC + dev@commons.apache.org + + + 2025-07-29T12:26:42Z + + This document provides information about the **exploitability of known vulnerabilities** in the **dependencies** of Apache Commons Text. + + # When is a dependency vulnerability exploitable? + + Because Apache Commons libraries do **not** bundle their dependencies, a vulnerability in a dependency is only exploitable if **both** of the following conditions are true: + + 1. The vulnerable dependency is included in the consuming project. + 2. Apache Commons Text is explicitly listed as affected by the vulnerability. + + # Notes and Limitations + + * This VEX document is **experimental** and provided **as-is**. + The semantics of this document may change in the future. + * The **absence** of a vulnerability entry does **not** indicate that Text is unaffected. + * If a version of Text is not listed under the `affects` section of a vulnerability, that version may still be affected or not. + * Only the **latest major version** of Text is currently assessed for vulnerabilities. + * The `analysis` field in the VEX file uses **Markdown** formatting. + + + + From f5908a7f204002cde362920dbf3c9755077628d4 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 29 Jul 2025 13:15:22 -0400 Subject: [PATCH 060/265] Add experimental CycloneDX VEX file #683 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 89c8799a00..298f8cc60a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,6 +48,7 @@ The type attribute can be add,update,fix,remove. + Add experimental CycloneDX VEX file #683. From d2f43cd822de59daab7924668ab9f0a2b7512553 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 16:11:40 -0400 Subject: [PATCH 061/265] Bump github/codeql-action from 3.29.4 to 3.29.5 (#685) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.4 to 3.29.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4e828ff8d448a8a6e532957b1811f387a63867e8...51f77329afa6477de8c49fc9c7046c15b9a4e79d) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 73bf9d5dec..d3aa4af0e3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 + uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 + uses: github/codeql-action/autobuild@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 + uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 1542dc9fe1..68adb567af 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 + uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 with: sarif_file: results.sarif From 8d3f4aa9eaa433774dcd6181cd69c790257d0bf6 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Mon, 4 Aug 2025 14:10:35 +0200 Subject: [PATCH 062/265] fix: Ensure unique serial number for VEX file (#686) This update corrects the serial number in the VEX file, which was mistakenly copied from apache/commons-bcel#446. With this fix, all published VEX files will now have unique serial numbers, preventing potential conflicts or duplication. --- src/conf/security/VEX.cyclonedx.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/conf/security/VEX.cyclonedx.xml b/src/conf/security/VEX.cyclonedx.xml index 7ef177f808..9c0875aa99 100644 --- a/src/conf/security/VEX.cyclonedx.xml +++ b/src/conf/security/VEX.cyclonedx.xml @@ -23,11 +23,11 @@ + serialNumber="urn:uuid:9d64577b-0376-4ee7-b154-5ec26a1803f4" + version="2"> - 2025-07-29T12:26:42Z + 2025-08-04T11:45:36Z org.apache.commons commons-text From c0599f43b6a84e8ae7e1cea10e082ac2657fb647 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Mon, 4 Aug 2025 14:31:22 +0200 Subject: [PATCH 063/265] fix: Replace Text -> Lang in VEX description The vulnerability is exploitable if a vulnerable Commons Lang is present, not Commons Text. --- src/conf/security/VEX.cyclonedx.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf/security/VEX.cyclonedx.xml b/src/conf/security/VEX.cyclonedx.xml index 9c0875aa99..dcad061f0e 100644 --- a/src/conf/security/VEX.cyclonedx.xml +++ b/src/conf/security/VEX.cyclonedx.xml @@ -67,7 +67,7 @@ CVE-2025-48924 is exploitable in Apache Commons Text versions 1.5 and later, but only when all the following conditions are met: - * The consuming project includes a vulnerable version of Commons Text on the classpath. + * The consuming project includes a vulnerable version of Commons Lang on the classpath. As of version `1.14.1`, Commons Text no longer references a vulnerable version of the `commons-lang3` library in its POM file. * Unvalidated or unsanitized user input is passed to the `StringSubstitutor` or `StringLookup` classes. * An interpolator lookup created via `StringLookupFactory.interpolatorLookup()` is used. From 87b9da4c80d234bf62d819b9cf9ad30a75bf6870 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 5 Aug 2025 09:41:38 -0400 Subject: [PATCH 064/265] Javadoc --- .../org/apache/commons/text/translate/LookupTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/translate/LookupTranslator.java b/src/main/java/org/apache/commons/text/translate/LookupTranslator.java index 005e36e446..e9d5d40645 100644 --- a/src/main/java/org/apache/commons/text/translate/LookupTranslator.java +++ b/src/main/java/org/apache/commons/text/translate/LookupTranslator.java @@ -43,7 +43,7 @@ public class LookupTranslator extends CharSequenceTranslator { /** * Constructs the lookup table to be used in translation. * - * Note that, as of Lang 3.1 (the origin of this code), the key to the lookup table is converted to a java.lang.String. This is because we need the key to + * Note that, as of Lang 3.1 (the origin of this code), the key to the lookup table is converted to a {@link String}. This is because we need the key to * support hashCode and equals(Object), allowing it to be the key for a HashMap. See LANG-882. * * @param lookupMap Map<CharSequence, CharSequence> table of translator mappings, may not be null. From 96c6382c2d2e28db5c54284ad566d8227a8bf86b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:00:13 -0400 Subject: [PATCH 065/265] Bump github/codeql-action from 3.29.7 to 3.29.8 (#688) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.7 to 3.29.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/51f77329afa6477de8c49fc9c7046c15b9a4e79d...76621b61decf072c1cee8dd1ce2d2a82d33c17ed) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d3aa4af0e3..6049e1d240 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 + uses: github/codeql-action/init@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 + uses: github/codeql-action/autobuild@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 + uses: github/codeql-action/analyze@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 68adb567af..387ec70f93 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 + uses: github/codeql-action/upload-sarif@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 with: sarif_file: results.sarif From abc4a103d4b1521da480e08fa2c3b29d909b3b5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:00:26 -0400 Subject: [PATCH 066/265] Bump actions/cache from 4.2.3 to 4.2.4 (#689) Bumps [actions/cache](https://github.com/actions/cache) from 4.2.3 to 4.2.4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/5a3ec84eff668545956fd18022155c47e93e2684...0400d5f644dc74513175e3cd8d07132dd4860809) --- updated-dependencies: - dependency-name: actions/cache dependency-version: 4.2.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6049e1d240..f7a3c7484f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -48,7 +48,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From 1c09035f232480c9920bb90a31b0a644c5165351 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 17:04:23 -0400 Subject: [PATCH 067/265] Bump actions/checkout from 4.2.2 to 5.0.0 (#691) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/11bd71901bbe5b1630ceea73d27597364c9af683...08c6903cd8c0fde910a37f88322edcfb5dd907a8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/maven.yml | 2 +- .github/workflows/scorecards-analysis.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f7a3c7484f..4e90507a7c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 33573cf948..e8d1ed6781 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index d182b41b99..c1f9fb58dc 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -34,7 +34,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Set up JDK ${{ matrix.java }} diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 387ec70f93..bf2796af74 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -40,7 +40,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false From a7cbd846db5e7aa0e6ea8d4caa0e154e40ad3796 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 17:04:37 -0400 Subject: [PATCH 068/265] Bump github/codeql-action from 3.29.8 to 3.29.9 (#690) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.8 to 3.29.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/76621b61decf072c1cee8dd1ce2d2a82d33c17ed...df559355d593797519d70b90fc8edd5db049e7a2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4e90507a7c..b6654adaf0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 + uses: github/codeql-action/init@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 + uses: github/codeql-action/autobuild@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 + uses: github/codeql-action/analyze@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index bf2796af74..fe4221817d 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 + uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 with: sarif_file: results.sarif From bbcc1e7a326e696e79efbdad2d35557f89ba5a2f Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 20 Aug 2025 06:57:30 -0400 Subject: [PATCH 069/265] Javadoc --- .../commons/text/TextStringBuilder.java | 2 +- .../commons/text/numbers/DoubleFormat.java | 32 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java index 939ce1eaf1..1f194220fe 100644 --- a/src/main/java/org/apache/commons/text/TextStringBuilder.java +++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java @@ -3019,7 +3019,7 @@ public TextStringBuilder setLength(final int length) { * Sets the text to be appended when {@link #appendNewLine() new line} is called. * * @param newLine the new line text, {@code null} means use the system default from {@link System#lineSeparator()}. - * @return this instance. + * @return {@code this} instance. */ public TextStringBuilder setNewLineText(final String newLine) { this.newLine = newLine; diff --git a/src/main/java/org/apache/commons/text/numbers/DoubleFormat.java b/src/main/java/org/apache/commons/text/numbers/DoubleFormat.java index 74e1713894..1ad97d5fd3 100644 --- a/src/main/java/org/apache/commons/text/numbers/DoubleFormat.java +++ b/src/main/java/org/apache/commons/text/numbers/DoubleFormat.java @@ -424,7 +424,7 @@ private Builder(final Function> factory) { * * @param signedZero if {@code true}, the zero string may be returned with a preceding minus sign; if {@code false}, the zero string will only be * returned in its positive form - * @return this instance + * @return {@code this} instance */ public Builder allowSignedZero(final boolean signedZero) { this.signedZero = signedZero; @@ -437,7 +437,7 @@ public Builder allowSignedZero(final boolean signedZero) { * ENGINEERING}, and {@link DoubleFormat#MIXED MIXED}. The default value is {@code false}. * * @param alwaysIncludeExponent if {@code true}, exponents will always be included in formatted output even if the exponent value is zero - * @return this instance + * @return {@code this} instance */ public Builder alwaysIncludeExponent(final boolean alwaysIncludeExponent) { this.alwaysIncludeExponent = alwaysIncludeExponent; @@ -460,7 +460,7 @@ public DoubleFunction build() { * default value is {@code '.'}. * * @param decimalSeparator decimal separator character - * @return this instance + * @return {@code this} instance */ public Builder decimalSeparator(final char decimalSeparator) { this.decimalSeparator = decimalSeparator; @@ -471,7 +471,7 @@ public Builder decimalSeparator(final char decimalSeparator) { * Sets the string containing the digit characters 0-9, in that order. The default value is the string {@code "0123456789"}. * * @param digits string containing the digit characters 0-9 - * @return this instance + * @return {@code this} instance * @throws NullPointerException if the argument is {@code null} * @throws IllegalArgumentException if the argument does not have a length of exactly 10 */ @@ -490,7 +490,7 @@ public Builder digits(final String digits) { * {@code "1.2E6"}. * * @param exponentSeparator exponent separator string - * @return this instance + * @return {@code this} instance * @throws NullPointerException if the argument is {@code null} */ public Builder exponentSeparator(final String exponentSeparator) { @@ -513,7 +513,7 @@ public Builder exponentSeparator(final String exponentSeparator) { * consecutive characters. * * @param symbols format symbols - * @return this instance + * @return {@code this} instance * @throws NullPointerException if the argument is {@code null} */ public Builder formatSymbols(final DecimalFormatSymbols symbols) { @@ -537,7 +537,7 @@ public DoubleFunction get() { * Sets the character used to separate groups of thousands. Default value is {@code ','}. * * @param groupingSeparator character used to separate groups of thousands - * @return this instance + * @return {@code this} instance * @see #groupThousands(boolean) */ public Builder groupingSeparator(final char groupingSeparator) { @@ -551,7 +551,7 @@ public Builder groupingSeparator(final char groupingSeparator) { * value is {@code false}. * * @param groupThousands if {@code true}, thousands will be grouped - * @return this instance + * @return {@code this} instance * @see #groupingSeparator(char) */ public Builder groupThousands(final boolean groupThousands) { @@ -566,7 +566,7 @@ public Builder groupThousands(final boolean groupThousands) { * * @param fractionPlaceholder if {@code true}, a zero character is placed in the fraction position when no fractional value is present; if * {@code false}, fractional digits are only included when needed - * @return this instance + * @return {@code this} instance */ public Builder includeFractionPlaceholder(final boolean fractionPlaceholder) { this.fractionPlaceholder = fractionPlaceholder; @@ -577,7 +577,7 @@ public Builder includeFractionPlaceholder(final boolean fractionPlaceholder) { * Sets the string used to represent infinity. For negative infinity, this string is prefixed with the {@link #minusSign(char) minus sign}. * * @param infinity string used to represent infinity - * @return this instance + * @return {@code this} instance * @throws NullPointerException if the argument is {@code null} */ public Builder infinity(final String infinity) { @@ -590,7 +590,7 @@ public Builder infinity(final String infinity) { * {@code 0}. * * @param maxPrecision maximum precision - * @return this instance + * @return {@code this} instance */ public Builder maxPrecision(final int maxPrecision) { this.maxPrecision = maxPrecision; @@ -604,7 +604,7 @@ public Builder maxPrecision(final int maxPrecision) { * {@code 0.001} is formatted, then the result is the zero string. * * @param minDecimalExponent minimum decimal exponent - * @return this instance + * @return {@code this} instance */ public Builder minDecimalExponent(final int minDecimalExponent) { this.minDecimalExponent = minDecimalExponent; @@ -615,7 +615,7 @@ public Builder minDecimalExponent(final int minDecimalExponent) { * Sets the character used as the minus sign. * * @param minusSign character to use as the minus sign - * @return this instance + * @return {@code this} instance */ public Builder minusSign(final char minusSign) { this.minusSign = minusSign; @@ -626,7 +626,7 @@ public Builder minusSign(final char minusSign) { * Sets the string used to represent {@link Double#NaN}. * * @param nan string used to represent {@link Double#NaN} - * @return this instance + * @return {@code this} instance * @throws NullPointerException if the argument is {@code null} */ public Builder nan(final String nan) { @@ -649,7 +649,7 @@ public Builder nan(final String nan) { * * @param plainFormatMaxDecimalExponent maximum decimal exponent for values formatted as plain strings when using the {@link DoubleFormat#MIXED MIXED} * format type. - * @return this instance + * @return {@code this} instance * @see #plainFormatMinDecimalExponent(int) */ public Builder plainFormatMaxDecimalExponent(final int plainFormatMaxDecimalExponent) { @@ -672,7 +672,7 @@ public Builder plainFormatMaxDecimalExponent(final int plainFormatMaxDecimalExpo * * @param plainFormatMinDecimalExponent maximum decimal exponent for values formatted as plain strings when using the {@link DoubleFormat#MIXED MIXED} * format type. - * @return this instance + * @return {@code this} instance * @see #plainFormatMinDecimalExponent(int) */ public Builder plainFormatMinDecimalExponent(final int plainFormatMinDecimalExponent) { From a2d2157859c1d470703dc363c391a2dd569f05d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 17:45:13 -0400 Subject: [PATCH 070/265] Bump actions/setup-java from 4.7.1 to 5.0.0 (#692) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.1 to 5.0.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/c5195efecf7bdfc987ee8bae7a71cb8b11521c00...dded0888837ed1f317902acf8a20df0ad188d165) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index c1f9fb58dc..4890f722c4 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -38,7 +38,7 @@ jobs: with: persist-credentials: false - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} From beae6a921ae6511fc96cf0a27d5063a172b331fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 17:45:28 -0400 Subject: [PATCH 071/265] Bump actions/dependency-review-action from 4.7.1 to 4.7.2 (#693) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.1 to 4.7.2. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/da24556b548a50705dd671f47852072ea4c105d9...bc41886e18ea39df68b1b1245f4184881938e050) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.7.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index e8d1ed6781..daed9687ff 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 + uses: actions/dependency-review-action@bc41886e18ea39df68b1b1245f4184881938e050 # v4.7.2 From 370a99be2bfb690b5bd25919c4e4243842ff5dbd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 17:45:43 -0400 Subject: [PATCH 072/265] Bump github/codeql-action from 3.29.9 to 3.29.11 (#694) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.9 to 3.29.11. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/df559355d593797519d70b90fc8edd5db049e7a2...3c3833e0f8c1c83d449a7478aa59c036a9165498) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b6654adaf0..36b2f321b5 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 + uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 + uses: github/codeql-action/autobuild@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 + uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index fe4221817d..f5ac42eaa8 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 + uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 with: sarif_file: results.sarif From c5a9bb5f51a27f625c73e40f3e18b4c8d916ad6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 20:49:17 -0400 Subject: [PATCH 073/265] Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 (#696) Bumps `commons.bytebuddy.version` from 1.17.6 to 1.17.7. Updates `net.bytebuddy:byte-buddy` from 1.17.6 to 1.17.7 - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.17.6...byte-buddy-1.17.7) Updates `net.bytebuddy:byte-buddy-agent` from 1.17.6 to 1.17.7 - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.17.6...byte-buddy-1.17.7) --- updated-dependencies: - dependency-name: net.bytebuddy:byte-buddy dependency-version: 1.17.7 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: net.bytebuddy:byte-buddy-agent dependency-version: 1.17.7 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dd280d8785..2e950031eb 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content 3.18.0 - 1.17.6 + 1.17.7 1.6 false 1.37 From ee2243e0d07e112c4439daded46ebb4d65901c44 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 22 Aug 2025 20:50:52 -0400 Subject: [PATCH 074/265] Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #696 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 298f8cc60a..fafac5dfc9 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,6 +50,7 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. + Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #696. @@ -63,7 +64,6 @@ The type attribute can be add,update,fix,remove. Fix PMD AvoidBranchingStatementAsLastInLoop in TextStringBuilder. Fix PMD AvoidBranchingStatementAsLastInLoop in StrBuilder. org.apache.commons.text.translate.LookupTranslator.LookupTranslator(Map CharSequence>) now throws NullPointerException instead of java.security.InvalidParameterException. - Interface StringLookup now extends UnaryOperator<String>. Interface TextRandomProvider extends IntUnaryOperator. From 80b12daa94162ee828f3e450dc0f431a0bb1888e Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 24 Aug 2025 16:19:21 -0400 Subject: [PATCH 075/265] Account for false positives only seen on GH CI --- src/conf/spotbugs-exclude-filter.xml | 13 +++--- .../commons/text/ExtendedMessageFormat.java | 42 +++++++------------ 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/src/conf/spotbugs-exclude-filter.xml b/src/conf/spotbugs-exclude-filter.xml index 2656019b49..d918d9f0f8 100644 --- a/src/conf/spotbugs-exclude-filter.xml +++ b/src/conf/spotbugs-exclude-filter.xml @@ -19,38 +19,39 @@ xmlns="https://github.com/spotbugs/filter/3.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0/spotbugs/etc/findbugsfilter.xsd"> - - + + + + + + + - - - - diff --git a/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java b/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java index 5cc88e3c22..e955490089 100644 --- a/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java +++ b/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java @@ -135,18 +135,14 @@ public ExtendedMessageFormat(final String pattern, final Locale locale) { * Constructs a new ExtendedMessageFormat. * * @param pattern the pattern to use, not null - * @param locale the locale to use, not null - * @param registry the registry of format factories, may be null + * @param locale the locale to use, not null + * @param registry the registry of format factories, may be null * @throws IllegalArgumentException in case of a bad pattern. */ - public ExtendedMessageFormat(final String pattern, - final Locale locale, - final Map registry) { + public ExtendedMessageFormat(final String pattern, final Locale locale, final Map registry) { super(EMPTY_PATTERN); setLocale(locale); - this.registry = registry != null - ? Collections.unmodifiableMap(new HashMap<>(registry)) - : null; + this.registry = registry != null ? Collections.unmodifiableMap(new HashMap<>(registry)) : null; applyPattern(pattern); } @@ -154,33 +150,27 @@ public ExtendedMessageFormat(final String pattern, * Constructs a new ExtendedMessageFormat for the default locale. * * @param pattern the pattern to use, not null - * @param registry the registry of format factories, may be null + * @param registry the registry of format factories, may be null * @throws IllegalArgumentException in case of a bad pattern. */ - public ExtendedMessageFormat(final String pattern, - final Map registry) { + public ExtendedMessageFormat(final String pattern, final Map registry) { this(pattern, Locale.getDefault(Category.FORMAT), registry); } /** - * Consumes a quoted string, adding it to {@code appendTo} if - * specified. + * Consumes a quoted string, adding it to {@code appendTo} if specified. * - * @param pattern pattern to parse - * @param pos current parse position + * @param pattern pattern to parse + * @param pos current parse position * @param appendTo optional StringBuilder to append */ - private void appendQuotedString(final String pattern, final ParsePosition pos, - final StringBuilder appendTo) { - assert pattern.toCharArray()[pos.getIndex()] == QUOTE - : "Quoted string must start with quote character"; - + private void appendQuotedString(final String pattern, final ParsePosition pos, final StringBuilder appendTo) { + assert pattern.toCharArray()[pos.getIndex()] == QUOTE : "Quoted string must start with quote character"; // handle quote character at the beginning of the string if (appendTo != null) { appendTo.append(QUOTE); } next(pos); - final int start = pos.getIndex(); final char[] c = pattern.toCharArray(); for (int i = pos.getIndex(); i < pattern.length(); i++) { @@ -195,8 +185,7 @@ private void appendQuotedString(final String pattern, final ParsePosition pos, next(pos); } } - throw new IllegalArgumentException( - "Unterminated quoted string at position " + start); + throw new IllegalArgumentException("Unterminated quoted string at position " + start); } /** @@ -214,7 +203,6 @@ public final void applyPattern(final String pattern) { final ArrayList foundFormats = new ArrayList<>(); final ArrayList foundDescriptions = new ArrayList<>(); final StringBuilder stripCustom = new StringBuilder(pattern.length()); - final ParsePosition pos = new ParsePosition(0); final char[] c = pattern.toCharArray(); int fmtCount = 0; @@ -233,8 +221,7 @@ public final void applyPattern(final String pattern) { Format format = null; String formatDescription = null; if (c[pos.getIndex()] == START_FMT) { - formatDescription = parseFormatDescription(pattern, - next(pos)); + formatDescription = parseFormatDescription(pattern, next(pos)); format = getFormat(formatDescription); if (format == null) { stripCustom.append(START_FMT).append(formatDescription); @@ -249,8 +236,7 @@ public final void applyPattern(final String pattern) { throw new IllegalArgumentException("The validated expression is false"); } if (c[pos.getIndex()] != END_FE) { - throw new IllegalArgumentException( - "Unreadable format element at position " + start); + throw new IllegalArgumentException("Unreadable format element at position " + start); } //$FALL-THROUGH$ default: From fcda003b17094384fdda579a59ea59becf200036 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 24 Aug 2025 16:20:08 -0400 Subject: [PATCH 076/265] Bump org.apache.commons:commons-parent from 85 to 87 --- pom.xml | 2 +- src/changes/changes.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2e950031eb..8c9b18d74a 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 85 + 87 commons-text 1.14.1-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index fafac5dfc9..66826b5844 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,7 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #696. + Bump org.apache.commons:commons-parent from 85 to 87. From 79252937b136534d608258acab8ad883696ff5a5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 28 Aug 2025 10:04:50 -0400 Subject: [PATCH 077/265] Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...) --- src/changes/changes.xml | 1 + .../java/org/apache/commons/text/lookup/XmlStringLookup.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 66826b5844..df97b651b1 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,6 +47,7 @@ The type attribute can be add,update,fix,remove. + Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). Add experimental CycloneDX VEX file #683. diff --git a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java index a476cc0786..0f3663fd45 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java @@ -72,7 +72,7 @@ final class XmlStringLookup extends AbstractPathFencedLookup { */ XmlStringLookup(final Map xPathFactoryFeatures, final Path... fences) { super(fences); - this.xPathFactoryFeatures = Objects.requireNonNull(xPathFactoryFeatures, "xPathFfactoryFeatures"); + this.xPathFactoryFeatures = Objects.requireNonNull(xPathFactoryFeatures, "xPathFactoryFeatures"); } /** From ff23055f79609ba9c049446d051bc4f110a8722f Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 29 Aug 2025 08:35:54 -0400 Subject: [PATCH 078/265] Javadoc --- .../apache/commons/text/lookup/BiFunctionStringLookup.java | 4 ++++ .../org/apache/commons/text/lookup/ConstantStringLookup.java | 4 ++++ .../org/apache/commons/text/lookup/DateStringLookup.java | 5 +++++ .../java/org/apache/commons/text/lookup/DnsStringLookup.java | 4 ++++ .../org/apache/commons/text/lookup/FileStringLookup.java | 4 ++++ .../org/apache/commons/text/lookup/FunctionStringLookup.java | 4 ++++ .../java/org/apache/commons/text/lookup/InetAddressKeys.java | 4 ++++ .../apache/commons/text/lookup/InetAddressStringLookup.java | 4 ++++ .../apache/commons/text/lookup/InterpolatorStringLookup.java | 5 +++++ .../apache/commons/text/lookup/JavaPlatformStringLookup.java | 4 ++++ .../apache/commons/text/lookup/PropertiesStringLookup.java | 4 ++++ .../commons/text/lookup/ResourceBundleStringLookup.java | 4 ++++ .../org/apache/commons/text/lookup/ScriptStringLookup.java | 4 ++++ .../apache/commons/text/lookup/UrlDecoderStringLookup.java | 4 ++++ .../apache/commons/text/lookup/UrlEncoderStringLookup.java | 5 +++++ .../java/org/apache/commons/text/lookup/UrlStringLookup.java | 5 +++++ .../apache/commons/text/lookup/XmlDecoderStringLookup.java | 5 +++++ .../apache/commons/text/lookup/XmlEncoderStringLookup.java | 5 +++++ .../java/org/apache/commons/text/lookup/XmlStringLookup.java | 2 +- 19 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/lookup/BiFunctionStringLookup.java b/src/main/java/org/apache/commons/text/lookup/BiFunctionStringLookup.java index 9e1891a5a9..336d429372 100644 --- a/src/main/java/org/apache/commons/text/lookup/BiFunctionStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/BiFunctionStringLookup.java @@ -22,9 +22,13 @@ /** * A function-based lookup where the request for a lookup is answered by applying that function with a key. + *

+ * Public access is through {@link StringLookupFactory}. + *

* * @param A function's return type * @param

A function's second input type + * @see StringLookupFactory * @since 1.9 */ final class BiFunctionStringLookup implements BiStringLookup

{ diff --git a/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java b/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java index 1f70af9b77..dff4509846 100644 --- a/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java @@ -58,7 +58,11 @@ *

* This class was adapted from Apache Commons Configuration. *

+ *

+ * Public access is through {@link StringLookupFactory}. + *

* + * @see StringLookupFactory * @since 1.5 */ class ConstantStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java b/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java index c684db35d4..fe313c2bf3 100644 --- a/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java @@ -43,6 +43,11 @@ *

* The above examples convert {@code "yyyy-MM-dd"} to today's date, for example, {@code "2019-08-04"}. *

+ *

+ * Public access is through {@link StringLookupFactory}. + *

+ * + * @see StringLookupFactory */ final class DateStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/DnsStringLookup.java b/src/main/java/org/apache/commons/text/lookup/DnsStringLookup.java index 0506b26997..5d76eb93d0 100644 --- a/src/main/java/org/apache/commons/text/lookup/DnsStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/DnsStringLookup.java @@ -53,7 +53,11 @@ *

* The above examples convert {@code "address|apache.org"} to {@code "95.216.24.32} (or {@code "40.79.78.1"}). *

+ *

+ * Public access is through {@link StringLookupFactory}. + *

* + * @see StringLookupFactory * @since 1.8 */ final class DnsStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/FileStringLookup.java b/src/main/java/org/apache/commons/text/lookup/FileStringLookup.java index f8a957ea6a..bf36478a14 100644 --- a/src/main/java/org/apache/commons/text/lookup/FileStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/FileStringLookup.java @@ -45,7 +45,11 @@ *

* The above example converts {@code "UTF-8:SomePath"} to the UTF-8 contents of the file at {@code SomePath}. *

+ *

+ * Public access is through {@link StringLookupFactory}. + *

* + * @see StringLookupFactory * @since 1.5 */ final class FileStringLookup extends AbstractPathFencedLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java b/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java index 4a7123ea9b..07df1489ea 100644 --- a/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java @@ -22,8 +22,12 @@ /** * A function-based lookup where the request for a lookup is answered by applying that function with a key. + *

+ * Public access is through {@link StringLookupFactory}. + *

* * @param A function's input type + * @see StringLookupFactory * @since 1.9 */ final class FunctionStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/InetAddressKeys.java b/src/main/java/org/apache/commons/text/lookup/InetAddressKeys.java index a188d4fd58..e7eee0136b 100644 --- a/src/main/java/org/apache/commons/text/lookup/InetAddressKeys.java +++ b/src/main/java/org/apache/commons/text/lookup/InetAddressKeys.java @@ -21,7 +21,11 @@ /** * Constants for referring to {@link InetAddress} APIs. + *

+ * Public access is through {@link StringLookupFactory}. + *

* + * @see StringLookupFactory * @since 1.8 */ final class InetAddressKeys { diff --git a/src/main/java/org/apache/commons/text/lookup/InetAddressStringLookup.java b/src/main/java/org/apache/commons/text/lookup/InetAddressStringLookup.java index 346634cdcb..6d0183db9c 100644 --- a/src/main/java/org/apache/commons/text/lookup/InetAddressStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/InetAddressStringLookup.java @@ -35,7 +35,11 @@ *
  • canonical-name: for the local canonical host name, for example {@code EXAMPLE.apache.org}.
  • *
  • address: for the local host address, for example {@code 192.168.56.1}.
  • * + *

    + * Public access is through {@link StringLookupFactory}. + *

    * + * @see StringLookupFactory * @since 1.3 */ final class InetAddressStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java b/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java index c864698043..17e3da7b93 100644 --- a/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java @@ -26,6 +26,11 @@ *

    * Uses the {@link StringLookupFactory default lookups}. *

    + *

    + * Public access is through {@link StringLookupFactory}. + *

    + * + * @see StringLookupFactory */ final class InterpolatorStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java index da1048bbe6..734e2dd436 100644 --- a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java @@ -53,7 +53,11 @@ * The above examples convert {@code "version"} to the current VM version, for example, * {@code "Java version 1.8.0_181"}. *

    + *

    + * Public access is through {@link StringLookupFactory}. + *

    * + * @see StringLookupFactory * @since 1.3 */ final class JavaPlatformStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java b/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java index d369ffcf39..dab5f62d5d 100644 --- a/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java @@ -35,7 +35,11 @@ *

    * For example: "com/domain/document.properties:key". *

    + *

    + * Public access is through {@link StringLookupFactory}. + *

    * + * @see StringLookupFactory * @see Properties * @since 1.5 */ diff --git a/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java b/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java index e92d131aa2..a517058ecc 100644 --- a/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java @@ -28,7 +28,11 @@ *

    * For example: "com.domain.messages:MyKey". *

    + *

    + * Public access is through {@link StringLookupFactory}. + *

    * + * @see StringLookupFactory * @see ResourceBundle * @since 1.3 */ diff --git a/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java b/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java index 697214508f..4151a732f7 100644 --- a/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java @@ -39,7 +39,11 @@ *
      * StringSubstitutor.createInterpolator().replace("${script:javascript:3 + 4}"));
      * 
    + *

    + * Public access is through {@link StringLookupFactory}. + *

    * + * @see StringLookupFactory * @since 1.5 */ final class ScriptStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/UrlDecoderStringLookup.java b/src/main/java/org/apache/commons/text/lookup/UrlDecoderStringLookup.java index 8072d36cac..0aabf06b8e 100644 --- a/src/main/java/org/apache/commons/text/lookup/UrlDecoderStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/UrlDecoderStringLookup.java @@ -24,7 +24,11 @@ /** * Decodes URL Strings using the UTF-8 encoding. + *

    + * Public access is through {@link StringLookupFactory}. + *

    * + * @see StringLookupFactory * @see URLEncoder * @since 1.5 */ diff --git a/src/main/java/org/apache/commons/text/lookup/UrlEncoderStringLookup.java b/src/main/java/org/apache/commons/text/lookup/UrlEncoderStringLookup.java index e34ecf4618..15be8d75aa 100644 --- a/src/main/java/org/apache/commons/text/lookup/UrlEncoderStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/UrlEncoderStringLookup.java @@ -24,6 +24,11 @@ /** * Encodes URL Strings using the UTF-8 encoding. * + *

    + * Public access is through {@link StringLookupFactory}. + *

    + * + * @see StringLookupFactory * @see URLEncoder * @since 1.5 */ diff --git a/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java index 00f431beb7..948f2b1bef 100644 --- a/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java @@ -33,6 +33,11 @@ * For example: "UTF-8:https://www.apache.org". *

    * + *

    + * Public access is through {@link StringLookupFactory}. + *

    + * + * @see StringLookupFactory * @since 1.5 */ final class UrlStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/XmlDecoderStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlDecoderStringLookup.java index 3176f33ad0..f3c4e93c10 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlDecoderStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlDecoderStringLookup.java @@ -22,6 +22,11 @@ /** * Decodes strings according to the XML 1.0 specification. * + *

    + * Public access is through {@link StringLookupFactory}. + *

    + * + * @see StringLookupFactory * @see StringEscapeUtils#unescapeXml(String) */ final class XmlDecoderStringLookup extends AbstractStringLookup { diff --git a/src/main/java/org/apache/commons/text/lookup/XmlEncoderStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlEncoderStringLookup.java index 50e6ffbc4e..b70cd20c9e 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlEncoderStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlEncoderStringLookup.java @@ -22,6 +22,11 @@ /** * Encodes strings according to the XML 1.0 specification. * + *

    + * Public access is through {@link StringLookupFactory}. + *

    + * + * @see StringLookupFactory * @see StringEscapeUtils#escapeXml10(String) * @since 1.11.0 */ diff --git a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java index 0f3663fd45..a476cc0786 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java @@ -72,7 +72,7 @@ final class XmlStringLookup extends AbstractPathFencedLookup { */ XmlStringLookup(final Map xPathFactoryFeatures, final Path... fences) { super(fences); - this.xPathFactoryFeatures = Objects.requireNonNull(xPathFactoryFeatures, "xPathFactoryFeatures"); + this.xPathFactoryFeatures = Objects.requireNonNull(xPathFactoryFeatures, "xPathFfactoryFeatures"); } /** From caa11a3fd387ab035e165355a6dc882f4422510f Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 29 Aug 2025 08:52:26 -0400 Subject: [PATCH 079/265] Javadoc --- .../text/lookup/StringLookupFactory.java | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java index 8a8b484fdf..e3678f3ff1 100644 --- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java +++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java @@ -391,7 +391,7 @@ Map getDefaultStringLookups() { * StringSubstitutor.createInterpolator().replace("... ${base64Decoder:SGVsbG9Xb3JsZCE=} ...")); * *

    - * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}. + * The examples above convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}. *

    */ static final FunctionStringLookup INSTANCE_BASE64_DECODER = FunctionStringLookup @@ -414,7 +414,7 @@ Map getDefaultStringLookups() { * StringSubstitutor.createInterpolator().replace("... ${base64Encoder:HelloWorld!} ...")); * *

    - * The above examples convert {@code "HelloWorld!"} to {@code "SGVsbG9Xb3JsZCE="}. + * The examples above convert {@code "HelloWorld!"} to {@code "SGVsbG9Xb3JsZCE="}. *

    * Defines the singleton for this class. */ @@ -438,7 +438,7 @@ Map getDefaultStringLookups() { * StringSubstitutor.createInterpolator().replace("... ${env:USER} ...")); * *

    - * The above examples convert (on Linux) {@code "USER"} to the current user name. On Windows 10, you would use {@code "USERNAME"} to the same effect. + * The examples above convert (on Linux) {@code "USER"} to the current user name. On Windows 10, you would use {@code "USERNAME"} to the same effect. *

    */ static final FunctionStringLookup INSTANCE_ENVIRONMENT_VARIABLES = FunctionStringLookup.on(System::getenv); @@ -684,7 +684,7 @@ public void addDefaultStringLookups(final Map stringLookup * StringSubstitutor.createInterpolator().replace("... ${base64Decoder:SGVsbG9Xb3JsZCE=} ...")); * *

    - * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}. + * The examples above convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}. *

    * * @return The Base64DecoderStringLookup singleton instance. @@ -711,7 +711,7 @@ public StringLookup base64DecoderStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${base64Encoder:HelloWorld!} ...")); * *

    - * The above examples convert {@code } to {@code "SGVsbG9Xb3JsZCE="}. + * The examples above convert {@code } to {@code "SGVsbG9Xb3JsZCE="}. *

    * * @return The Base64EncoderStringLookup singleton instance. @@ -738,7 +738,7 @@ public StringLookup base64EncoderStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${base64Decoder:SGVsbG9Xb3JsZCE=} ...")); * *

    - * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}. + * The examples above convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}. *

    * * @return The Base64DecoderStringLookup singleton instance. @@ -790,7 +790,7 @@ public BiStringLookup biFunctionStringLookup(final BiFunction *

    - * The above examples convert {@code java.awt.event.KeyEvent.VK_ESCAPE} to {@code "27"}. + * The examples above convert {@code java.awt.event.KeyEvent.VK_ESCAPE} to {@code "27"}. *

    * * @return The ConstantStringLookup singleton instance. @@ -818,7 +818,7 @@ public StringLookup constantStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${date:yyyy-MM-dd} ...")); * *

    - * The above examples convert {@code "yyyy-MM-dd"} to todays's date, for example, {@code "2019-08-04"}. + * The examples above convert {@code "yyyy-MM-dd"} to todays's date, for example, {@code "2019-08-04"}. *

    * * @return The DateStringLookup singleton instance. @@ -856,7 +856,7 @@ public StringLookup dateStringLookup() { * new StringSubstitutor(variableResolver).replace("... ${dns:address|apache.org} ..."); * *

    - * The above examples convert {@code "address|apache.org"} to the IP address of {@code apache.org}. + * The examples above convert {@code "address|apache.org"} to the IP address of {@code apache.org}. *

    * * @return the DnsStringLookup singleton instance. @@ -883,7 +883,7 @@ public StringLookup dnsStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${env:USER} ...")); * *

    - * The above examples convert (on Linux) {@code "USER"} to the current user name. On Windows 10, you would use {@code "USERNAME"} to the same effect. + * The examples above convert (on Linux) {@code "USER"} to the current user name. On Windows 10, you would use {@code "USERNAME"} to the same effect. *

    * * @return The EnvironmentVariableStringLookup singleton instance. @@ -946,7 +946,7 @@ public StringLookup environmentVariableStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${file:UTF-8:com/domain/document.txt} ...")); * *

    - * The above examples convert {@code "UTF-8:com/domain/document.txt"} to the contents of the file. + * The examples above convert {@code "UTF-8:com/domain/document.txt"} to the contents of the file. *

    * * @return a file StringLookup instance. @@ -1017,7 +1017,7 @@ public StringLookup functionStringLookup(final Function function) * StringSubstitutor.createInterpolator().replace("... ${sys:os.name}, ${env:USER} ...")); * *

    - * The above examples convert {@code "${sys:os.name}, ${env:USER}"} to the OS name and Linux user name. + * The examples above convert {@code "${sys:os.name}, ${env:USER}"} to the OS name and Linux user name. *

    * * @return the default {@link InterpolatorStringLookup}. @@ -1095,7 +1095,7 @@ public StringLookup interpolatorStringLookup(final StringLookup defaultStringLoo * StringSubstitutor.createInterpolator().replace("... ${java:version} ...")); * *

    - * The above examples convert {@code "version"} to the current VM version, for example, {@code "Java version 1.8.0_181"}. + * The examples above convert {@code "version"} to the current VM version, for example, {@code "Java version 1.8.0_181"}. *

    * * @return The JavaPlatformStringLookup singleton instance. @@ -1127,7 +1127,7 @@ public StringLookup javaPlatformStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${localhost:canonical-name} ...")); * *

    - * The above examples convert {@code "canonical-name"} to the current host name, for example, {@code "EXAMPLE.apache.org"}. + * The examples above convert {@code "canonical-name"} to the current host name, for example, {@code "EXAMPLE.apache.org"}. *

    * * @return The InetAddressStringLookup singleton instance. @@ -1159,7 +1159,7 @@ public StringLookup localHostStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${loopbackAddress:canonical-name} ...")); * *

    - * The above examples convert {@code "canonical-name"} to the current host name, for example, {@code "EXAMPLE.apache.org"}. + * The examples above convert {@code "canonical-name"} to the current host name, for example, {@code "EXAMPLE.apache.org"}. *

    * * @return The InetAddressStringLookup singleton instance. @@ -1195,13 +1195,13 @@ public StringLookup nullStringLookup() { * if a lookup causes causes a path to resolve outside of these fences. Otherwise, the result is unfenced to preserved behavior from previous versions. *

    *

    - * We looks up a value for the key in the format "DocumentPath::MyKey". + * We looks up a value for the key in the format {@code "DocumentPath::MyKey"}. *

    *

    * Note the use of "::" instead of ":" to allow for "C:" drive letters in paths. *

    *

    - * For example: "com/domain/document.properties::MyKey". + * For example: {@code "com/domain/document.properties::MyKey"}. *

    * Using a fenced StringLookup *

    @@ -1251,8 +1251,8 @@ public StringLookup nullStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${properties:com/domain/document.properties::MyKey} ...")); * *

    - * The above examples convert {@code "com/domain/document.properties::MyKey"} to the key value in the properties file at the path - * "com/domain/document.properties". + * The examples above convert {@code "com/domain/document.properties::MyKey"} to the key value in the properties file at the path + * {@code "com/domain/document.properties"}. *

    * * @return a Properties StringLookup instance. @@ -1326,7 +1326,7 @@ public StringLookup propertiesStringLookup(final Path... fences) { * StringSubstitutor.createInterpolator().replace("... ${resourceBundle:com.domain.messages:MyKey} ...")); * *

    - * The above examples convert {@code "com.domain.messages:MyKey"} to the key value in the resource bundle at {@code "com.domain.messages"}. + * The examples above convert {@code "com.domain.messages:MyKey"} to the key value in the resource bundle at {@code "com.domain.messages"}. *

    * * @return The ResourceBundleStringLookup singleton instance. @@ -1392,7 +1392,7 @@ public StringLookup resourceBundleStringLookup(final String bundleName) { * String value = new StringSubstitutor(variableResolver).replace("${script:javascript:3 + 4}"); * *

    - * The above examples convert {@code "javascript:3 + 4"} to {@code "7"}. + * The examples above convert {@code "javascript:3 + 4"} to {@code "7"}. *

    * * @return The ScriptStringLookup singleton instance. @@ -1420,7 +1420,7 @@ public StringLookup scriptStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${sys:os.name} ...")); * *

    - * The above examples convert {@code "os.name"} to the operating system name. + * The examples above convert {@code "os.name"} to the operating system name. *

    * * @return The SystemPropertyStringLookup singleton instance. @@ -1452,7 +1452,7 @@ public StringLookup systemPropertyStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${urlDecoder:Hello%20World%21} ...")); * *

    - * The above examples convert {@code "Hello%20World%21"} to {@code "Hello World!"}. + * The examples above convert {@code "Hello%20World%21"} to {@code "Hello World!"}. *

    * * @return The UrlStringLookup singleton instance. @@ -1485,7 +1485,7 @@ public StringLookup urlDecoderStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${urlEncoder:Hello World!} ...")); * *

    - * The above examples convert {@code "Hello World!"} to {@code "Hello%20World%21"}. + * The examples above convert {@code "Hello World!"} to {@code "Hello%20World%21"}. *

    * * @return The UrlStringLookup singleton instance. @@ -1528,7 +1528,7 @@ public StringLookup urlEncoderStringLookup() { * String value = new StringSubstitutor(variableResolver).replace("${url:UTF-8:https://www.apache.org}"); * *

    - * The above examples convert {@code "UTF-8:https://www.apache.org"} to the contents of that page. + * The examples above convert {@code "UTF-8:https://www.apache.org"} to the contents of that page. *

    * * @return The UrlStringLookup singleton instance. @@ -1561,7 +1561,7 @@ public StringLookup urlStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${xmlDecoder:&lt;element&gt;} ...")); * *

    - * The above examples convert {@code "<element>"} to {@code ""}. + * The examples above convert {@code "<element>"} to {@code ""}. *

    * * @return The XmlDecoderStringLookup singleton instance. @@ -1594,7 +1594,7 @@ public StringLookup xmlDecoderStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${xmlEncoder:<element>} ...")); * *

    - * The above examples convert {@code ""} to {@code "<element>"}. + * The examples above convert {@code ""} to {@code "<element>"}. *

    * * @return The XmlEncoderStringLookup singleton instance. @@ -1631,7 +1631,7 @@ public StringLookup xmlEncoderStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${xml:com/domain/document.xml:/path/to/node} ...")); * *

    - * The above examples convert {@code "com/domain/document.xml:/path/to/node"} to the value of the XPath in the XML document. + * The examples above convert {@code "com/domain/document.xml:/path/to/node"} to the value of the XPath in the XML document. *

    * * @return An XML StringLookup instance. @@ -1648,10 +1648,10 @@ public StringLookup xmlStringLookup() { * if a lookup causes causes a path to resolve outside of these fences. Otherwise, the result is unfenced to preserved behavior from previous versions. *

    *

    - * We look up the value for the key in the format "DocumentPath:XPath". + * We look up the value for the key in the format {@code "DocumentPath:XPath"}. *

    *

    - * For example: "com/domain/document.xml:/path/to/node". + * For example: {@code "com/domain/document.xml:/path/to/node"}. *

    *

    * Using a {@link StringLookup} from the {@link StringLookupFactory}: @@ -1668,7 +1668,7 @@ public StringLookup xmlStringLookup() { * StringSubstitutor.createInterpolator().replace("... ${xml:com/domain/document.xml:/path/to/node} ...")); * *

    - * The above examples convert {@code "com/domain/document.xml:/path/to/node"} to the value of the XPath in the XML document. + * The examples above convert {@code "com/domain/document.xml:/path/to/node"} to the value of the XPath in the XML document. *

    * * @param xPathFactoryFeatures XPathFactory features to set. @@ -1687,10 +1687,10 @@ public StringLookup xmlStringLookup(final Map xPathFactoryFeatu * if a lookup causes causes a path to resolve outside of these fences. Otherwise, the result is unfenced to preserved behavior from previous versions. *

    *

    - * We look up the value for the key in the format "DocumentPath:XPath". + * We look up the value for the key in the format {@code "DocumentPath:XPath"}. *

    *

    - * For example: "com/domain/document.xml:/path/to/node". + * For example: {@code "com/domain/document.xml:/path/to/node"}. *

    *

    * Using a {@link StringLookup} from the {@link StringLookupFactory} fenced by the current directory ({@code Paths.get("")}): @@ -1713,7 +1713,7 @@ public StringLookup xmlStringLookup(final Map xPathFactoryFeatu * StringLookupFactory.INSTANCE.xmlStringLookup(Paths.get("")).lookup("../com/domain/document.xml:/path/to/node"); * *

    - * The above examples convert {@code "com/domain/document.xml:/path/to/node"} to the value of the XPath in the XML document. + * The examples above convert {@code "com/domain/document.xml:/path/to/node"} to the value of the XPath in the XML document. *

    *

    * {@link StringSubstitutor} methods like {@link StringSubstitutor#replace(String)} will throw a {@link IllegalArgumentException} when a file doesn't From 3e883ed1d3fff96db53480c2d351a6655de1dae7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 16:11:13 -0400 Subject: [PATCH 080/265] Bump actions/dependency-review-action from 4.7.2 to 4.7.3 (#698) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.2 to 4.7.3. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/bc41886e18ea39df68b1b1245f4184881938e050...595b5aeba73380359d98a5e087f648dbb0edce1b) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.7.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index daed9687ff..1e04392423 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@bc41886e18ea39df68b1b1245f4184881938e050 # v4.7.2 + uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # v4.7.3 From 5ba7929668286593db244bf888e4c94b53d41b21 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 30 Aug 2025 13:29:59 -0400 Subject: [PATCH 081/265] Remove trailing whitespace --- src/conf/spotbugs-exclude-filter.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/conf/spotbugs-exclude-filter.xml b/src/conf/spotbugs-exclude-filter.xml index d918d9f0f8..546e6193a4 100644 --- a/src/conf/spotbugs-exclude-filter.xml +++ b/src/conf/spotbugs-exclude-filter.xml @@ -63,14 +63,14 @@ - + - - + + - + From 53cf6ece273622821c5aa13444800ba94a69be55 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 30 Aug 2025 13:34:54 -0400 Subject: [PATCH 082/265] [TEXT-236] Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException --- src/changes/changes.xml | 1 + src/conf/spotbugs-exclude-filter.xml | 6 +++ .../commons/text/TextStringBuilder.java | 14 +++--- .../TextStringBuilderAppendInsertTest.java | 46 +++++++++++++++++++ 4 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index df97b651b1..362314fa01 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,6 +48,7 @@ The type attribute can be add,update,fix,remove. Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). + Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException. Add experimental CycloneDX VEX file #683. diff --git a/src/conf/spotbugs-exclude-filter.xml b/src/conf/spotbugs-exclude-filter.xml index 546e6193a4..c2b01f6b36 100644 --- a/src/conf/spotbugs-exclude-filter.xml +++ b/src/conf/spotbugs-exclude-filter.xml @@ -73,4 +73,10 @@ + + + + + + diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java index 1f194220fe..503bb0567f 100644 --- a/src/main/java/org/apache/commons/text/TextStringBuilder.java +++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java @@ -2190,7 +2190,7 @@ public int indexOf(final StringMatcher matcher, int startIndex) { * @throws IndexOutOfBoundsException if the index is invalid */ public TextStringBuilder insert(final int index, final boolean value) { - validateIndex(index); + validateRange(index, size); if (value) { ensureCapacityInternal(size + TRUE_STRING_SIZE); System.arraycopy(buffer, index, buffer, index + TRUE_STRING_SIZE, size - index); @@ -2212,7 +2212,7 @@ public TextStringBuilder insert(final int index, final boolean value) { * @throws IndexOutOfBoundsException if the index is invalid */ public TextStringBuilder insert(final int index, final char value) { - validateIndex(index); + validateRange(index, size); ensureCapacityInternal(size + 1); System.arraycopy(buffer, index, buffer, index + 1, size - index); buffer[index] = value; @@ -2229,7 +2229,7 @@ public TextStringBuilder insert(final int index, final char value) { * @throws IndexOutOfBoundsException if the index is invalid */ public TextStringBuilder insert(final int index, final char[] chars) { - validateIndex(index); + validateRange(index, size); if (chars == null) { return insert(index, nullText); } @@ -2254,7 +2254,7 @@ public TextStringBuilder insert(final int index, final char[] chars) { * @throws IndexOutOfBoundsException if any index is invalid */ public TextStringBuilder insert(final int index, final char[] chars, final int offset, final int length) { - validateIndex(index); + validateRange(index, size); if (chars == null) { return insert(index, nullText); } @@ -2346,7 +2346,7 @@ public TextStringBuilder insert(final int index, final Object obj) { * @throws IndexOutOfBoundsException if the index is invalid */ public TextStringBuilder insert(final int index, String str) { - validateIndex(index); + validateRange(index, size); if (str == null) { str = nullText; } @@ -3208,10 +3208,10 @@ public TextStringBuilder trim() { } /** - * Validates that an index is in the range {@code 0 <= index <= size}. + * Validates that an index is in the range {@code 0 <= index < size}. * * @param index the index to test. - * @throws IndexOutOfBoundsException Thrown when the index is not the range {@code 0 <= index <= size}. + * @throws IndexOutOfBoundsException Thrown when the index is not the range {@code 0 <= index < size}. */ protected void validateIndex(final int index) { if (index < 0 || index >= size) { diff --git a/src/test/java/org/apache/commons/text/TextStringBuilderAppendInsertTest.java b/src/test/java/org/apache/commons/text/TextStringBuilderAppendInsertTest.java index 6d7a33c13d..51e431f57c 100644 --- a/src/test/java/org/apache/commons/text/TextStringBuilderAppendInsertTest.java +++ b/src/test/java/org/apache/commons/text/TextStringBuilderAppendInsertTest.java @@ -1133,6 +1133,52 @@ void testInsert() { assertEquals("4.5barbaz", sb.toString()); } + @Test + void testInsertAtEnd() { + final TextStringBuilder sb = new TextStringBuilder(); + assertEquals("", sb.toString()); + sb.insert(0, "Hello"); + assertEquals("Hello", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, "World")); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(6, "World")); + sb.insert(5, true); + assertEquals("Hellotrue", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(10, false)); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-20, false)); + sb.insert(9, 'A'); + assertEquals("HellotrueA", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(11, 'B')); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-2, 'B')); + sb.insert(10, new char[] { 'B', 'C' }); + assertEquals("HellotrueABC", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(13, new char[] { 'D', 'E' })); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, new char[] { 'D', 'E' })); + sb.insert(12, new char[] { 'D', 'E', 'F' }, 1, 1); + assertEquals("HellotrueABCE", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(14, new char[] { 'G', 'H', 'I' }, 1, 2)); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, new char[] { 'G', 'H', 'I' }, 1, 1)); + sb.insert(13, 1.2d); + assertEquals("HellotrueABCE1.2", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(17, 1.3d)); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, 1.3d)); + sb.insert(16, 1f); + assertEquals("HellotrueABCE1.21.0", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(20, 1.3f)); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-3, 1.3f)); + sb.insert(19, 23); + assertEquals("HellotrueABCE1.21.023", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(22, 20)); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-5, -5)); + sb.insert(21, 99L); + assertEquals("HellotrueABCE1.21.02399", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(24, 22L)); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, -1L)); + sb.insert(23, FOO); + assertEquals("HellotrueABCE1.21.02399foo", sb.toString()); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(27, FOO)); + assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-3, FOO)); + } + @Test void testInsertWithNullText() { final TextStringBuilder sb = new TextStringBuilder(); From ac0c6d63ca83a67e88cb0b4c0e1cb580e0ea191e Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 30 Aug 2025 13:35:27 -0400 Subject: [PATCH 083/265] [TEXT-236] Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 362314fa01..4366dbe10e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,7 +48,7 @@ The type attribute can be add,update,fix,remove. Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). - Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException. + Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException. Add experimental CycloneDX VEX file #683. From 125a97f00d275c431abafff6a38b869e272be1cb Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 30 Aug 2025 13:39:51 -0400 Subject: [PATCH 084/265] User ternary expression --- .../java/org/apache/commons/text/TextStringBuilder.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java index 503bb0567f..dcf816f90e 100644 --- a/src/main/java/org/apache/commons/text/TextStringBuilder.java +++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java @@ -1185,13 +1185,10 @@ public TextStringBuilder appendNewLine() { /** * Appends the text representing {@code null} to this string builder. * - * @return this, to enable chaining + * @return this, to enable chaining. */ public TextStringBuilder appendNull() { - if (nullText == null) { - return this; - } - return append(nullText); + return nullText != null ? append(nullText) : this; } /** From b55435665f8c4a051f1407118bfa17ed176793b2 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 30 Aug 2025 13:41:15 -0400 Subject: [PATCH 085/265] Use Objects.toString() --- .../org/apache/commons/text/TextStringBuilder.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java index dcf816f90e..a7db693c2a 100644 --- a/src/main/java/org/apache/commons/text/TextStringBuilder.java +++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java @@ -2322,16 +2322,13 @@ public TextStringBuilder insert(final int index, final long value) { * Inserts the string representation of an object into this builder. Inserting null will use the stored null text * value. * - * @param index the index to add at, must be valid - * @param obj the object to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index to add at, must be valid. + * @param obj the object to insert. + * @return this, to enable chaining. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, final Object obj) { - if (obj == null) { - return insert(index, nullText); - } - return insert(index, obj.toString()); + return insert(index, Objects.toString(obj, nullText)); } /** From 0c3cadeeda1aa01869e1d5f72c25e6176121c11e Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 30 Aug 2025 14:03:06 -0400 Subject: [PATCH 086/265] Use fluent APIs and ternary expressions --- .../commons/text/TextStringBuilder.java | 51 ++++--------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java index a7db693c2a..40d53b1bf4 100644 --- a/src/main/java/org/apache/commons/text/TextStringBuilder.java +++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java @@ -114,10 +114,7 @@ public boolean markSupported() { /** {@inheritDoc} */ @Override public int read() { - if (!ready()) { - return -1; - } - return charAt(pos++); + return ready() ? charAt(pos++) : -1; } /** {@inheritDoc} */ @@ -181,10 +178,7 @@ final class TextStringBuilderTokenizer extends StringTokenizer { @Override public String getContent() { final String str = super.getContent(); - if (str == null) { - return TextStringBuilder.this.toString(); - } - return str; + return str != null ? str : TextStringBuilder.this.toString(); } /** {@inheritDoc} */ @@ -1175,11 +1169,7 @@ public TextStringBuilder appendln(final TextStringBuilder str, final int startIn * @see #setNewLineText(String) */ public TextStringBuilder appendNewLine() { - if (newLine == null) { - append(System.lineSeparator()); - return this; - } - return append(newLine); + return append(newLine == null ? System.lineSeparator() : newLine); } /** @@ -1229,10 +1219,7 @@ public TextStringBuilder appendPadding(final int length, final char padChar) { * @return this, to enable chaining */ public TextStringBuilder appendSeparator(final char separator) { - if (isNotEmpty()) { - append(separator); - } - return this; + return isEmpty() ? this : append(separator); } /** @@ -1246,12 +1233,7 @@ public TextStringBuilder appendSeparator(final char separator) { * @return this, to enable chaining */ public TextStringBuilder appendSeparator(final char standard, final char defaultIfEmpty) { - if (isEmpty()) { - append(defaultIfEmpty); - } else { - append(standard); - } - return this; + return append(isEmpty() ? defaultIfEmpty : standard); } /** @@ -1277,10 +1259,7 @@ public TextStringBuilder appendSeparator(final char standard, final char default * @return this, to enable chaining */ public TextStringBuilder appendSeparator(final char separator, final int loopIndex) { - if (loopIndex > 0) { - append(separator); - } - return this; + return loopIndex > 0 ? append(separator) : this; } /** @@ -1331,10 +1310,7 @@ public TextStringBuilder appendSeparator(final String separator) { * @return this, to enable chaining */ public TextStringBuilder appendSeparator(final String separator, final int loopIndex) { - if (separator != null && loopIndex > 0) { - append(separator); - } - return this; + return separator != null && loopIndex > 0 ? append(separator) : this; } /** @@ -1366,10 +1342,7 @@ public TextStringBuilder appendSeparator(final String separator, final int loopI */ public TextStringBuilder appendSeparator(final String standard, final String defaultIfEmpty) { final String str = isEmpty() ? defaultIfEmpty : standard; - if (str != null) { - append(str); - } - return this; + return str != null ? append(str) : this; } /** @@ -1454,8 +1427,7 @@ public TextStringBuilder appendWithSeparators(final Object[] array, final String final String sep = Objects.toString(separator, StringUtils.EMPTY); append(array[0]); for (int i = 1; i < array.length; i++) { - append(sep); - append(array[i]); + append(sep).append(array[i]); } } return this; @@ -2925,7 +2897,6 @@ public TextStringBuilder reverse() { if (size == 0) { return this; } - final int half = size / 2; final char[] buf = buffer; for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++, rightIdx--) { @@ -2966,9 +2937,7 @@ public String rightString(final int length) { * @since 1.9 */ public TextStringBuilder set(final CharSequence str) { - clear(); - append(str); - return this; + return clear().append(str); } /** From c8058b8353ea0b0d7009dec0c0d7dc7eb5f37c9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 13:34:53 -0700 Subject: [PATCH 087/265] Bump github/codeql-action from 3.29.11 to 3.30.1 (#700) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.11 to 3.30.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/3c3833e0f8c1c83d449a7478aa59c036a9165498...f1f6e5f6af878fb37288ce1c627459e94dbf7d01) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 36b2f321b5..69e3507492 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 + uses: github/codeql-action/init@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 + uses: github/codeql-action/autobuild@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 + uses: github/codeql-action/analyze@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index f5ac42eaa8..ef4beb910d 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 + uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 with: sarif_file: results.sarif From 5d356fd01d231dd27dd7c38cb98761343d364075 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:12:30 -0400 Subject: [PATCH 088/265] Bump github/codeql-action from 3.30.1 to 3.30.3 (#702) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.1 to 3.30.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f1f6e5f6af878fb37288ce1c627459e94dbf7d01...192325c86100d080feab897ff886c34abd4c83a3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 69e3507492..e61f02688c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 + uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 + uses: github/codeql-action/autobuild@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 + uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index ef4beb910d..9f6e1fd0c2 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 + uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 with: sarif_file: results.sarif From d454232e0bb4efb973378180c8ba234087b7dddb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 17:21:29 -0400 Subject: [PATCH 089/265] Bump graalvm.version from 24.2.2 to 25.0.0 (#703) Bumps `graalvm.version` from 24.2.2 to 25.0.0. Updates `org.graalvm.js:js` from 24.2.2 to 25.0.0 - [Release notes](https://github.com/graalvm/graaljs/releases) - [Changelog](https://github.com/oracle/graaljs/blob/master/CHANGELOG.md) - [Commits](https://github.com/graalvm/graaljs/compare/vm-24.2.2...vm-25.0.0) Updates `org.graalvm.js:js-scriptengine` from 24.2.2 to 25.0.0 - [Release notes](https://github.com/graalvm/graaljs/releases) - [Changelog](https://github.com/oracle/graaljs/blob/master/CHANGELOG.md) - [Commits](https://github.com/graalvm/graaljs/compare/vm-24.2.2...vm-25.0.0) Updates `org.graalvm.js:js-language` from 24.2.2 to 25.0.0 - [Release notes](https://github.com/graalvm/graaljs/releases) - [Changelog](https://github.com/oracle/graaljs/blob/master/CHANGELOG.md) - [Commits](https://github.com/graalvm/graaljs/compare/vm-24.2.2...vm-25.0.0) Updates `org.graalvm.truffle:truffle-runtime` from 24.2.2 to 25.0.0 - [Release notes](https://github.com/oracle/graal/releases) - [Commits](https://github.com/oracle/graal/compare/vm-24.2.2...vm-25.0.0) --- updated-dependencies: - dependency-name: org.graalvm.js:js dependency-version: 25.0.0 dependency-type: direct:development update-type: version-update:semver-major - dependency-name: org.graalvm.js:js-scriptengine dependency-version: 25.0.0 dependency-type: direct:development update-type: version-update:semver-major - dependency-name: org.graalvm.js:js-language dependency-version: 25.0.0 dependency-type: direct:development update-type: version-update:semver-major - dependency-name: org.graalvm.truffle:truffle-runtime dependency-version: 25.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8c9b18d74a..e38a59942a 100644 --- a/pom.xml +++ b/pom.xml @@ -500,7 +500,7 @@ [22,) - 24.2.2 + 25.0.0 5.2.0 From 618cc66d41e33652ce8e4d838e2297cd53293d89 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Sep 2025 17:22:11 -0400 Subject: [PATCH 090/265] Bump graalvm.version from 24.2.2 to 25.0.0 #703 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4366dbe10e..092409b28e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,6 +54,7 @@ The type attribute can be add,update,fix,remove. Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #696. Bump org.apache.commons:commons-parent from 85 to 87. + Bump graalvm.version from 24.2.2 to 25.0.0 #703. From ac17677e712c0962b1a145da58e4f3c129505b83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 22:26:46 -0400 Subject: [PATCH 091/265] Bump org.apache.commons:commons-parent from 87 to 88 (#704) Bumps [org.apache.commons:commons-parent](https://github.com/apache/commons-parent) from 87 to 88. - [Changelog](https://github.com/apache/commons-parent/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-parent/commits) --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '88' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e38a59942a..5cf6ea22bb 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 87 + 88 commons-text 1.14.1-SNAPSHOT From db5ea4fe4424ee2b6b002302de1a84da6ba74810 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Sep 2025 22:27:18 -0400 Subject: [PATCH 092/265] Bump org.apache.commons:commons-parent from 87 to 88 #704 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 092409b28e..c0e5169784 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,7 +53,7 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #696. - Bump org.apache.commons:commons-parent from 85 to 87. + Bump org.apache.commons:commons-parent from 85 to 88 #704. Bump graalvm.version from 24.2.2 to 25.0.0 #703. From 1df1c0cdaf5a1101860cf7422d01d06d3d33329d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 22 Sep 2025 13:18:33 -0400 Subject: [PATCH 093/265] Javadoc --- .../commons/text/lookup/AbstractPathFencedLookup.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java b/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java index 2a980ab2d8..c988738830 100644 --- a/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java @@ -30,7 +30,7 @@ abstract class AbstractPathFencedLookup extends AbstractStringLookup { /** - * Fences guarding Path resolution. + * A fence is made of Paths guarding Path resolution. */ protected final List fences; @@ -44,11 +44,11 @@ abstract class AbstractPathFencedLookup extends AbstractStringLookup { } /** - * Gets a Path for the given file name checking that it resolves within our fences. + * Gets a Path for the given file name checking that it resolves within our fence. * * @param fileName the file name to resolve. * @return a fenced Path. - * @throws IllegalArgumentException if the file name is not without our fences. + * @throws IllegalArgumentException if the file name is not without our fence. */ protected Path getPath(final String fileName) { final Path path = Paths.get(fileName); From f3b64e766b6819825217353a76a6864234759c57 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 22 Sep 2025 15:36:41 -0400 Subject: [PATCH 094/265] Internal refactoring Extract a package-private PathFence class from AbstractPathFencedLookup --- .../text/lookup/AbstractPathFencedLookup.java | 29 ++--- .../apache/commons/text/lookup/PathFence.java | 108 ++++++++++++++++++ 2 files changed, 115 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/apache/commons/text/lookup/PathFence.java diff --git a/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java b/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java index c988738830..d077c17766 100644 --- a/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java @@ -14,33 +14,28 @@ * See the license for the specific language governing permissions and * limitations under the license. */ + package org.apache.commons.text.lookup; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; /** - * Abstracts guarding Path lookups with fences. + * Abstracts string lookup that guards Path lookups with a fence. */ abstract class AbstractPathFencedLookup extends AbstractStringLookup { /** * A fence is made of Paths guarding Path resolution. */ - protected final List fences; + protected final PathFence fence; /** * Constructs a new instance. * - * @param fences The fences guarding Path resolution. + * @param paths The fences guarding Path resolution. */ - AbstractPathFencedLookup(final Path... fences) { - this.fences = fences != null ? Arrays.stream(fences).map(Path::toAbsolutePath).collect(Collectors.toList()) : Collections.emptyList(); + AbstractPathFencedLookup(final Path... paths) { + this.fence = PathFence.builder().setPaths(paths).get(); } /** @@ -51,16 +46,6 @@ abstract class AbstractPathFencedLookup extends AbstractStringLookup { * @throws IllegalArgumentException if the file name is not without our fence. */ protected Path getPath(final String fileName) { - final Path path = Paths.get(fileName); - if (fences.isEmpty()) { - return path; - } - final Path pathAbs = path.normalize().toAbsolutePath(); - final Optional first = fences.stream().filter(pathAbs::startsWith).findFirst(); - if (first.isPresent()) { - return path; - } - throw IllegalArgumentExceptions.format("[%s] -> [%s] not in %s", fileName, pathAbs, fences); + return fence.getPath(fileName); } - } diff --git a/src/main/java/org/apache/commons/text/lookup/PathFence.java b/src/main/java/org/apache/commons/text/lookup/PathFence.java new file mode 100644 index 0000000000..0428ef2f8e --- /dev/null +++ b/src/main/java/org/apache/commons/text/lookup/PathFence.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ + +package org.apache.commons.text.lookup; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +/** + * A Path fence guards Path resolution. + * + * Keep package-private. + */ +final class PathFence { + + /** + * Builds {@link PathFence} instances. + */ + static final class Builder implements Supplier { + + /** The empty Path array. */ + private static final Path[] EMPTY = {}; + + /** + * A fence is made of Paths guarding Path resolution. + */ + private Path[] paths = EMPTY; + + /** + * Sets the paths that delineate this fence. + * + * @param paths the paths that delineate this fence. + * @return {@code this} instance. + */ + Builder setPaths(final Path... paths) { + this.paths = paths != null ? paths.clone() : EMPTY; + return this; + } + + @Override + public PathFence get() { + return new PathFence(this); + } + } + + /** + * Creates a new builder. + * + * @return a new builder. + */ + static Builder builder() { + return new Builder(); + } + + /** + * A fence is made of Paths guarding Path resolution. + */ + private final List paths; + + /** + * Constructs a new instance. + * + * @param builder A builder. + */ + private PathFence(final Builder builder) { + this.paths = Arrays.stream(builder.paths).map(Path::toAbsolutePath).collect(Collectors.toList()); + } + + /** + * Gets a Path for the given file name checking that it resolves within our fence. + * + * @param fileName the file name to resolve. + * @return a fenced Path. + * @throws IllegalArgumentException if the file name is not without our fence. + */ + Path getPath(final String fileName) { + final Path path = Paths.get(fileName); + if (paths.isEmpty()) { + return path; + } + final Path pathAbs = path.normalize().toAbsolutePath(); + final Optional first = paths.stream().filter(pathAbs::startsWith).findFirst(); + if (first.isPresent()) { + return path; + } + throw new IllegalArgumentException(String.format("[%s] -> [%s] not in the fence %s", fileName, pathAbs, paths)); + } + +} From 3abedb8b5c48991be87f8a135ab54a0d2b18e532 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 24 Sep 2025 17:40:47 -0400 Subject: [PATCH 095/265] Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0 --- pom.xml | 2 +- src/changes/changes.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5cf6ea22bb..0e51279212 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ text https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content - 3.18.0 + 3.19.0 1.17.7 1.6 false diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c0e5169784..a7e3623057 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,9 +52,10 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. - Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #696. Bump org.apache.commons:commons-parent from 85 to 88 #704. + Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #696. Bump graalvm.version from 24.2.2 to 25.0.0 #703. + Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From e2277f5400cce07039a16d25c0f2f98fdaf26fbf Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 26 Sep 2025 10:45:34 -0400 Subject: [PATCH 096/265] Add GH CI 25 and 26-EA --- .github/workflows/maven.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 4890f722c4..6724e87101 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -27,10 +27,10 @@ jobs: continue-on-error: ${{ matrix.experimental }} strategy: matrix: - java: [ 8, 11, 17, 21, 24 ] + java: [ 8, 11, 17, 21, 25 ] experimental: [false] include: - - java: 25-ea + - java: 26-ea experimental: true steps: From 03bdf123ab8fb6b95187d3b490391bc3a5e2ce13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:48:02 -0400 Subject: [PATCH 097/265] Bump github/codeql-action from 3.30.3 to 3.30.5 (#705) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.3 to 3.30.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/192325c86100d080feab897ff886c34abd4c83a3...3599b3baa15b485a2e49ef411a7a4bb2452e7f93) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e61f02688c..af6cd05036 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 + uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 + uses: github/codeql-action/autobuild@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 + uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 9f6e1fd0c2..7ec7ae6801 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 + uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # 3.29.5 with: sarif_file: results.sarif From 78d5cfaf12d96ba7bb6674e4902a9d663a6c36dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:48:47 -0400 Subject: [PATCH 098/265] Bump actions/dependency-review-action from 4.7.3 to 4.8.0 (#707) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.3 to 4.8.0. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/595b5aeba73380359d98a5e087f648dbb0edce1b...56339e523c0409420f6c2c9a2f4292bbb3c07dd3) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 1e04392423..edfe875664 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # v4.7.3 + uses: actions/dependency-review-action@56339e523c0409420f6c2c9a2f4292bbb3c07dd3 # v4.8.0 From cb7233acd4fc0b98b1e872925e403d2664f148f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:49:01 -0400 Subject: [PATCH 099/265] Bump actions/cache from 4.2.4 to 4.3.0 (#706) Bumps [actions/cache](https://github.com/actions/cache) from 4.2.4 to 4.3.0. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/0400d5f644dc74513175e3cd8d07132dd4860809...0057852bfaa89a56745cba8c7296529d2fc39830) --- updated-dependencies: - dependency-name: actions/cache dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index af6cd05036..96554af907 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -48,7 +48,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From 5ef8eea758e862c5212b9dd91d9074664dc2f6e6 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 1 Oct 2025 15:46:00 -0400 Subject: [PATCH 100/265] Update JMH test data --- .../org/apache/commons/text/lcs-perf-analysis-inputs.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv b/src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv index d000a26c96..53610d3579 100644 --- a/src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv +++ b/src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv @@ -1,5 +1,5 @@ -"This code is free software; you can redistribute it and/or modify it","under the terms of the GNU General Public License version 2 only, as" -"You should have received a copy of the GNU General Public License version","2 along with this work; if not, write to the Free Software Foundation," +"This is test data for a JMH (the Java Microbenchmark Harness) which is used from the class org.apache.commons.text.jmh.LongestCommonSubsequencePerformance." +"The quick brown fox jumps over the lazy dog. A man, a plan, a canal, Panama. Was it a car or a cat I saw? Step on no pets. Rats live on no evil star." "Here, the field iterations will be populated with appropriate values from the @Param annotation by the JMH when it is passed to the benchmark method. The @Setup annotated method is invoked before each invocation of the benchmark and creates a new Hasher ensuring isolation. When the execution is finished, we'll get a result similar to the one below: When running microbenchmarks, it's very important to be aware of optimizations. Otherwise, they may affect the","benchmark results in a very misleading way. To make matters a bit more concrete, let's consider an example: We expect object allocation costs more than doing nothing at all. However, if we run the benchmarks: Apparently finding a place in the TLAB, creating and initializing an object is almost free! Just by looking at these numbers, we should know that something does not quite add up here." "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. This code is free software; you can redistribute it and/or modify it published by the Free Software Foundation. Oracle designates this This code is distributed in the hope that it will be useful, but WITHOUT FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License You should have received a copy of the GNU General Public License version","Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? under the terms of the GNU General Public License version 2 only, as particular file as subject to the *Classpath* exception as provided ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or version 2 for more details (a copy is included in the LICENSE file that 2 along with this work; if not, write to the Free Software Foundation," "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure? Here, the field iterations will be populated with appropriate values from the @Param annotation by the JMH when it is passed to the benchmark method. The @Setup annotated method is invoked before each invocation of the benchmark and creates a new Hasher ensuring isolation. When the execution is finished, we'll get a result similar to the one below: When running microbenchmarks, it's very important to be aware of optimizations. Otherwise, they may affect the","At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat. benchmark results in a very misleading way. To make matters a bit more concrete, let's consider an example: We expect object allocation costs more than doing nothing at all. However, if we run the benchmarks: Apparently finding a place in the TLAB, creating and initializing an object is almost free! Just by looking at these numbers, we should know that something does not quite add up here." From 81f219f61284cd82392085a7210777037c2893ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 17:54:13 -0400 Subject: [PATCH 101/265] Bump github/codeql-action from 3.30.5 to 3.30.6 (#709) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.5 to 3.30.6. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/3599b3baa15b485a2e49ef411a7a4bb2452e7f93...64d10c13136e1c5bce3e5fbde8d4906eeaafc885) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 96554af907..131d8f6927 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # 3.29.5 + uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # 3.29.5 + uses: github/codeql-action/autobuild@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # 3.29.5 + uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 7ec7ae6801..2620d75876 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # 3.29.5 + uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 with: sarif_file: results.sarif From 4ef7194ddcc7ca88c768a72d76f1c64370d462c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 17:55:16 -0400 Subject: [PATCH 102/265] Bump ossf/scorecard-action from 2.4.2 to 2.4.3 (#708) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.2 to 2.4.3. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/05b42c624433fc40578a4040d5cf5e36ddca8cde...4eaacf0543bb3f2c246792bd56e8cdeffafb205a) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-version: 2.4.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 2620d75876..b8af37f418 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -45,7 +45,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # 2.4.2 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # 2.4.3 with: results_file: results.sarif results_format: sarif From 34fec1023b5c55bee9a376bbfdecd9da24b8c515 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 8 Oct 2025 15:35:22 -0400 Subject: [PATCH 103/265] Bump org.apache.commons:commons-parent from 88 to 89 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0e51279212..8f77daf91d 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 88 + 89 commons-text 1.14.1-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index a7e3623057..7dd3974ca6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,7 +52,7 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. - Bump org.apache.commons:commons-parent from 85 to 88 #704. + Bump org.apache.commons:commons-parent from 85 to 89 #704. Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #696. Bump graalvm.version from 24.2.2 to 25.0.0 #703. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From 4d2f10673f1c849c9edfd6090070fa624560931e Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 10 Oct 2025 07:02:09 -0400 Subject: [PATCH 104/265] Fix typo in StringUtils.trunctate() IllegalArgumentException message and test assertion messages --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8f77daf91d..37c2a41b51 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content 3.19.0 - 1.17.7 + 1.17.8 1.6 false 1.37 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 7dd3974ca6..7397803ebb 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,7 +53,7 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. Bump org.apache.commons:commons-parent from 85 to 89 #704. - Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #696. + Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. Bump graalvm.version from 24.2.2 to 25.0.0 #703. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From 0d81869d37e7e0bdf967e466e2471d160a40faa8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Oct 2025 16:04:42 -0400 Subject: [PATCH 105/265] Bump github/codeql-action from 3.30.6 to 4.30.8 (#710) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.6 to 4.30.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/64d10c13136e1c5bce3e5fbde8d4906eeaafc885...f443b600d91635bebf5b0d9ebc620189c0d6fba5) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.30.8 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 131d8f6927..a999a0751b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 + uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 + uses: github/codeql-action/autobuild@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 + uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index b8af37f418..6c7da95500 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 + uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 with: sarif_file: results.sarif From 903d6268519d6093e9a6c3848cd840605af511c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 16:07:51 -0400 Subject: [PATCH 106/265] Bump github/codeql-action from 4.30.8 to 4.30.9 (#711) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.8 to 4.30.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f443b600d91635bebf5b0d9ebc620189c0d6fba5...16140ae1a102900babc80a33c44059580f687047) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.30.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a999a0751b..d3291cb300 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 + uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 + uses: github/codeql-action/autobuild@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 + uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 6c7da95500..40a87e44bf 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 + uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 with: sarif_file: results.sarif From 12b1e6a9cd5fc2c8e0eb08f2594269a933e3e711 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 16:08:06 -0400 Subject: [PATCH 107/265] Bump actions/dependency-review-action from 4.8.0 to 4.8.1 (#712) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.8.0 to 4.8.1. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/56339e523c0409420f6c2c9a2f4292bbb3c07dd3...40c09b7dc99638e5ddb0bfd91c1673effc064d8a) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.8.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index edfe875664..a657a4ae2c 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@56339e523c0409420f6c2c9a2f4292bbb3c07dd3 # v4.8.0 + uses: actions/dependency-review-action@40c09b7dc99638e5ddb0bfd91c1673effc064d8a # v4.8.1 From 76df9e54399018163c8cd92bc1e407c7c4296612 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 19 Oct 2025 08:48:58 -0400 Subject: [PATCH 108/265] Better internal names and comments --- .../text/lookup/AbstractPathFencedLookup.java | 4 +-- .../apache/commons/text/lookup/PathFence.java | 32 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java b/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java index d077c17766..b4fc4601b8 100644 --- a/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/AbstractPathFencedLookup.java @@ -35,7 +35,7 @@ abstract class AbstractPathFencedLookup extends AbstractStringLookup { * @param paths The fences guarding Path resolution. */ AbstractPathFencedLookup(final Path... paths) { - this.fence = PathFence.builder().setPaths(paths).get(); + this.fence = PathFence.builder().setRoots(paths).get(); } /** @@ -46,6 +46,6 @@ abstract class AbstractPathFencedLookup extends AbstractStringLookup { * @throws IllegalArgumentException if the file name is not without our fence. */ protected Path getPath(final String fileName) { - return fence.getPath(fileName); + return fence.apply(fileName); } } diff --git a/src/main/java/org/apache/commons/text/lookup/PathFence.java b/src/main/java/org/apache/commons/text/lookup/PathFence.java index 0428ef2f8e..95b9b615f5 100644 --- a/src/main/java/org/apache/commons/text/lookup/PathFence.java +++ b/src/main/java/org/apache/commons/text/lookup/PathFence.java @@ -26,7 +26,7 @@ import java.util.stream.Collectors; /** - * A Path fence guards Path resolution. + * A Path fence guards against using paths outside of a "fence" of made of root paths. * * Keep package-private. */ @@ -41,9 +41,14 @@ static final class Builder implements Supplier { private static final Path[] EMPTY = {}; /** - * A fence is made of Paths guarding Path resolution. + * A fence is made of root Paths. */ - private Path[] paths = EMPTY; + private Path[] roots = EMPTY; + + @Override + public PathFence get() { + return new PathFence(this); + } /** * Sets the paths that delineate this fence. @@ -51,15 +56,10 @@ static final class Builder implements Supplier { * @param paths the paths that delineate this fence. * @return {@code this} instance. */ - Builder setPaths(final Path... paths) { - this.paths = paths != null ? paths.clone() : EMPTY; + Builder setRoots(final Path... paths) { + this.roots = paths != null ? paths.clone() : EMPTY; return this; } - - @Override - public PathFence get() { - return new PathFence(this); - } } /** @@ -74,7 +74,7 @@ static Builder builder() { /** * A fence is made of Paths guarding Path resolution. */ - private final List paths; + private final List roots; /** * Constructs a new instance. @@ -82,7 +82,7 @@ static Builder builder() { * @param builder A builder. */ private PathFence(final Builder builder) { - this.paths = Arrays.stream(builder.paths).map(Path::toAbsolutePath).collect(Collectors.toList()); + this.roots = Arrays.stream(builder.roots).map(Path::toAbsolutePath).collect(Collectors.toList()); } /** @@ -92,17 +92,17 @@ private PathFence(final Builder builder) { * @return a fenced Path. * @throws IllegalArgumentException if the file name is not without our fence. */ - Path getPath(final String fileName) { + Path apply(final String fileName) { final Path path = Paths.get(fileName); - if (paths.isEmpty()) { + if (roots.isEmpty()) { return path; } final Path pathAbs = path.normalize().toAbsolutePath(); - final Optional first = paths.stream().filter(pathAbs::startsWith).findFirst(); + final Optional first = roots.stream().filter(pathAbs::startsWith).findFirst(); if (first.isPresent()) { return path; } - throw new IllegalArgumentException(String.format("[%s] -> [%s] not in the fence %s", fileName, pathAbs, paths)); + throw new IllegalArgumentException(String.format("[%s] -> [%s] not in the fence %s", fileName, pathAbs, roots)); } } From 346f7ba2b37aa3081a0692e1d3d23266315cccd0 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 19 Oct 2025 08:59:58 -0400 Subject: [PATCH 109/265] Fix grammar --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7578b4da03..4cbe168c3e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -25,6 +25,6 @@ Before you push a pull request, review this list: - [ ] Read the [ASF Generative Tooling Guidance](https://www.apache.org/legal/generative-tooling.html) if you use Artificial Intelligence (AI). - [ ] I used AI to create any part of, or all of, this pull request. - [ ] Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself. -- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best-practice. +- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice. - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. - [ ] Each commit in the pull request should have a meaningful subject line and body. Note that a maintainer may squash commits during the merge process. From 50bfffe72683a7d3816e809edc22f1022bc7a27f Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 19 Oct 2025 09:29:36 -0400 Subject: [PATCH 110/265] Use https scheme in license link --- pom.xml | 2 +- src/conf/security/README.md | 2 +- src/conf/security/VEX.cyclonedx.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 37c2a41b51..3f8dfc0007 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/src/conf/security/README.md b/src/conf/security/README.md index 8629f82a7a..4ac566bc6a 100644 --- a/src/conf/security/README.md +++ b/src/conf/security/README.md @@ -6,7 +6,7 @@ ~ (the "License"); you may not use this file except in compliance with ~ the License. You may obtain a copy of the License at ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ https://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, diff --git a/src/conf/security/VEX.cyclonedx.xml b/src/conf/security/VEX.cyclonedx.xml index dcad061f0e..a347293699 100644 --- a/src/conf/security/VEX.cyclonedx.xml +++ b/src/conf/security/VEX.cyclonedx.xml @@ -7,7 +7,7 @@ ~ (the "License"); you may not use this file except in compliance with ~ the License. You may obtain a copy of the License at ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ https://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, From 9fd0ca67703503557c0f4c08bc6e26f8a1be8f44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:19:38 -0400 Subject: [PATCH 111/265] Bump github/codeql-action from 4.30.9 to 4.31.0 (#714) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.9 to 4.31.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/16140ae1a102900babc80a33c44059580f687047...4e94bd11f71e507f7f87df81788dff88d1dacbfb) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d3291cb300..18730ee4ae 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 + uses: github/codeql-action/init@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 + uses: github/codeql-action/autobuild@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 + uses: github/codeql-action/analyze@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 40a87e44bf..07625fba6f 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 3.29.5 with: sarif_file: results.sarif From 2f516325b0bb87a88e621c904f5ceea6c1eb2750 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:19:57 -0400 Subject: [PATCH 112/265] Bump actions/upload-artifact from 4.6.2 to 5.0.0 (#715) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 5.0.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/ea165f8d65b6e75b540449e92b4886f43607fa02...330a01c490aca151604b8cf639adc76d48f6c5d4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 07625fba6f..31b58e38e8 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -57,7 +57,7 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 with: name: SARIF file path: results.sarif From f8db46df6dbb3dbd5085d005b6055304108eaf37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:55:56 -0400 Subject: [PATCH 113/265] Bump org.apache.commons:commons-parent from 89 to 90 (#713) Bumps [org.apache.commons:commons-parent](https://github.com/apache/commons-parent) from 89 to 90. - [Changelog](https://github.com/apache/commons-parent/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-parent/commits) --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '90' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3f8dfc0007..ed37a53d00 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 89 + 90 commons-text 1.14.1-SNAPSHOT From 388effdf87475ba79c8881392e18809832606715 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 24 Oct 2025 16:56:19 -0400 Subject: [PATCH 114/265] Bump org.apache.commons:commons-parent from 89 to 90 #713 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 7397803ebb..78845b2afa 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,7 +52,7 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. - Bump org.apache.commons:commons-parent from 85 to 89 #704. + Bump org.apache.commons:commons-parent from 85 to 90 #704. Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. Bump graalvm.version from 24.2.2 to 25.0.0 #703. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From 8283f350552eeabb98c87825053f78af58365e7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:56:56 -0400 Subject: [PATCH 115/265] Bump graalvm.version from 25.0.0 to 25.0.1 (#716) Bumps `graalvm.version` from 25.0.0 to 25.0.1. Updates `org.graalvm.js:js` from 25.0.0 to 25.0.1 - [Release notes](https://github.com/graalvm/graaljs/releases) - [Changelog](https://github.com/oracle/graaljs/blob/master/CHANGELOG.md) - [Commits](https://github.com/graalvm/graaljs/compare/vm-25.0.0...vm-25.0.1) Updates `org.graalvm.js:js-scriptengine` from 25.0.0 to 25.0.1 - [Release notes](https://github.com/graalvm/graaljs/releases) - [Changelog](https://github.com/oracle/graaljs/blob/master/CHANGELOG.md) - [Commits](https://github.com/graalvm/graaljs/compare/vm-25.0.0...vm-25.0.1) Updates `org.graalvm.js:js-language` from 25.0.0 to 25.0.1 - [Release notes](https://github.com/graalvm/graaljs/releases) - [Changelog](https://github.com/oracle/graaljs/blob/master/CHANGELOG.md) - [Commits](https://github.com/graalvm/graaljs/compare/vm-25.0.0...vm-25.0.1) Updates `org.graalvm.truffle:truffle-runtime` from 25.0.0 to 25.0.1 - [Release notes](https://github.com/oracle/graal/releases) - [Commits](https://github.com/oracle/graal/compare/vm-25.0.0...vm-25.0.1) --- updated-dependencies: - dependency-name: org.graalvm.js:js dependency-version: 25.0.1 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: org.graalvm.js:js-scriptengine dependency-version: 25.0.1 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: org.graalvm.js:js-language dependency-version: 25.0.1 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: org.graalvm.truffle:truffle-runtime dependency-version: 25.0.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ed37a53d00..072b91361c 100644 --- a/pom.xml +++ b/pom.xml @@ -500,7 +500,7 @@ [22,) - 25.0.0 + 25.0.1 5.2.0 From 57f197870e0aaba57ea60f24544efb61f607d311 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 24 Oct 2025 16:57:29 -0400 Subject: [PATCH 116/265] Bump graalvm.version from 25.0.0 to 25.0.1 #716 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 78845b2afa..2de17e803e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,7 +54,7 @@ The type attribute can be add,update,fix,remove. Bump org.apache.commons:commons-parent from 85 to 90 #704. Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. - Bump graalvm.version from 24.2.2 to 25.0.0 #703. + Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From 4f3555954819dda2a9a0ff6f9a8bd694bee56632 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 26 Oct 2025 15:33:42 -0400 Subject: [PATCH 117/265] No need for Latin --- .../commons/text/similarity/LevenshteinDetailedDistance.java | 3 ++- .../apache/commons/text/similarity/LevenshteinDistance.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java index a25b988b60..7e3df86aba 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java @@ -168,7 +168,8 @@ private static LevenshteinResults limitedCompare(SimilarityInput left, Si * of the cost table. It is also possible to use this to compute the unbounded Levenshtein distance by starting the threshold at 1 and doubling each * time until the distance is found; this is O(dm), where d is the distance. * - * One subtlety comes from needing to ignore entries on the border of our stripe eg. p[] = |#|#|#|* d[] = *|#|#|#| We must ignore the entry to the left + * One subtlety comes from needing to ignore entries on the border of our stripe, for example, + * p[] = |#|#|#|* d[] = *|#|#|#| We must ignore the entry to the left * of the leftmost member We must ignore the entry above the rightmost member * * Another subtlety comes from our stripe running off the matrix if the strings aren't of the same size. Since string s is always swapped to be the diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java index 787279c6ab..0deb2b525a 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java @@ -91,7 +91,8 @@ private static int limitedCompare(SimilarityInput left, SimilarityInput Date: Thu, 30 Oct 2025 11:04:59 +0000 Subject: [PATCH 118/265] [TEXT-235] Add Damerau-Levenshtein distance (#687) * [TEXT-235] Implement Damerau-Levenshtein distance * Fix comment formatting * Fix style and spotbugs --------- Co-authored-by: Eirik Lorgen Tanberg --- .../DamerauLevenshteinDistance.java | 326 ++++++++++++++++++ .../DamerauLevenshteinDistanceTest.java | 220 ++++++++++++ 2 files changed, 546 insertions(+) create mode 100644 src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java create mode 100644 src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java diff --git a/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java new file mode 100644 index 0000000000..d7685ebc29 --- /dev/null +++ b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java @@ -0,0 +1,326 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.similarity; + +/** + * An algorithm for measuring the difference between two character sequences using the + * Damerau-Levenshtein Distance. + * + *

    + * This is the number of changes needed to change one sequence into another, where each change is a single character + * modification (deletion, insertion, substitution, or transposition of two adjacent characters). + *

    + * + * @see Damerau-Levenshtein Distance on Wikipedia + * @since 1.15.0 + */ +public class DamerauLevenshteinDistance implements EditDistance { + + /** + * Utility function to ensure distance is valid according to threshold. + * + * @param distance The distance value + * @param threshold The threshold value + * @return The distance value, or {@code -1} if distance is greater than threshold + */ + private static int clampDistance(final int distance, final int threshold) { + return distance > threshold ? -1 : distance; + } + + /** + * Finds the Damerau-Levenshtein distance between two CharSequences if it's less than or equal to a given threshold. + * + * @param left the first SimilarityInput, must not be null. + * @param right the second SimilarityInput, must not be null. + * @param threshold the target threshold, must not be negative. + * @return result distance, or -1 if distance exceeds threshold + */ + private static int limitedCompare(SimilarityInput left, SimilarityInput right, final int threshold) { + if (left == null || right == null) { + throw new IllegalArgumentException("Left/right inputs must not be null"); + } + + if (threshold < 0) { + throw new IllegalArgumentException("Threshold can not be negative"); + } + + // Implementation based on https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance#Optimal_string_alignment_distance + + int leftLength = left.length(); + int rightLength = right.length(); + + if (leftLength == 0) { + return clampDistance(rightLength, threshold); + } + + if (rightLength == 0) { + return clampDistance(leftLength, threshold); + } + + // Inspired by LevenshteinDistance impl; swap the input strings to consume less memory + if (rightLength > leftLength) { + final SimilarityInput tmp = left; + left = right; + right = tmp; + leftLength = rightLength; + rightLength = right.length(); + } + + // If the difference between the lengths of the strings is greater than the threshold, we must at least do + // threshold operations so we can return early + if (leftLength - rightLength > threshold) { + return -1; + } + + // Use three arrays of minimum possible size to reduce memory usage. This avoids having to create a 2D + // array of size leftLength * rightLength + int[] curr = new int[rightLength + 1]; + int[] prev = new int[rightLength + 1]; + int[] prevPrev = new int[rightLength + 1]; + int[] temp; // Temp variable use to shuffle arrays at the end of each iteration + + int rightIndex, leftIndex, cost, minCost; + + // Changing empty sequence to [0..i] requires i insertions + for (rightIndex = 0; rightIndex <= rightLength; rightIndex++) { + prev[rightIndex] = rightIndex; + } + + // Calculate how many operations it takes to change right[0..rightIndex] into left[0..leftIndex] + // For each iteration + // - curr[i] contains the cost of changing right[0..i] into left[0..leftIndex] + // (computed in current iteration) + // - prev[i] contains the cost of changing right[0..i] into left[0..leftIndex - 1] + // (computed in previous iteration) + // - prevPrev[i] contains the cost of changing right[0..i] into left[0..leftIndex - 2] + // (computed in iteration before previous) + for (leftIndex = 1; leftIndex <= leftLength; leftIndex++) { + // For right[0..0] we must insert leftIndex characters, which means the cost is always leftIndex + curr[0] = leftIndex; + + minCost = Integer.MAX_VALUE; + + for (rightIndex = 1; rightIndex <= rightLength; rightIndex++) { + cost = (left.at(leftIndex - 1) == right.at(rightIndex - 1)) ? 0 : 1; + + // Select cheapest operation + curr[rightIndex] = Math.min( + Math.min( + prev[rightIndex] + 1, // Delete current character + curr[rightIndex - 1] + 1 // Insert current character + ), + prev[rightIndex - 1] + cost // Replace (or no cost if same character) + ); + + // Check if adjacent characters are the same -> transpose if cheaper + if (leftIndex > 1 + && rightIndex > 1 + && left.at(leftIndex - 1) == right.at(rightIndex - 2) + && left.at(leftIndex - 2) == right.at(rightIndex - 1)) { + // Use cost here, to properly handle two subsequent equal letters + curr[rightIndex] = Math.min(curr[rightIndex], prevPrev[rightIndex - 2] + cost); + } + + minCost = Math.min(curr[rightIndex], minCost); + } + + // If there was no total cost for this entire iteration to transform right to left[0..leftIndex], there + // can not be a way to do it below threshold. This is because we have no way to reduce the overall cost + // in later operations. + if (minCost > threshold) { + return -1; + } + + // Rotate arrays for next iteration + temp = prevPrev; + prevPrev = prev; + prev = curr; + curr = temp; + } + + // Prev contains the value computed in the latest iteration + return clampDistance(prev[rightLength], threshold); + } + + /** + * Finds the Damerau-Levenshtein distance between two inputs using optimal string alignment. + * + * @param left the first CharSequence, must not be null. + * @param right the second CharSequence, must not be null. + * @return result distance. + * @throws IllegalArgumentException if either CharSequence input is {@code null}. + */ + private static int unlimitedCompare(SimilarityInput left, SimilarityInput right) { + if (left == null || right == null) { + throw new IllegalArgumentException("Left/right inputs must not be null"); + } + + /* + * Implementation based on https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance#Optimal_string_alignment_distance + */ + + int leftLength = left.length(); + int rightLength = right.length(); + + if (leftLength == 0) { + return rightLength; + } + + if (rightLength == 0) { + return leftLength; + } + + // Inspired by LevenshteinDistance impl; swap the input strings to consume less memory + if (rightLength > leftLength) { + final SimilarityInput tmp = left; + left = right; + right = tmp; + leftLength = rightLength; + rightLength = right.length(); + } + + // Use three arrays of minimum possible size to reduce memory usage. This avoids having to create a 2D + // array of size leftLength * rightLength + int[] curr = new int[rightLength + 1]; + int[] prev = new int[rightLength + 1]; + int[] prevPrev = new int[rightLength + 1]; + int[] temp; // Temp variable use to shuffle arrays at the end of each iteration + + int rightIndex, leftIndex, cost; + + // Changing empty sequence to [0..i] requires i insertions + for (rightIndex = 0; rightIndex <= rightLength; rightIndex++) { + prev[rightIndex] = rightIndex; + } + + // Calculate how many operations it takes to change right[0..rightIndex] into left[0..leftIndex] + // For each iteration + // - curr[i] contains the cost of changing right[0..i] into left[0..leftIndex] + // (computed in current iteration) + // - prev[i] contains the cost of changing right[0..i] into left[0..leftIndex - 1] + // (computed in previous iteration) + // - prevPrev[i] contains the cost of changing right[0..i] into left[0..leftIndex - 2] + // (computed in iteration before previous) + for (leftIndex = 1; leftIndex <= leftLength; leftIndex++) { + // For right[0..0] we must insert leftIndex characters, which means the cost is always leftIndex + curr[0] = leftIndex; + + for (rightIndex = 1; rightIndex <= rightLength; rightIndex++) { + cost = (left.at(leftIndex - 1) == right.at(rightIndex - 1)) ? 0 : 1; + + // Select cheapest operation + curr[rightIndex] = Math.min( + Math.min( + prev[rightIndex] + 1, // Delete current character + curr[rightIndex - 1] + 1 // Insert current character + ), + prev[rightIndex - 1] + cost // Replace (or no cost if same character) + ); + + // Check if adjacent characters are the same -> transpose if cheaper + if (leftIndex > 1 + && rightIndex > 1 + && left.at(leftIndex - 1) == right.at(rightIndex - 2) + && left.at(leftIndex - 2) == right.at(rightIndex - 1)) { + // Use cost here, to properly handle two subsequent equal letters + curr[rightIndex] = Math.min(curr[rightIndex], prevPrev[rightIndex - 2] + cost); + } + } + + // Rotate arrays for next iteration + temp = prevPrev; + prevPrev = prev; + prev = curr; + curr = temp; + } + + // Prev contains the value computed in the latest iteration + return prev[rightLength]; + } + + /** + * Threshold. + */ + private final Integer threshold; + + /** + * Constructs a default instance that uses a version of the algorithm that does not use a threshold parameter. + */ + public DamerauLevenshteinDistance() { + this(null); + } + + /** + * Constructs a new instance. If the threshold is not null, distance calculations will be limited to a maximum length. + * If the threshold is null, the unlimited version of the algorithm will be used. + * + * @param threshold If this is null then distances calculations will not be limited. This may not be negative. + */ + public DamerauLevenshteinDistance(final Integer threshold) { + if (threshold != null && threshold < 0) { + throw new IllegalArgumentException("Threshold must not be negative"); + } + this.threshold = threshold; + } + + /** + * Computes the Damerau-Levenshtein distance between two Strings. + * + *

    + * A higher score indicates a greater distance. + *

    + * + * @param left the first input, must not be null. + * @param right the second input, must not be null. + * @return result distance, or -1 if threshold is exceeded. + * @throws IllegalArgumentException if either String input {@code null}. + */ + @Override + public Integer apply(final CharSequence left, final CharSequence right) { + return apply(SimilarityInput.input(left), SimilarityInput.input(right)); + } + + /** + * Computes the Damerau-Levenshtein distance between two inputs. + * + *

    + * A higher score indicates a greater distance. + *

    + * + * @param The type of similarity score unit. + * @param left the first input, must not be null. + * @param right the second input, must not be null. + * @return result distance, or -1 if threshold is exceeded. + * @throws IllegalArgumentException if either String input {@code null}. + * @since 1.13.0 + */ + public Integer apply(final SimilarityInput left, final SimilarityInput right) { + if (threshold != null) { + return limitedCompare(left, right, threshold); + } + return unlimitedCompare(left, right); + } + + /** + * Gets the distance threshold. + * + * @return The distance threshold. + */ + public Integer getThreshold() { + return threshold; + } +} diff --git a/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java new file mode 100644 index 0000000000..d1c1dcadc6 --- /dev/null +++ b/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.similarity; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.Arrays; +import java.util.stream.Stream; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +public class DamerauLevenshteinDistanceTest { + + private static DamerauLevenshteinDistance defaultInstance; + + @BeforeAll + static void createInstance() { + defaultInstance = new DamerauLevenshteinDistance(); + } + + @Test + void testGetThresholdDirectlyAfterObjectInstantiation() { + assertNull(defaultInstance.getThreshold()); + } + + @Test + void testGetThresholdIsCorrect() { + DamerauLevenshteinDistance distance = new DamerauLevenshteinDistance(10); + + assertEquals(10, distance.getThreshold()); + } + + @Test + void testNullInputsThrowUnlimited() { + assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply(null, "test")); + assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply("test", null)); + assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply(null, SimilarityInput.input("test"))); + assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply(SimilarityInput.input("test"), null)); + } + + @Test + void testNullInputsThrowLimited() { + DamerauLevenshteinDistance instance = new DamerauLevenshteinDistance(10); + + assertThrows(IllegalArgumentException.class, () -> instance.apply(null, "test")); + assertThrows(IllegalArgumentException.class, () -> instance.apply("test", null)); + assertThrows(IllegalArgumentException.class, () -> instance.apply(null, SimilarityInput.input("test"))); + assertThrows(IllegalArgumentException.class, () -> instance.apply(SimilarityInput.input("test"), null)); + } + + @Test + void testInvalidThresholdThrows() { + assertThrows(IllegalArgumentException.class, () -> new DamerauLevenshteinDistance(-1)); + } + + @ParameterizedTest(name = "DamerauLevenshteinDistance.unlimitedCompare(\"{0}\", \"{1}\") should return {2}") + @MethodSource("unlimitedDamerauLevenshteinDistanceTestCases") + void testCalculateDamerauLevenshteinDistance(String left, String right, int expectedDistance) { + int leftRightDistance = defaultInstance.apply(left, right); + int rightLeftDistance = defaultInstance.apply(right, left); + + assertEquals(expectedDistance, leftRightDistance); + assertEquals(expectedDistance, rightLeftDistance); + } + + @ParameterizedTest(name = "DamerauLevenshteinDistance.unlimitedCompare(\"{0}\", \"{1}\") should return {2} ({3})") + @MethodSource("unlimitedDamerauLevenshteinDistanceTestCases_SimilarityInput") + void testCalculateDamerauLevenshteinDistance_SimilarityInput(String left, String right, int expectedDistance, final Class cls) { + SimilarityInput leftInput = SimilarityInputTest.build(cls, left); + SimilarityInput rightInput = SimilarityInputTest.build(cls, right); + + int leftRightDistance = defaultInstance.apply(leftInput, rightInput); + int rightLeftDistance = defaultInstance.apply(rightInput, leftInput); + + assertEquals(expectedDistance, leftRightDistance); + assertEquals(expectedDistance, rightLeftDistance); + } + + @ParameterizedTest(name = "DamerauLevenshteinDistance.limitedCompare(\"{0}\", \"{1}\") should return {2}") + @MethodSource("limitedDamerauLevenshteinDistanceTestCases") + void testCalculateDamerauLevenshteinDistance(String left, String right, int threshold, int expectedDistance) { + DamerauLevenshteinDistance instance = new DamerauLevenshteinDistance(threshold); + + int leftRightDistance = instance.apply(left, right); + int rightLeftDistance = instance.apply(right, left); + + assertEquals(expectedDistance, leftRightDistance); + assertEquals(expectedDistance, rightLeftDistance); + } + + @ParameterizedTest(name = "DamerauLevenshteinDistance.limitedCompare(\"{0}\", \"{1}\") should return {2}") + @MethodSource("limitedDamerauLevenshteinDistanceTestCases_SimilarityInput") + void testCalculateDamerauLevenshteinDistance_SimilarityInput(String left, String right, int threshold, int expectedDistance, final Class cls) { + DamerauLevenshteinDistance instance = new DamerauLevenshteinDistance(threshold); + + SimilarityInput leftInput = SimilarityInputTest.build(cls, left); + SimilarityInput rightInput = SimilarityInputTest.build(cls, right); + + int leftRightDistance = instance.apply(leftInput, rightInput); + int rightLeftDistance = instance.apply(rightInput, leftInput); + + assertEquals(expectedDistance, leftRightDistance); + assertEquals(expectedDistance, rightLeftDistance); + } + + static Stream unlimitedDamerauLevenshteinDistanceTestCases_SimilarityInput() { + return SimilarityInputTest.similarityInputs() + .flatMap(cls -> unlimitedDamerauLevenshteinDistanceTestCases().map(arguments -> { + Object[] values = Arrays.copyOf(arguments.get(), arguments.get().length + 1); + values[values.length - 1] = cls; + return Arguments.of(values); + })); + } + + static Stream unlimitedDamerauLevenshteinDistanceTestCases() { + return Stream.of( + Arguments.of("", "test", 4), + Arguments.of("test", "", 4), + Arguments.of("kitten", "sitting", 3), + Arguments.of("saturday", "sunday", 3), + Arguments.of("hello", "world", 4), + Arguments.of("algorithm", "logarithm", 3), + Arguments.of("computer", "comptuer", 1), + Arguments.of("receive", "recieve", 1), + Arguments.of("programming", "porgramming", 1), + Arguments.of("test", "tset", 1), + Arguments.of("example", "exmaple", 1), + Arguments.of("transform", "transfrom", 1), + Arguments.of("information", "infromation", 1), + Arguments.of("development", "developemnt", 1), + Arguments.of("password", "passwrod", 1), + Arguments.of("separate", "seperate", 1), + Arguments.of("definitely", "definately", 1), + Arguments.of("occurrence", "occurence", 1), + Arguments.of("necessary", "neccessary", 1), + Arguments.of("restaurant", "restaraunt", 2), + Arguments.of("beginning", "begining", 1), + Arguments.of("government", "goverment", 1), + Arguments.of("abcdefghijklmnop", "ponmlkjihgfedcba", 15), + Arguments.of("AAAAAAAAAA", "BBBBBBBBBB", 10), + Arguments.of("abababababab", "babababababa", 2), + Arguments.of("supercalifragilisticexpialidocious", "supercalifragilisticexpialidocous", 1), + Arguments.of("pneumonoultramicroscopicsilicovolcanoconiosiss", "pneumonoultramicroscopicsilicovolcanoconiosis", 1), + Arguments.of("abcdefg", "gfedcba", 6), + Arguments.of("xyxyxyxyxy", "yxyxyxyxyx", 2), + Arguments.of("aaaaabbbbbccccc", "cccccbbbbbaaaaa", 10), + Arguments.of("thequickbrownfoxjumpsoverthelazydog", "thequickbrownfoxjumpsovrethelazydog", 1), + Arguments.of("antidisestablishmentarianism", "antidisestablishmentarianisn", 1) + ); + } + + static Stream limitedDamerauLevenshteinDistanceTestCases_SimilarityInput() { + return SimilarityInputTest.similarityInputs() + .flatMap(cls -> limitedDamerauLevenshteinDistanceTestCases().map(arguments -> { + Object[] values = Arrays.copyOf(arguments.get(), arguments.get().length + 1); + values[values.length - 1] = cls; + return Arguments.of(values); + })); + } + + static Stream limitedDamerauLevenshteinDistanceTestCases() { + return Stream.of( + Arguments.of("", "test", 10, 4), + Arguments.of("test", "", 10, 4), + Arguments.of("", "test", 2, -1), + Arguments.of("test", "", 2, -1), + Arguments.of("testing long string", "testing", 2, -1), + Arguments.of("kitten", "sitting", 1, -1), + Arguments.of("saturday", "sunday", 3, 3), + Arguments.of("hello", "world", 6, 4), + Arguments.of("algorithm", "logarithm", 1, -1), + Arguments.of("computer", "comptuer", 1, 1), + Arguments.of("receive", "recieve", 3, 1), + Arguments.of("programming", "porgramming", 0, -1), + Arguments.of("test", "tset", 1, 1), + Arguments.of("example", "exmaple", 3, 1), + Arguments.of("transform", "transfrom", 0, -1), + Arguments.of("information", "infromation", 1, 1), + Arguments.of("development", "developemnt", 3, 1), + Arguments.of("password", "passwrod", 0, -1), + Arguments.of("separate", "seperate", 1, 1), + Arguments.of("definitely", "definately", 3, 1), + Arguments.of("occurrence", "occurence", 0, -1), + Arguments.of("necessary", "neccessary", 1, 1), + Arguments.of("restaurant", "restaraunt", 4, 2), + Arguments.of("beginning", "begining", 0, -1), + Arguments.of("government", "goverment", 1, 1), + Arguments.of("abcdefghijklmnop", "ponmlkjihgfedcba", 17, 15), + Arguments.of("AAAAAAAAAA", "BBBBBBBBBB", 5, -1), + Arguments.of("abababababab", "babababababa", 2, 2), + Arguments.of("supercalifragilisticexpialidocious", "supercalifragilisticexpialidocous", 3, 1), + Arguments.of("pneumonoultramicroscopicsilicovolcanoconiosiss", "pneumonoultramicroscopicsilicovolcanoconiosis", 0, -1), + Arguments.of("abcdefg", "gfedcba", 6, 6), + Arguments.of("xyxyxyxyxy", "yxyxyxyxyx", 4, 2), + Arguments.of("aaaaabbbbbccccc", "cccccbbbbbaaaaa", 5, -1), + Arguments.of("thequickbrownfoxjumpsoverthelazydog", "thequickbrownfoxjumpsovrethelazydog", 1, 1), + Arguments.of("antidisestablishmentarianism", "antidisestablishmentarianisn", 3, 1) + ); + } +} From 3e5e7f82cfee4e68c720356d990f8a73820416fb Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Thu, 30 Oct 2025 07:11:13 -0400 Subject: [PATCH 119/265] [TEXT-235] Add Damerau-Levenshtein distance #687 - Update changes.xml - Use final - Add Javadoc - Sort members - Reduce vertical whitespace - Remove extra parentheses --- src/changes/changes.xml | 1 + .../DamerauLevenshteinDistance.java | 4 +- .../DamerauLevenshteinDistanceTest.java | 250 +++++++++--------- 3 files changed, 125 insertions(+), 130 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2de17e803e..366f6c8825 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,7 @@ The type attribute can be add,update,fix,remove. Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException. Add experimental CycloneDX VEX file #683. + Add Damerau-Levenshtein distance #687. Bump org.apache.commons:commons-parent from 85 to 90 #704. Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. diff --git a/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java index d7685ebc29..0aa39accfa 100644 --- a/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java @@ -115,7 +115,7 @@ private static int limitedCompare(SimilarityInput left, SimilarityInput<= rightLength; rightIndex++) { - cost = (left.at(leftIndex - 1) == right.at(rightIndex - 1)) ? 0 : 1; + cost = left.at(leftIndex - 1) == right.at(rightIndex - 1) ? 0 : 1; // Select cheapest operation curr[rightIndex] = Math.min( @@ -220,7 +220,7 @@ private static int unlimitedCompare(SimilarityInput left, SimilarityInput curr[0] = leftIndex; for (rightIndex = 1; rightIndex <= rightLength; rightIndex++) { - cost = (left.at(leftIndex - 1) == right.at(rightIndex - 1)) ? 0 : 1; + cost = left.at(leftIndex - 1) == right.at(rightIndex - 1) ? 0 : 1; // Select cheapest operation curr[rightIndex] = Math.min( diff --git a/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java index d1c1dcadc6..65f664bb57 100644 --- a/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java @@ -16,8 +16,8 @@ */ package org.apache.commons.text.similarity; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.Arrays; @@ -29,6 +29,9 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +/** + * Tests {@link DamerauLevenshteinDistance}. + */ public class DamerauLevenshteinDistanceTest { private static DamerauLevenshteinDistance defaultInstance; @@ -38,95 +41,50 @@ static void createInstance() { defaultInstance = new DamerauLevenshteinDistance(); } - @Test - void testGetThresholdDirectlyAfterObjectInstantiation() { - assertNull(defaultInstance.getThreshold()); - } - - @Test - void testGetThresholdIsCorrect() { - DamerauLevenshteinDistance distance = new DamerauLevenshteinDistance(10); - - assertEquals(10, distance.getThreshold()); - } - - @Test - void testNullInputsThrowUnlimited() { - assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply(null, "test")); - assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply("test", null)); - assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply(null, SimilarityInput.input("test"))); - assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply(SimilarityInput.input("test"), null)); - } - - @Test - void testNullInputsThrowLimited() { - DamerauLevenshteinDistance instance = new DamerauLevenshteinDistance(10); - - assertThrows(IllegalArgumentException.class, () -> instance.apply(null, "test")); - assertThrows(IllegalArgumentException.class, () -> instance.apply("test", null)); - assertThrows(IllegalArgumentException.class, () -> instance.apply(null, SimilarityInput.input("test"))); - assertThrows(IllegalArgumentException.class, () -> instance.apply(SimilarityInput.input("test"), null)); - } - - @Test - void testInvalidThresholdThrows() { - assertThrows(IllegalArgumentException.class, () -> new DamerauLevenshteinDistance(-1)); - } - - @ParameterizedTest(name = "DamerauLevenshteinDistance.unlimitedCompare(\"{0}\", \"{1}\") should return {2}") - @MethodSource("unlimitedDamerauLevenshteinDistanceTestCases") - void testCalculateDamerauLevenshteinDistance(String left, String right, int expectedDistance) { - int leftRightDistance = defaultInstance.apply(left, right); - int rightLeftDistance = defaultInstance.apply(right, left); - - assertEquals(expectedDistance, leftRightDistance); - assertEquals(expectedDistance, rightLeftDistance); - } - - @ParameterizedTest(name = "DamerauLevenshteinDistance.unlimitedCompare(\"{0}\", \"{1}\") should return {2} ({3})") - @MethodSource("unlimitedDamerauLevenshteinDistanceTestCases_SimilarityInput") - void testCalculateDamerauLevenshteinDistance_SimilarityInput(String left, String right, int expectedDistance, final Class cls) { - SimilarityInput leftInput = SimilarityInputTest.build(cls, left); - SimilarityInput rightInput = SimilarityInputTest.build(cls, right); - - int leftRightDistance = defaultInstance.apply(leftInput, rightInput); - int rightLeftDistance = defaultInstance.apply(rightInput, leftInput); - - assertEquals(expectedDistance, leftRightDistance); - assertEquals(expectedDistance, rightLeftDistance); - } - - @ParameterizedTest(name = "DamerauLevenshteinDistance.limitedCompare(\"{0}\", \"{1}\") should return {2}") - @MethodSource("limitedDamerauLevenshteinDistanceTestCases") - void testCalculateDamerauLevenshteinDistance(String left, String right, int threshold, int expectedDistance) { - DamerauLevenshteinDistance instance = new DamerauLevenshteinDistance(threshold); - - int leftRightDistance = instance.apply(left, right); - int rightLeftDistance = instance.apply(right, left); - - assertEquals(expectedDistance, leftRightDistance); - assertEquals(expectedDistance, rightLeftDistance); - } - - @ParameterizedTest(name = "DamerauLevenshteinDistance.limitedCompare(\"{0}\", \"{1}\") should return {2}") - @MethodSource("limitedDamerauLevenshteinDistanceTestCases_SimilarityInput") - void testCalculateDamerauLevenshteinDistance_SimilarityInput(String left, String right, int threshold, int expectedDistance, final Class cls) { - DamerauLevenshteinDistance instance = new DamerauLevenshteinDistance(threshold); - - SimilarityInput leftInput = SimilarityInputTest.build(cls, left); - SimilarityInput rightInput = SimilarityInputTest.build(cls, right); - - int leftRightDistance = instance.apply(leftInput, rightInput); - int rightLeftDistance = instance.apply(rightInput, leftInput); - - assertEquals(expectedDistance, leftRightDistance); - assertEquals(expectedDistance, rightLeftDistance); + static Stream limitedDamerauLevenshteinDistanceTestCases() { + return Stream.of( + Arguments.of("", "test", 10, 4), + Arguments.of("test", "", 10, 4), + Arguments.of("", "test", 2, -1), + Arguments.of("test", "", 2, -1), + Arguments.of("testing long string", "testing", 2, -1), + Arguments.of("kitten", "sitting", 1, -1), + Arguments.of("saturday", "sunday", 3, 3), + Arguments.of("hello", "world", 6, 4), + Arguments.of("algorithm", "logarithm", 1, -1), + Arguments.of("computer", "comptuer", 1, 1), + Arguments.of("receive", "recieve", 3, 1), + Arguments.of("programming", "porgramming", 0, -1), + Arguments.of("test", "tset", 1, 1), + Arguments.of("example", "exmaple", 3, 1), + Arguments.of("transform", "transfrom", 0, -1), + Arguments.of("information", "infromation", 1, 1), + Arguments.of("development", "developemnt", 3, 1), + Arguments.of("password", "passwrod", 0, -1), + Arguments.of("separate", "seperate", 1, 1), + Arguments.of("definitely", "definately", 3, 1), + Arguments.of("occurrence", "occurence", 0, -1), + Arguments.of("necessary", "neccessary", 1, 1), + Arguments.of("restaurant", "restaraunt", 4, 2), + Arguments.of("beginning", "begining", 0, -1), + Arguments.of("government", "goverment", 1, 1), + Arguments.of("abcdefghijklmnop", "ponmlkjihgfedcba", 17, 15), + Arguments.of("AAAAAAAAAA", "BBBBBBBBBB", 5, -1), + Arguments.of("abababababab", "babababababa", 2, 2), + Arguments.of("supercalifragilisticexpialidocious", "supercalifragilisticexpialidocous", 3, 1), + Arguments.of("pneumonoultramicroscopicsilicovolcanoconiosiss", "pneumonoultramicroscopicsilicovolcanoconiosis", 0, -1), + Arguments.of("abcdefg", "gfedcba", 6, 6), + Arguments.of("xyxyxyxyxy", "yxyxyxyxyx", 4, 2), + Arguments.of("aaaaabbbbbccccc", "cccccbbbbbaaaaa", 5, -1), + Arguments.of("thequickbrownfoxjumpsoverthelazydog", "thequickbrownfoxjumpsovrethelazydog", 1, 1), + Arguments.of("antidisestablishmentarianism", "antidisestablishmentarianisn", 3, 1) + ); } - static Stream unlimitedDamerauLevenshteinDistanceTestCases_SimilarityInput() { + static Stream limitedDamerauLevenshteinDistanceTestCases_SimilarityInput() { return SimilarityInputTest.similarityInputs() - .flatMap(cls -> unlimitedDamerauLevenshteinDistanceTestCases().map(arguments -> { - Object[] values = Arrays.copyOf(arguments.get(), arguments.get().length + 1); + .flatMap(cls -> limitedDamerauLevenshteinDistanceTestCases().map(arguments -> { + final Object[] values = Arrays.copyOf(arguments.get(), arguments.get().length + 1); values[values.length - 1] = cls; return Arguments.of(values); })); @@ -169,52 +127,88 @@ static Stream unlimitedDamerauLevenshteinDistanceTestCases() { ); } - static Stream limitedDamerauLevenshteinDistanceTestCases_SimilarityInput() { + static Stream unlimitedDamerauLevenshteinDistanceTestCases_SimilarityInput() { return SimilarityInputTest.similarityInputs() - .flatMap(cls -> limitedDamerauLevenshteinDistanceTestCases().map(arguments -> { - Object[] values = Arrays.copyOf(arguments.get(), arguments.get().length + 1); + .flatMap(cls -> unlimitedDamerauLevenshteinDistanceTestCases().map(arguments -> { + final Object[] values = Arrays.copyOf(arguments.get(), arguments.get().length + 1); values[values.length - 1] = cls; return Arguments.of(values); })); } - static Stream limitedDamerauLevenshteinDistanceTestCases() { - return Stream.of( - Arguments.of("", "test", 10, 4), - Arguments.of("test", "", 10, 4), - Arguments.of("", "test", 2, -1), - Arguments.of("test", "", 2, -1), - Arguments.of("testing long string", "testing", 2, -1), - Arguments.of("kitten", "sitting", 1, -1), - Arguments.of("saturday", "sunday", 3, 3), - Arguments.of("hello", "world", 6, 4), - Arguments.of("algorithm", "logarithm", 1, -1), - Arguments.of("computer", "comptuer", 1, 1), - Arguments.of("receive", "recieve", 3, 1), - Arguments.of("programming", "porgramming", 0, -1), - Arguments.of("test", "tset", 1, 1), - Arguments.of("example", "exmaple", 3, 1), - Arguments.of("transform", "transfrom", 0, -1), - Arguments.of("information", "infromation", 1, 1), - Arguments.of("development", "developemnt", 3, 1), - Arguments.of("password", "passwrod", 0, -1), - Arguments.of("separate", "seperate", 1, 1), - Arguments.of("definitely", "definately", 3, 1), - Arguments.of("occurrence", "occurence", 0, -1), - Arguments.of("necessary", "neccessary", 1, 1), - Arguments.of("restaurant", "restaraunt", 4, 2), - Arguments.of("beginning", "begining", 0, -1), - Arguments.of("government", "goverment", 1, 1), - Arguments.of("abcdefghijklmnop", "ponmlkjihgfedcba", 17, 15), - Arguments.of("AAAAAAAAAA", "BBBBBBBBBB", 5, -1), - Arguments.of("abababababab", "babababababa", 2, 2), - Arguments.of("supercalifragilisticexpialidocious", "supercalifragilisticexpialidocous", 3, 1), - Arguments.of("pneumonoultramicroscopicsilicovolcanoconiosiss", "pneumonoultramicroscopicsilicovolcanoconiosis", 0, -1), - Arguments.of("abcdefg", "gfedcba", 6, 6), - Arguments.of("xyxyxyxyxy", "yxyxyxyxyx", 4, 2), - Arguments.of("aaaaabbbbbccccc", "cccccbbbbbaaaaa", 5, -1), - Arguments.of("thequickbrownfoxjumpsoverthelazydog", "thequickbrownfoxjumpsovrethelazydog", 1, 1), - Arguments.of("antidisestablishmentarianism", "antidisestablishmentarianisn", 3, 1) - ); + @ParameterizedTest(name = "DamerauLevenshteinDistance.unlimitedCompare(\"{0}\", \"{1}\") should return {2}") + @MethodSource("unlimitedDamerauLevenshteinDistanceTestCases") + void testCalculateDamerauLevenshteinDistance(final String left, final String right, final int expectedDistance) { + final int leftRightDistance = defaultInstance.apply(left, right); + final int rightLeftDistance = defaultInstance.apply(right, left); + assertEquals(expectedDistance, leftRightDistance); + assertEquals(expectedDistance, rightLeftDistance); + } + + @ParameterizedTest(name = "DamerauLevenshteinDistance.limitedCompare(\"{0}\", \"{1}\") should return {2}") + @MethodSource("limitedDamerauLevenshteinDistanceTestCases") + void testCalculateDamerauLevenshteinDistance(final String left, final String right, final int threshold, final int expectedDistance) { + final DamerauLevenshteinDistance instance = new DamerauLevenshteinDistance(threshold); + final int leftRightDistance = instance.apply(left, right); + final int rightLeftDistance = instance.apply(right, left); + assertEquals(expectedDistance, leftRightDistance); + assertEquals(expectedDistance, rightLeftDistance); + } + + @ParameterizedTest(name = "DamerauLevenshteinDistance.unlimitedCompare(\"{0}\", \"{1}\") should return {2} ({3})") + @MethodSource("unlimitedDamerauLevenshteinDistanceTestCases_SimilarityInput") + void testCalculateDamerauLevenshteinDistance_SimilarityInput(final String left, final String right, final int expectedDistance, final Class cls) { + final SimilarityInput leftInput = SimilarityInputTest.build(cls, left); + final SimilarityInput rightInput = SimilarityInputTest.build(cls, right); + final int leftRightDistance = defaultInstance.apply(leftInput, rightInput); + final int rightLeftDistance = defaultInstance.apply(rightInput, leftInput); + assertEquals(expectedDistance, leftRightDistance); + assertEquals(expectedDistance, rightLeftDistance); + } + + @ParameterizedTest(name = "DamerauLevenshteinDistance.limitedCompare(\"{0}\", \"{1}\") should return {2}") + @MethodSource("limitedDamerauLevenshteinDistanceTestCases_SimilarityInput") + void testCalculateDamerauLevenshteinDistance_SimilarityInput(final String left, final String right, final int threshold, final int expectedDistance, + final Class cls) { + final DamerauLevenshteinDistance instance = new DamerauLevenshteinDistance(threshold); + final SimilarityInput leftInput = SimilarityInputTest.build(cls, left); + final SimilarityInput rightInput = SimilarityInputTest.build(cls, right); + final int leftRightDistance = instance.apply(leftInput, rightInput); + final int rightLeftDistance = instance.apply(rightInput, leftInput); + assertEquals(expectedDistance, leftRightDistance); + assertEquals(expectedDistance, rightLeftDistance); + } + + @Test + void testGetThresholdDirectlyAfterObjectInstantiation() { + assertNull(defaultInstance.getThreshold()); + } + + @Test + void testGetThresholdIsCorrect() { + final DamerauLevenshteinDistance distance = new DamerauLevenshteinDistance(10); + assertEquals(10, distance.getThreshold()); + } + + @Test + void testInvalidThresholdThrows() { + assertThrows(IllegalArgumentException.class, () -> new DamerauLevenshteinDistance(-1)); + } + + @Test + void testNullInputsThrowLimited() { + final DamerauLevenshteinDistance instance = new DamerauLevenshteinDistance(10); + assertThrows(IllegalArgumentException.class, () -> instance.apply(null, "test")); + assertThrows(IllegalArgumentException.class, () -> instance.apply("test", null)); + assertThrows(IllegalArgumentException.class, () -> instance.apply(null, SimilarityInput.input("test"))); + assertThrows(IllegalArgumentException.class, () -> instance.apply(SimilarityInput.input("test"), null)); + } + + @Test + void testNullInputsThrowUnlimited() { + assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply(null, "test")); + assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply("test", null)); + assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply(null, SimilarityInput.input("test"))); + assertThrows(IllegalArgumentException.class, () -> defaultInstance.apply(SimilarityInput.input("test"), null)); } } From 611c68669c8484388068da44b4e54fb7b5f65c6d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Thu, 30 Oct 2025 07:15:16 -0400 Subject: [PATCH 120/265] The next release will be a feature release 1.15.0 --- pom.xml | 6 +++--- src/changes/changes.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 072b91361c..733d0fde3e 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 90 commons-text - 1.14.1-SNAPSHOT + 1.15.0-SNAPSHOT Apache Commons Text Apache Commons Text is a set of utility functions and reusable components for processing and manipulating text in a Java environment. @@ -39,8 +39,8 @@ text text org.apache.commons.text - 1.14.1 - 1.14.2 + 1.15.0 + 1.15.1 (Java 8+) TEXT 12318221 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 366f6c8825..448824d8c8 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -45,7 +45,7 @@ The type attribute can be add,update,fix,remove. Apache Commons Text Changes - + Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException. From 3d875c2737f921f94e86e10a9b2750be750d2f83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:14:57 -0400 Subject: [PATCH 121/265] Bump org.apache.commons:commons-parent from 90 to 91 (#718) Bumps [org.apache.commons:commons-parent](https://github.com/apache/commons-parent) from 90 to 91. - [Changelog](https://github.com/apache/commons-parent/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-parent/commits) --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '91' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 733d0fde3e..c34914b36d 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 90 + 91 commons-text 1.15.0-SNAPSHOT From c29b1ee259e42d263d3b91df4d6b8bd428425fed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:15:12 -0400 Subject: [PATCH 122/265] Bump github/codeql-action from 4.31.0 to 4.31.2 (#717) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.0 to 4.31.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4e94bd11f71e507f7f87df81788dff88d1dacbfb...0499de31b99561a6d14a36a5f662c2a54f91beee) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 18730ee4ae..a04eb0532f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 3.29.5 + uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 3.29.5 + uses: github/codeql-action/autobuild@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 3.29.5 + uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 31b58e38e8..2372664fcd 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 3.29.5 + uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 with: sarif_file: results.sarif From 342d2549b8c8c9e61a5f1e7a48dce0f8abc5c588 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 31 Oct 2025 17:39:42 -0400 Subject: [PATCH 123/265] Bump org.apache.commons:commons-parent from 90 to 91 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 448824d8c8..61138101f9 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,7 +53,7 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. - Bump org.apache.commons:commons-parent from 85 to 90 #704. + Bump org.apache.commons:commons-parent from 85 to 91 #704. Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From af3e2bff0e3a2b782d1d89164bf23bc475d70ce2 Mon Sep 17 00:00:00 2001 From: Sebb Date: Sat, 1 Nov 2025 16:46:40 +0000 Subject: [PATCH 124/265] Add dependabot email [skip ci] --- .asf.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.asf.yaml b/.asf.yaml index 4522b2ba79..b7e94937c1 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -23,7 +23,8 @@ notifications: pullrequests: issues@commons.apache.org jira_options: link label jobs: notifications@commons.apache.org - issues_bot_dependabot: notifications@commons.apache.org - pullrequests_bot_dependabot: notifications@commons.apache.org + # commits_bot_dependabot: dependabot@commons.apache.org + issues_bot_dependabot: dependabot@commons.apache.org + pullrequests_bot_dependabot: dependabot@commons.apache.org issues_bot_codecov-commenter: notifications@commons.apache.org pullrequests_bot_codecov-commenter: notifications@commons.apache.org From 7c7a06a7a50d57b1ebcd8a8a8b39d7264de6279c Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 2 Nov 2025 10:36:59 -0500 Subject: [PATCH 125/265] Use HTTPS in URL --- .../apache/commons/text/StringEscapeUtils.java | 8 ++++---- .../commons/text/diff/StringsComparator.java | 4 ++-- .../LevenshteinDetailedDistance.java | 14 +++++++------- .../text/similarity/LevenshteinDistance.java | 6 +++--- .../commons/text/translate/EntityArrays.java | 2 +- src/site/xdoc/userguide.xml | 18 +++++++++--------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/apache/commons/text/StringEscapeUtils.java b/src/main/java/org/apache/commons/text/StringEscapeUtils.java index dae5c48ec6..6fc8f27532 100644 --- a/src/main/java/org/apache/commons/text/StringEscapeUtils.java +++ b/src/main/java/org/apache/commons/text/StringEscapeUtils.java @@ -576,10 +576,10 @@ public static String escapeHtml3(final String input) { * @param input the {@code String} to escape, may be null * @return a new escaped {@code String}, {@code null} if null string input * @see ISO Entities - * @see HTML 3.2 Character Entities for ISO Latin-1 - * @see HTML 4.0 Character entity references - * @see HTML 4.01 Character References - * @see HTML 4.01 Code positions + * @see HTML 3.2 Character Entities for ISO Latin-1 + * @see HTML 4.0 Character entity references + * @see HTML 4.01 Character References + * @see HTML 4.01 Code positions */ public static String escapeHtml4(final String input) { return ESCAPE_HTML4.translate(input); diff --git a/src/main/java/org/apache/commons/text/diff/StringsComparator.java b/src/main/java/org/apache/commons/text/diff/StringsComparator.java index 99ce43aaa6..db7ff5ac49 100644 --- a/src/main/java/org/apache/commons/text/diff/StringsComparator.java +++ b/src/main/java/org/apache/commons/text/diff/StringsComparator.java @@ -35,7 +35,7 @@ *

    * This class implements the comparison algorithm, which is the very efficient * algorithm from Eugene W. Myers - * + * * An O(ND) Difference Algorithm and Its Variations. This algorithm produces * the shortest possible {@link EditScript edit script} containing all the * {@link EditCommand commands} needed to transform the first sequence into @@ -220,7 +220,7 @@ private Snake buildSnake(final int start, final int diag, final int end1, final * The snake is found using the MYERS Algorithm (this algorithms has * also been implemented in the GNU diff program). This algorithm is * explained in Eugene Myers article: - * + * * An O(ND) Difference Algorithm and Its Variations. *

    * diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java index 7e3df86aba..bec6e7f131 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java @@ -132,7 +132,7 @@ public static LevenshteinDetailedDistance getDefaultInstance() { * *

    * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance - * algorithm from http://www.merriampark.com/ld.htm + * algorithm from http://www.merriampark.com/ld.htm *

    * *
    @@ -274,14 +274,14 @@ private static  LevenshteinResults limitedCompare(SimilarityInput left, Si
          *
          * 

    * The previous implementation of the Levenshtein distance algorithm was from - * http://www.merriampark.com/ld.htm + * http://www.merriampark.com/ld.htm *

    * *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large * strings.
    * This implementation of the Levenshtein distance algorithm is from - * http://www.merriampark.com/ldjava.htm + * http://www.merriampark.com/ldjava.htm *

    * *
    @@ -417,14 +417,14 @@ public LevenshteinDetailedDistance(final Integer threshold) {
          *
          * 

    * The previous implementation of the Levenshtein distance algorithm was from - * http://www.merriampark.com/ld.htm + * http://www.merriampark.com/ld.htm *

    * *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large * strings.
    * This implementation of the Levenshtein distance algorithm is from - * http://www.merriampark.com/ldjava.htm + * http://www.merriampark.com/ldjava.htm *

    * *
    @@ -460,14 +460,14 @@ public LevenshteinResults apply(final CharSequence left, final CharSequence righ
          *
          * 

    * The previous implementation of the Levenshtein distance algorithm was from - * http://www.merriampark.com/ld.htm + * http://www.merriampark.com/ld.htm *

    * *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large * strings.
    * This implementation of the Levenshtein distance algorithm is from - * http://www.merriampark.com/ldjava.htm + * http://www.merriampark.com/ldjava.htm *

    * *
    diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
    index 0deb2b525a..7fdbc6fb8f 100644
    --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
    +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
    @@ -55,7 +55,7 @@ public static LevenshteinDistance getDefaultInstance() {
          *
          * 

    * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance - * algorithm from http://www.merriampark.com/ld.htm + * algorithm from http://www.merriampark.com/ld.htm *

    * *
    @@ -324,14 +324,14 @@ public LevenshteinDistance(final Integer threshold) {
          *
          * 

    * The previous implementation of the Levenshtein distance algorithm was from - * http://www.merriampark.com/ld.htm + * http://www.merriampark.com/ld.htm *

    * *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large * strings.
    * This implementation of the Levenshtein distance algorithm is from - * http://www.merriampark.com/ldjava.htm + * http://www.merriampark.com/ldjava.htm *

    * *
    diff --git a/src/main/java/org/apache/commons/text/translate/EntityArrays.java b/src/main/java/org/apache/commons/text/translate/EntityArrays.java
    index e977532e49..262fd52451 100644
    --- a/src/main/java/org/apache/commons/text/translate/EntityArrays.java
    +++ b/src/main/java/org/apache/commons/text/translate/EntityArrays.java
    @@ -150,7 +150,7 @@ public class EntityArrays {
     
         /**
          * A Map<CharSequence, CharSequence> to escape additional
    -     * character entity
    +     * character entity
          * references. Note that this must be used with {@link #ISO8859_1_ESCAPE} to get the full list of
          * HTML 4.0 character entities.
          */
    diff --git a/src/site/xdoc/userguide.xml b/src/site/xdoc/userguide.xml
    index 9d9f733f69..569256be8d 100644
    --- a/src/site/xdoc/userguide.xml
    +++ b/src/site/xdoc/userguide.xml
    @@ -88,10 +88,10 @@ limitations under the License.
             

    - For details see StringSubstitutor. + For details see StringSubstitutor.

    - Use a StringSubstitutorReader + Use a StringSubstitutorReader to avoid reading a whole file into memory as a String to perform string substitution, for example, when a Servlet filters a file to a client.

    @@ -99,13 +99,13 @@ limitations under the License.

    The available substitutions are defined in - org.apache.commons.text.lookup.StringLookupFactory. + org.apache.commons.text.lookup.StringLookupFactory.

    @@ -180,11 +180,11 @@ limitations under the License.

    Provides algorithms for looking up strings used by a - StringSubstitutor. + StringSubstitutor. Standard lookups are defined in - StringLookupFactory + StringLookupFactory and the associated - DefaultStringLookup + DefaultStringLookup enum.

    @@ -192,7 +192,7 @@ limitations under the License. construct a complex string.

    NOTE: The list of lookups available by default changed in version 1.10.0. See the documentation for - StringLookupFactory + StringLookupFactory for details and instructions on how to reproduce the previous behavior.

    From 04d98c4e9d86f2f3eb04079b74885f254fcc8ee8 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 7 Nov 2025 05:58:53 -0500 Subject: [PATCH 126/265] Bump commons-io:commons-io from 2.20.0 to 2.21.0 --- pom.xml | 2 +- src/changes/changes.xml | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index c34914b36d..e54d054494 100644 --- a/pom.xml +++ b/pom.xml @@ -109,7 +109,7 @@ commons-io commons-io - 2.20.0 + 2.21.0 test diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 61138101f9..e12bb48ac8 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,17 +46,18 @@ The type attribute can be add,update,fix,remove. - - Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). - Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException. - - Add experimental CycloneDX VEX file #683. - Add Damerau-Levenshtein distance #687. - - Bump org.apache.commons:commons-parent from 85 to 91 #704. - Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. - Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. - Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. + + Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). + Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException. + + Add experimental CycloneDX VEX file #683. + Add Damerau-Levenshtein distance #687. + + Bump org.apache.commons:commons-parent from 85 to 91 #704. + Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. + Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. + Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. + Bump commons-io:commons-io from 2.20.0 to 2.21.0. From 271181b949d248a3f2397e67c44f834c2951486a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 7 Nov 2025 15:18:39 -0500 Subject: [PATCH 127/265] Typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 29041c11c4..9d1083cc5e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ Making Changes + Respect the original code style: + Only use spaces for indentation; you can check for unnecessary whitespace with `git diff` before committing. + Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first. -+ Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible but is a best-practice. ++ Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible but is a best practice. Unit tests are typically in the `src/test/java` directory. + Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself. + Write a pull request description that is detailed enough to understand what the pull request does, how, and why. From 9398a77cf70f668cf0a72fe5746d3e81b75bc9c7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 8 Nov 2025 11:23:53 -0500 Subject: [PATCH 128/265] No need to override project/issueManagement/system --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index e54d054494..1f331014d0 100644 --- a/pom.xml +++ b/pom.xml @@ -414,7 +414,6 @@ https://gitbox.apache.org/repos/asf?p=commons-text.git - jira https://issues.apache.org/jira/browse/TEXT From 965f90dc297137e703cbd8d3f79b0239de5bef98 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 11 Nov 2025 07:39:01 -0500 Subject: [PATCH 129/265] Javadoc --- .../org/apache/commons/text/lookup/StringLookupFactory.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java index e3678f3ff1..229c410d39 100644 --- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java +++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java @@ -363,7 +363,7 @@ Map getDefaultStringLookups() { /** * Name of the system property used to determine the string lookups added by the {@link #addDefaultStringLookups(Map)} method. Use of this property is only - * required in cases where the set of default lookups must be modified. (See the class documentation for details.) + * required in cases where the set of default lookups must be modified. (See the {@link StringLookupFactory class documentation} for details.) * * @since 1.10.0 */ @@ -657,6 +657,9 @@ private StringLookupFactory(final Path[] fences) { * Adds the default string lookups for this class to {@code stringLookupMap}. The default string lookups are a set of built-in lookups added for convenience * during string interpolation. The defaults may be configured using the {@value #DEFAULT_STRING_LOOKUPS_PROPERTY} system property. See the class * documentation for details and a list of lookups. + *

    + * The format of the property string is a comma-separated list of names from the {@link DefaultStringLookup} enum. + *

    * * @param stringLookupMap the map of string lookups to edit. * @since 1.5 From 0b63d06654e10418ce49f83f882531cf603bf80e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 11 Nov 2025 07:40:04 -0500 Subject: [PATCH 130/265] Javadoc --- .../org/apache/commons/text/lookup/StringLookupFactory.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java index 229c410d39..2f163b8e05 100644 --- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java +++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java @@ -364,6 +364,9 @@ Map getDefaultStringLookups() { /** * Name of the system property used to determine the string lookups added by the {@link #addDefaultStringLookups(Map)} method. Use of this property is only * required in cases where the set of default lookups must be modified. (See the {@link StringLookupFactory class documentation} for details.) + *

    + * The format of the property string is a comma-separated list of names from the {@link DefaultStringLookup} enum. + *

    * * @since 1.10.0 */ From aab6439edd5c25d399d3435d8f79be20994270f9 Mon Sep 17 00:00:00 2001 From: Michael Hausegger Date: Fri, 14 Nov 2025 19:47:03 +0100 Subject: [PATCH 131/265] Add unit tests to increase coverage (#719) * Added new Unit Tests to increase coverage * Remove trailing whitespace * I verified a before-and-after JaCoCo report that each change improved coverage. --------- Co-authored-by: TheRealHaui Co-authored-by: Gary Gregory --- .../commons/text/StringSubstitutorTest.java | 7 +++++++ .../text/similarity/HammingDistanceTest.java | 15 +++++++++++++++ .../text/similarity/JaroWinklerDistanceTest.java | 10 ++++++++++ .../similarity/JaroWinklerSimilarityTest.java | 10 ++++++++++ 4 files changed, 42 insertions(+) diff --git a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java index 0f1fbf4339..3692653f10 100644 --- a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java +++ b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java @@ -1078,4 +1078,11 @@ void testSubstitutePreserveEscape() throws IOException { assertEqualsCharSeq("value $${escaped}", replace(sub, org)); } + @Test + void testDetectsCyclicSubstitution() { + final Map map = new HashMap<>(); + map.put("name", ""); + assertThrows(IllegalStateException.class, () -> StringSubstitutor.replace("Hi !", map, "<", ">")); + } + } diff --git a/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java index 181d2fe277..918a7bedc2 100644 --- a/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java @@ -59,6 +59,21 @@ void testHammingDistance_nullRightValue() { assertThrows(IllegalArgumentException.class, () -> distance.apply("", null)); } + @Test + void testApply_NullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(null, new SimilarityCharacterInput("a"))); + } + + @Test + void testApply_SimilarityInputNull() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), null)); + } + + @Test + void testApply_DifferentSimilarityInputLength() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), new SimilarityCharacterInput("ab"))); + } + @Test void testHammingDistanceCharSequence() { assertEquals(0, distance.apply("", "")); diff --git a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java index f1242fb301..412f1e721c 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java @@ -95,4 +95,14 @@ void testGetJaroWinklerDistance_StringString() { assertEquals(1 - 0.51111d, distance.apply("foo", " foo"), 0.00001d); } + @Test + void testApply_NullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(null, new SimilarityCharacterInput("a"))); + } + + @Test + void testApply_SimilarityInputNull() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), null)); + } + } diff --git a/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java b/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java index a5acfb2394..0b1f97052a 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java @@ -136,4 +136,14 @@ void testGetJaroWinklerSimilarity_StringString() { assertEquals(0.911111d, similarity.apply(wrap("John Horn"), "John Hopkins"), 0.00001d); } + @Test + void testApply_NullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> similarity.apply(null, new SimilarityCharacterInput("a"))); + } + + @Test + void testApply_SimilarityInputNull() { + assertThrows(IllegalArgumentException.class, () -> similarity.apply(new SimilarityCharacterInput("a"), null)); + } + } From 9280e357ac8ef9c9a8b4dc0c35985f9b6a5ef538 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 14 Nov 2025 13:49:03 -0500 Subject: [PATCH 132/265] Add unit tests to increase coverage #719 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e12bb48ac8..21c89d0d00 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,6 +52,7 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. + Add unit tests to increase coverage #719. Bump org.apache.commons:commons-parent from 85 to 91 #704. Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. From 0211ac6868f7329256a093de6b87c67c393cb424 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 14 Nov 2025 13:59:25 -0500 Subject: [PATCH 133/265] Sort members --- .../commons/text/StringSubstitutorTest.java | 14 +++--- .../text/similarity/HammingDistanceTest.java | 48 +++++++++---------- .../similarity/JaroWinklerDistanceTest.java | 20 ++++---- .../similarity/JaroWinklerSimilarityTest.java | 28 +++++------ 4 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java index 3692653f10..75f112ba6b 100644 --- a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java +++ b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java @@ -228,6 +228,13 @@ void testConstructorStringSubstitutor() { assertTrue(target.getVariableSuffixMatcher().toString().endsWith("['s']"), target.getValueDelimiterMatcher().toString()); } + @Test + void testDetectsCyclicSubstitution() { + final Map map = new HashMap<>(); + map.put("name", ""); + assertThrows(IllegalStateException.class, () -> StringSubstitutor.replace("Hi !", map, "<", ">")); + } + /** * Tests get set. */ @@ -1078,11 +1085,4 @@ void testSubstitutePreserveEscape() throws IOException { assertEqualsCharSeq("value $${escaped}", replace(sub, org)); } - @Test - void testDetectsCyclicSubstitution() { - final Map map = new HashMap<>(); - map.put("name", ""); - assertThrows(IllegalStateException.class, () -> StringSubstitutor.replace("Hi !", map, "<", ">")); - } - } diff --git a/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java index 918a7bedc2..0b8e5e133c 100644 --- a/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java @@ -36,42 +36,42 @@ public static void setUp() { distance = new HammingDistance(); } - @ParameterizedTest - @MethodSource("org.apache.commons.text.similarity.SimilarityInputTest#similarityInputsEquals()") - void testHammingDistance(final Class cls) { - assertEquals(0, distance.apply(SimilarityInputTest.build(cls, ""), SimilarityInputTest.build(cls, ""))); - assertEquals(0, distance.apply(SimilarityInputTest.build(cls, "pappa"), SimilarityInputTest.build(cls, "pappa"))); - assertEquals(1, distance.apply(SimilarityInputTest.build(cls, "papaa"), SimilarityInputTest.build(cls, "pappa"))); - assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "karolin"), SimilarityInputTest.build(cls, "kathrin"))); - assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "karolin"), SimilarityInputTest.build(cls, "kerstin"))); - assertEquals(2, distance.apply(SimilarityInputTest.build(cls, "1011101"), SimilarityInputTest.build(cls, "1001001"))); - assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "2173896"), SimilarityInputTest.build(cls, "2233796"))); - assertEquals(2, distance.apply(SimilarityInputTest.build(cls, "ATCG"), SimilarityInputTest.build(cls, "ACCC"))); + @Test + void testApply_DifferentSimilarityInputLength() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), new SimilarityCharacterInput("ab"))); } @Test - void testHammingDistance_nullLeftValue() { - assertThrows(IllegalArgumentException.class, () -> distance.apply(null, "")); - } + void testApply_NullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(null, new SimilarityCharacterInput("a"))); + } @Test - void testHammingDistance_nullRightValue() { - assertThrows(IllegalArgumentException.class, () -> distance.apply("", null)); + void testApply_SimilarityInputNull() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), null)); } - @Test - void testApply_NullSimilarityInput() { - assertThrows(IllegalArgumentException.class, () -> distance.apply(null, new SimilarityCharacterInput("a"))); - } + @ParameterizedTest + @MethodSource("org.apache.commons.text.similarity.SimilarityInputTest#similarityInputsEquals()") + void testHammingDistance(final Class cls) { + assertEquals(0, distance.apply(SimilarityInputTest.build(cls, ""), SimilarityInputTest.build(cls, ""))); + assertEquals(0, distance.apply(SimilarityInputTest.build(cls, "pappa"), SimilarityInputTest.build(cls, "pappa"))); + assertEquals(1, distance.apply(SimilarityInputTest.build(cls, "papaa"), SimilarityInputTest.build(cls, "pappa"))); + assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "karolin"), SimilarityInputTest.build(cls, "kathrin"))); + assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "karolin"), SimilarityInputTest.build(cls, "kerstin"))); + assertEquals(2, distance.apply(SimilarityInputTest.build(cls, "1011101"), SimilarityInputTest.build(cls, "1001001"))); + assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "2173896"), SimilarityInputTest.build(cls, "2233796"))); + assertEquals(2, distance.apply(SimilarityInputTest.build(cls, "ATCG"), SimilarityInputTest.build(cls, "ACCC"))); + } @Test - void testApply_SimilarityInputNull() { - assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), null)); + void testHammingDistance_nullLeftValue() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(null, "")); } @Test - void testApply_DifferentSimilarityInputLength() { - assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), new SimilarityCharacterInput("ab"))); + void testHammingDistance_nullRightValue() { + assertThrows(IllegalArgumentException.class, () -> distance.apply("", null)); } @Test diff --git a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java index 412f1e721c..509d58bb59 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java @@ -36,6 +36,16 @@ public static void setUp() { distance = new JaroWinklerDistance(); } + @Test + void testApply_NullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(null, new SimilarityCharacterInput("a"))); + } + + @Test + void testApply_SimilarityInputNull() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), null)); + } + @ParameterizedTest @MethodSource("org.apache.commons.text.similarity.SimilarityInputTest#similarityInputsEquals()") void testGetJaroWinklerDistance(final Class cls) { @@ -95,14 +105,4 @@ void testGetJaroWinklerDistance_StringString() { assertEquals(1 - 0.51111d, distance.apply("foo", " foo"), 0.00001d); } - @Test - void testApply_NullSimilarityInput() { - assertThrows(IllegalArgumentException.class, () -> distance.apply(null, new SimilarityCharacterInput("a"))); - } - - @Test - void testApply_SimilarityInputNull() { - assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), null)); - } - } diff --git a/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java b/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java index 0b1f97052a..f2a362dc12 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java @@ -78,6 +78,16 @@ public String toString() { }; } + @Test + void testApply_NullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> similarity.apply(null, new SimilarityCharacterInput("a"))); + } + + @Test + void testApply_SimilarityInputNull() { + assertThrows(IllegalArgumentException.class, () -> similarity.apply(new SimilarityCharacterInput("a"), null)); + } + @ParameterizedTest @MethodSource("org.apache.commons.text.similarity.SimilarityInputTest#similarityInputsEquals()") void testGetJaroWinklerSimilarity(final Class cls) { @@ -111,10 +121,10 @@ void testGetJaroWinklerSimilarity_NullString() { assertThrows(IllegalArgumentException.class, () -> similarity.apply(null, "clear")); } - @Test - void testGetJaroWinklerSimilarity_StringNull() { - assertThrows(IllegalArgumentException.class, () -> similarity.apply(" ", null)); - } + @Test + void testGetJaroWinklerSimilarity_StringNull() { + assertThrows(IllegalArgumentException.class, () -> similarity.apply(" ", null)); + } @Test void testGetJaroWinklerSimilarity_StringString() { @@ -136,14 +146,4 @@ void testGetJaroWinklerSimilarity_StringString() { assertEquals(0.911111d, similarity.apply(wrap("John Horn"), "John Hopkins"), 0.00001d); } - @Test - void testApply_NullSimilarityInput() { - assertThrows(IllegalArgumentException.class, () -> similarity.apply(null, new SimilarityCharacterInput("a"))); - } - - @Test - void testApply_SimilarityInputNull() { - assertThrows(IllegalArgumentException.class, () -> similarity.apply(new SimilarityCharacterInput("a"), null)); - } - } From b696bda8326f196803af3deee16528fc8c7400a0 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 15 Nov 2025 08:48:47 -0500 Subject: [PATCH 134/265] No tabs for you --- .../text/similarity/HammingDistanceTest.java | 32 +++++++++---------- .../similarity/JaroWinklerSimilarityTest.java | 16 +++++----- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java index 0b8e5e133c..7eb744856e 100644 --- a/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/HammingDistanceTest.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.text.similarity; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -42,27 +43,27 @@ void testApply_DifferentSimilarityInputLength() { } @Test - void testApply_NullSimilarityInput() { - assertThrows(IllegalArgumentException.class, () -> distance.apply(null, new SimilarityCharacterInput("a"))); - } + void testApply_NullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> distance.apply(null, new SimilarityCharacterInput("a"))); + } @Test void testApply_SimilarityInputNull() { assertThrows(IllegalArgumentException.class, () -> distance.apply(new SimilarityCharacterInput("a"), null)); } - @ParameterizedTest - @MethodSource("org.apache.commons.text.similarity.SimilarityInputTest#similarityInputsEquals()") - void testHammingDistance(final Class cls) { - assertEquals(0, distance.apply(SimilarityInputTest.build(cls, ""), SimilarityInputTest.build(cls, ""))); - assertEquals(0, distance.apply(SimilarityInputTest.build(cls, "pappa"), SimilarityInputTest.build(cls, "pappa"))); - assertEquals(1, distance.apply(SimilarityInputTest.build(cls, "papaa"), SimilarityInputTest.build(cls, "pappa"))); - assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "karolin"), SimilarityInputTest.build(cls, "kathrin"))); - assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "karolin"), SimilarityInputTest.build(cls, "kerstin"))); - assertEquals(2, distance.apply(SimilarityInputTest.build(cls, "1011101"), SimilarityInputTest.build(cls, "1001001"))); - assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "2173896"), SimilarityInputTest.build(cls, "2233796"))); - assertEquals(2, distance.apply(SimilarityInputTest.build(cls, "ATCG"), SimilarityInputTest.build(cls, "ACCC"))); - } + @ParameterizedTest + @MethodSource("org.apache.commons.text.similarity.SimilarityInputTest#similarityInputsEquals()") + void testHammingDistance(final Class cls) { + assertEquals(0, distance.apply(SimilarityInputTest.build(cls, ""), SimilarityInputTest.build(cls, ""))); + assertEquals(0, distance.apply(SimilarityInputTest.build(cls, "pappa"), SimilarityInputTest.build(cls, "pappa"))); + assertEquals(1, distance.apply(SimilarityInputTest.build(cls, "papaa"), SimilarityInputTest.build(cls, "pappa"))); + assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "karolin"), SimilarityInputTest.build(cls, "kathrin"))); + assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "karolin"), SimilarityInputTest.build(cls, "kerstin"))); + assertEquals(2, distance.apply(SimilarityInputTest.build(cls, "1011101"), SimilarityInputTest.build(cls, "1001001"))); + assertEquals(3, distance.apply(SimilarityInputTest.build(cls, "2173896"), SimilarityInputTest.build(cls, "2233796"))); + assertEquals(2, distance.apply(SimilarityInputTest.build(cls, "ATCG"), SimilarityInputTest.build(cls, "ACCC"))); + } @Test void testHammingDistance_nullLeftValue() { @@ -85,5 +86,4 @@ void testHammingDistanceCharSequence() { assertEquals(3, distance.apply("2173896", "2233796")); assertEquals(2, distance.apply("ATCG", "ACCC")); } - } diff --git a/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java b/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java index f2a362dc12..55986ab59d 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaroWinklerSimilarityTest.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.text.similarity; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -79,9 +80,9 @@ public String toString() { } @Test - void testApply_NullSimilarityInput() { - assertThrows(IllegalArgumentException.class, () -> similarity.apply(null, new SimilarityCharacterInput("a"))); - } + void testApply_NullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> similarity.apply(null, new SimilarityCharacterInput("a"))); + } @Test void testApply_SimilarityInputNull() { @@ -121,10 +122,10 @@ void testGetJaroWinklerSimilarity_NullString() { assertThrows(IllegalArgumentException.class, () -> similarity.apply(null, "clear")); } - @Test - void testGetJaroWinklerSimilarity_StringNull() { - assertThrows(IllegalArgumentException.class, () -> similarity.apply(" ", null)); - } + @Test + void testGetJaroWinklerSimilarity_StringNull() { + assertThrows(IllegalArgumentException.class, () -> similarity.apply(" ", null)); + } @Test void testGetJaroWinklerSimilarity_StringString() { @@ -145,5 +146,4 @@ void testGetJaroWinklerSimilarity_StringString() { assertEquals(0.941666d, similarity.apply(wrap("aaabcd"), "aaacdb"), 0.00001d); assertEquals(0.911111d, similarity.apply(wrap("John Horn"), "John Hopkins"), 0.00001d); } - } From 4d8b9098e05f21e7abaa3bc6300a950c8faa4010 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Nov 2025 08:49:54 -0500 Subject: [PATCH 135/265] Bump github/codeql-action from 4.31.2 to 4.31.3 (#721) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.2 to 4.31.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/0499de31b99561a6d14a36a5f662c2a54f91beee...014f16e7ab1402f30e7c3329d33797e7948572db) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a04eb0532f..a3881f0766 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 + uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 + uses: github/codeql-action/autobuild@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 + uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 2372664fcd..8f94802660 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 + uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 with: sarif_file: results.sarif From 45584f05c622e80511ae6327220a59c29d6c0da2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Nov 2025 08:50:04 -0500 Subject: [PATCH 136/265] Bump actions/dependency-review-action from 4.8.1 to 4.8.2 (#720) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.8.1 to 4.8.2. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/40c09b7dc99638e5ddb0bfd91c1673effc064d8a...3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.8.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index a657a4ae2c..11834ed9d1 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@40c09b7dc99638e5ddb0bfd91c1673effc064d8a # v4.8.1 + uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 From d255668d8971dc0f76e399d35dce4e3db3752c08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Nov 2025 08:55:57 -0500 Subject: [PATCH 137/265] Bump org.apache.commons:commons-parent from 91 to 92 (#723) Bumps [org.apache.commons:commons-parent](https://github.com/apache/commons-parent) from 91 to 92. - [Changelog](https://github.com/apache/commons-parent/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-parent/commits) --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '92' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1f331014d0..5d2afd3371 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 91 + 92 commons-text 1.15.0-SNAPSHOT From 5c4c7c35952f4654ef872881fd59d60fd995245d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 15 Nov 2025 08:56:25 -0500 Subject: [PATCH 138/265] Bump org.apache.commons:commons-parent from 91 to 92 #723 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 21c89d0d00..5f913a9d7a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,7 +54,7 @@ The type attribute can be add,update,fix,remove. Add Damerau-Levenshtein distance #687. Add unit tests to increase coverage #719. - Bump org.apache.commons:commons-parent from 85 to 91 #704. + Bump org.apache.commons:commons-parent from 85 to 92 #704, #723. Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From d7bc06c49f28cbbde09c01990b5a3c3ca9a14036 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 15 Nov 2025 08:56:46 -0500 Subject: [PATCH 139/265] Fix typo in exception message for TextStringBuilder --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 5f913a9d7a..b24bd1a0f9 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,7 +48,7 @@ The type attribute can be add,update,fix,remove. Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). - Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException. + Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. From 2b229580f64e8c3cd39e6d172e728e00f21a14cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Nov 2025 09:04:17 -0500 Subject: [PATCH 140/265] Bump commons.bytebuddy.version from 1.17.8 to 1.18.1 (#722) Bumps `commons.bytebuddy.version` from 1.17.8 to 1.18.1. Updates `net.bytebuddy:byte-buddy` from 1.17.8 to 1.18.1 - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.17.8...byte-buddy-1.18.1) Updates `net.bytebuddy:byte-buddy-agent` from 1.17.8 to 1.18.1 - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.17.8...byte-buddy-1.18.1) --- updated-dependencies: - dependency-name: net.bytebuddy:byte-buddy dependency-version: 1.18.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: net.bytebuddy:byte-buddy-agent dependency-version: 1.18.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5d2afd3371..fa0d58d927 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content 3.19.0 - 1.17.8 + 1.18.1 1.6 false 1.37 From 213a883d915799e2b087ab28099536a9d7e1b1c6 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 15 Nov 2025 09:05:03 -0500 Subject: [PATCH 141/265] Bump commons.bytebuddy.version from 1.17.8 to 1.18.1 #722 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index b24bd1a0f9..260ef37daa 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -55,7 +55,7 @@ The type attribute can be add,update,fix,remove. Add unit tests to increase coverage #719. Bump org.apache.commons:commons-parent from 85 to 92 #704, #723. - Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #696. + Bump commons.bytebuddy.version from 1.17.6 to 1.18.1 #696, #722. Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. Bump commons-io:commons-io from 2.20.0 to 2.21.0. From b1f661539eac561501a8a860a3f140bc6937c8d4 Mon Sep 17 00:00:00 2001 From: Sebb Date: Sat, 15 Nov 2025 17:45:49 +0000 Subject: [PATCH 142/265] Dependabot => quarterly --- .github/dependabot.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 00079caf1b..90ec55f742 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -18,10 +18,8 @@ updates: - package-ecosystem: "maven" directory: "/" schedule: - interval: "weekly" - day: "friday" + interval: "quarterly" - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "weekly" - day: "friday" + interval: "quarterly" From b2b5b978ccc1cdcf08e8812f17657a71bdf3b092 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 16 Nov 2025 09:56:56 -0500 Subject: [PATCH 143/265] Bump commons-lang3 from 3.19.0 to 3.20.0 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fa0d58d927..4b221340f6 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ text https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content - 3.19.0 + 3.20.0 1.18.1 1.6 false diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 260ef37daa..a72d382cf3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -57,7 +57,7 @@ The type attribute can be add,update,fix,remove. Bump org.apache.commons:commons-parent from 85 to 92 #704, #723. Bump commons.bytebuddy.version from 1.17.6 to 1.18.1 #696, #722. Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. - Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. + Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-io:commons-io from 2.20.0 to 2.21.0. From c3c3b598220b63aa1776c56482dd4a9345379783 Mon Sep 17 00:00:00 2001 From: Michael Hausegger Date: Tue, 18 Nov 2025 18:47:20 +0100 Subject: [PATCH 144/265] TextStringBuilderTest#testAppendToStringBuffer appends to StringBuffer now (#724) Co-authored-by: TheRealHaui --- .../java/org/apache/commons/text/TextStringBuilderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/apache/commons/text/TextStringBuilderTest.java b/src/test/java/org/apache/commons/text/TextStringBuilderTest.java index 8ef3eaa111..3317543f73 100644 --- a/src/test/java/org/apache/commons/text/TextStringBuilderTest.java +++ b/src/test/java/org/apache/commons/text/TextStringBuilderTest.java @@ -246,7 +246,7 @@ void testAppendToCharBuffer() throws Exception { @Test void testAppendToStringBuffer() throws Exception { final TextStringBuilder sb = new TextStringBuilder("1234567890"); - final StringBuilder buffer = new StringBuilder("Test "); + final StringBuffer buffer = new StringBuffer("Test "); sb.appendTo(buffer); From eb00fd532ac4e3e59772939d434aaf7224fb5246 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 18 Nov 2025 12:49:03 -0500 Subject: [PATCH 145/265] Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index a72d382cf3..ef5abe56ee 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,6 +49,7 @@ The type attribute can be add,update,fix,remove. Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. + Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. From 6f42263ec6e78cf86b697f936a5bed054068c3d6 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 21 Nov 2025 14:25:44 +0000 Subject: [PATCH 146/265] Use HTTPS to download XML Schema --- src/site/xdoc/download_text.xml | 2 +- src/site/xdoc/issue-tracking.xml | 2 +- src/site/xdoc/mail-lists.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/site/xdoc/download_text.xml b/src/site/xdoc/download_text.xml index 12c6a1a08a..4f7cbc7c3a 100644 --- a/src/site/xdoc/download_text.xml +++ b/src/site/xdoc/download_text.xml @@ -58,7 +58,7 @@ limitations under the License. --> + xsi:schemaLocation="https://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Download Apache Commons Text Apache Commons Team diff --git a/src/site/xdoc/issue-tracking.xml b/src/site/xdoc/issue-tracking.xml index 83219a0dd5..9ef2de7e3f 100644 --- a/src/site/xdoc/issue-tracking.xml +++ b/src/site/xdoc/issue-tracking.xml @@ -43,7 +43,7 @@ limitations under the License. --> + xsi:schemaLocation="https://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons Text Issue tracking Apache Commons Team diff --git a/src/site/xdoc/mail-lists.xml b/src/site/xdoc/mail-lists.xml index 806e21bb19..c8734db5fb 100644 --- a/src/site/xdoc/mail-lists.xml +++ b/src/site/xdoc/mail-lists.xml @@ -41,7 +41,7 @@ limitations under the License. --> + xsi:schemaLocation="https://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons Text Mailing Lists Apache Commons Team From db60004c6bdc6d1b15c39fb04c4e9e022d1e1700 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 21 Nov 2025 14:44:48 +0000 Subject: [PATCH 147/265] Bump CodeQL 4.31.4 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a3881f0766..60d115d843 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 + uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 + uses: github/codeql-action/autobuild@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 + uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 8f94802660..d0348717cf 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 + uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 with: sarif_file: results.sarif From 66bafadc42c722ce8e8f99f318408ba5baca13b8 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 21 Nov 2025 19:46:51 +0000 Subject: [PATCH 148/265] Bump actions/checkout from v5.0.0 to v6.0.0 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/maven.yml | 2 +- .github/workflows/scorecards-analysis.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 60d115d843..db1d51c381 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 11834ed9d1..b58ce93016 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: 'Dependency Review PR' uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 6724e87101..882c73abbd 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -34,7 +34,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false - name: Set up JDK ${{ matrix.java }} diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index d0348717cf..4270678db1 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -40,7 +40,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false From 13fe39124867d03110513304edda1312c5c6f0db Mon Sep 17 00:00:00 2001 From: Michael Hausegger Date: Fri, 21 Nov 2025 23:22:10 +0100 Subject: [PATCH 149/265] Added new test for CharSequenceTranslator#with. (#725) * Added new test for CharSequenceTranslator#with. * Fixed typo * Reduce whitespace --------- Co-authored-by: TheRealHaui Co-authored-by: Gary Gregory --- src/changes/changes.xml | 2 +- .../translate/CharSequenceTranslatorTest.java | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ef5abe56ee..e9c6b331a8 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,7 +49,7 @@ The type attribute can be add,update,fix,remove. Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. - Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724. + Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. diff --git a/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java new file mode 100644 index 0000000000..8bc38cae71 --- /dev/null +++ b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.commons.text.translate; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.io.Writer; + +import org.junit.jupiter.api.Test; + + +class CharSequenceTranslatorTest { + + //Used to count translate invocations + private int translateInvocationCounter; + + @Test + void testWith() throws IOException { + CharSequenceTranslator charSequenceTranslatorOne = new TestCharSequenceTranslator(); + CharSequenceTranslator charSequenceTranslatorTwo = new TestCharSequenceTranslator(); + CharSequenceTranslator charSequenceTranslatorThree = new TestCharSequenceTranslator(); + CharSequenceTranslator aggregatedTranslator = charSequenceTranslatorOne.with(charSequenceTranslatorTwo, charSequenceTranslatorThree); + aggregatedTranslator.translate("", 0, null); + assertTrue(aggregatedTranslator instanceof AggregateTranslator); + assertEquals(3, translateInvocationCounter); + } + + private final class TestCharSequenceTranslator extends CharSequenceTranslator { + @Override + public int translate(final CharSequence input, final int index, final Writer writer) { + translateInvocationCounter++; + return 0; + } + + } + +} From 8625878805284992c76ce3a5b0d32fb177f667e3 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 21 Nov 2025 22:24:39 +0000 Subject: [PATCH 150/265] Sort members Use final --- .../translate/CharSequenceTranslatorTest.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java index 8bc38cae71..7585f71df1 100644 --- a/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java +++ b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java @@ -16,8 +16,8 @@ */ package org.apache.commons.text.translate; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.Writer; @@ -27,27 +27,27 @@ class CharSequenceTranslatorTest { + private final class TestCharSequenceTranslator extends CharSequenceTranslator { + @Override + public int translate(final CharSequence input, final int index, final Writer writer) { + translateInvocationCounter++; + return 0; + } + + } + //Used to count translate invocations private int translateInvocationCounter; @Test void testWith() throws IOException { - CharSequenceTranslator charSequenceTranslatorOne = new TestCharSequenceTranslator(); - CharSequenceTranslator charSequenceTranslatorTwo = new TestCharSequenceTranslator(); - CharSequenceTranslator charSequenceTranslatorThree = new TestCharSequenceTranslator(); - CharSequenceTranslator aggregatedTranslator = charSequenceTranslatorOne.with(charSequenceTranslatorTwo, charSequenceTranslatorThree); + final CharSequenceTranslator charSequenceTranslatorOne = new TestCharSequenceTranslator(); + final CharSequenceTranslator charSequenceTranslatorTwo = new TestCharSequenceTranslator(); + final CharSequenceTranslator charSequenceTranslatorThree = new TestCharSequenceTranslator(); + final CharSequenceTranslator aggregatedTranslator = charSequenceTranslatorOne.with(charSequenceTranslatorTwo, charSequenceTranslatorThree); aggregatedTranslator.translate("", 0, null); assertTrue(aggregatedTranslator instanceof AggregateTranslator); assertEquals(3, translateInvocationCounter); } - private final class TestCharSequenceTranslator extends CharSequenceTranslator { - @Override - public int translate(final CharSequence input, final int index, final Writer writer) { - translateInvocationCounter++; - return 0; - } - - } - } From 2eb7d4c39119b7b6419794d2a0c4488afc8044e2 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 21 Nov 2025 22:26:29 +0000 Subject: [PATCH 151/265] Add new test for CharSequenceTranslator#with() #725 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e9c6b331a8..963c8aa72d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,6 +54,7 @@ The type attribute can be add,update,fix,remove. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. Add unit tests to increase coverage #719. + Add new test for CharSequenceTranslator#with() #725. Bump org.apache.commons:commons-parent from 85 to 92 #704, #723. Bump commons.bytebuddy.version from 1.17.6 to 1.18.1 #696, #722. From ecff9a0ad3c7a6287532fa3a4293d41dc810a12f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Nov 2025 08:53:12 -0500 Subject: [PATCH 152/265] Bump org.apache.commons:commons-parent from 92 to 93 (#726) Bumps org.apache.commons:commons-parent from 92 to 93. --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '93' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4b221340f6..b173021fd3 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 92 + 93 commons-text 1.15.0-SNAPSHOT From 05a02e16240d8f4d3f6c623acee41ec916e29440 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 22 Nov 2025 08:53:43 -0500 Subject: [PATCH 153/265] Bump org.apache.commons:commons-parent from 92 to 93 #726 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 963c8aa72d..4a2aaa1c8b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -56,7 +56,7 @@ The type attribute can be add,update,fix,remove. Add unit tests to increase coverage #719. Add new test for CharSequenceTranslator#with() #725. - Bump org.apache.commons:commons-parent from 85 to 92 #704, #723. + Bump org.apache.commons:commons-parent from 85 to 93 #704, #723, #726. Bump commons.bytebuddy.version from 1.17.6 to 1.18.1 #696, #722. Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. From fa7a253aaea60059e418563ee31a3807b8fe5bcd Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 23 Nov 2025 10:01:41 -0500 Subject: [PATCH 154/265] Fix Apache RAT plugin console warnings --- pom.xml | 16 ++++++++-------- src/changes/changes.xml | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index b173021fd3..5a00fd7778 100644 --- a/pom.xml +++ b/pom.xml @@ -139,14 +139,14 @@ org.apache.rat apache-rat-plugin - - site-content/** - src/site/resources/download_text.cgi - src/site/resources/release-notes/RELEASE-NOTES-*.txt - src/test/resources/org/apache/commons/text/stringEscapeUtilsTestData.txt - src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv - src/test/resources/org/apache/commons/text/oss-fuzz/** - + + site-content/** + src/site/resources/download_text.cgi + src/site/resources/release-notes/RELEASE-NOTES-*.txt + src/test/resources/org/apache/commons/text/stringEscapeUtilsTestData.txt + src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv + src/test/resources/org/apache/commons/text/oss-fuzz/** + diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4a2aaa1c8b..b901a067ea 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,6 +50,7 @@ The type attribute can be add,update,fix,remove. Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724. + Fix Apache RAT plugin console warnings. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. From 0c52aa1449895c24088f694f2883fdc3b90e1248 Mon Sep 17 00:00:00 2001 From: Michael Hausegger Date: Wed, 26 Nov 2025 14:00:14 +0100 Subject: [PATCH 155/265] Added new tests for equals method for SimilarityCharacterInput class (#727) Co-authored-by: TheRealHaui --- .../commons/text/similarity/SimilarityCharacterInputTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/org/apache/commons/text/similarity/SimilarityCharacterInputTest.java b/src/test/java/org/apache/commons/text/similarity/SimilarityCharacterInputTest.java index a8d2ae8400..218fce1916 100644 --- a/src/test/java/org/apache/commons/text/similarity/SimilarityCharacterInputTest.java +++ b/src/test/java/org/apache/commons/text/similarity/SimilarityCharacterInputTest.java @@ -42,6 +42,8 @@ void testEquals(final Class cls) { assertNotEquals(similarityInput1, similarityInput4); assertNotEquals(similarityInput2, similarityInput4); assertNotEquals(similarityInput3, similarityInput4); + assertNotEquals(similarityInput1, null); + assertNotEquals(similarityInput1, new Object()); } @ParameterizedTest From 5f0833414a8a5f498f0e04de47235644f97b0f7a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 26 Nov 2025 08:01:47 -0500 Subject: [PATCH 156/265] Add test assertions for SimilarityCharacterInput#equals() class #727 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index b901a067ea..741b7fc46b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -56,6 +56,7 @@ The type attribute can be add,update,fix,remove. Add Damerau-Levenshtein distance #687. Add unit tests to increase coverage #719. Add new test for CharSequenceTranslator#with() #725. + Add test assertions for SimilarityCharacterInput#equals() class #727. Bump org.apache.commons:commons-parent from 85 to 93 #704, #723, #726. Bump commons.bytebuddy.version from 1.17.6 to 1.18.1 #696, #722. From b9fac67ec0cd764924a5dc9181c8bc76fa14c6b5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 26 Nov 2025 08:02:22 -0500 Subject: [PATCH 157/265] Add test assertions for SimilarityCharacterInput#equals() #727 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 741b7fc46b..a04993582f 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -56,7 +56,7 @@ The type attribute can be add,update,fix,remove. Add Damerau-Levenshtein distance #687. Add unit tests to increase coverage #719. Add new test for CharSequenceTranslator#with() #725. - Add test assertions for SimilarityCharacterInput#equals() class #727. + Add test assertions for SimilarityCharacterInput#equals() #727. Bump org.apache.commons:commons-parent from 85 to 93 #704, #723, #726. Bump commons.bytebuddy.version from 1.17.6 to 1.18.1 #696, #722. From 1c87739cbbc866c7ed0eb7fd110688070e3adcca Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 26 Nov 2025 13:06:18 +0000 Subject: [PATCH 158/265] Fix site XML to use version 2.0.0 XML schema --- src/changes/changes.xml | 3 ++- src/site/site.xml | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index a04993582f..c6de2b3687 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,12 +51,13 @@ The type attribute can be add,update,fix,remove. Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724. Fix Apache RAT plugin console warnings. + Fix site XML to use version 2.0.0 XML schema. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. Add unit tests to increase coverage #719. Add new test for CharSequenceTranslator#with() #725. - Add test assertions for SimilarityCharacterInput#equals() #727. + Add test assertions for SimilarityCharacterInput#equals() #727. Bump org.apache.commons:commons-parent from 85 to 93 #704, #723, #726. Bump commons.bytebuddy.version from 1.17.6 to 1.18.1 #696, #722. diff --git a/src/site/site.xml b/src/site/site.xml index cf3fee8aaf..484a229cc1 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -15,13 +15,13 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - Commons Text - /images/logo.png - /index.html - - + + + + @@ -43,4 +43,4 @@ - + From 3f5295bfa4032058a838290d1c888096da2204bd Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 26 Nov 2025 13:09:26 +0000 Subject: [PATCH 159/265] Use new oak leaf logo --- src/media/commons-logo-component-100.xcf | Bin 0 -> 25475 bytes src/media/commons-logo-component.xcf | Bin 0 -> 150711 bytes src/media/logo.png | Bin 0 -> 9454 bytes src/media/logo.xcf | Bin 17288 -> 0 bytes src/site/resources/images/logo.png | Bin 10143 -> 9454 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/media/commons-logo-component-100.xcf create mode 100644 src/media/commons-logo-component.xcf create mode 100644 src/media/logo.png delete mode 100644 src/media/logo.xcf diff --git a/src/media/commons-logo-component-100.xcf b/src/media/commons-logo-component-100.xcf new file mode 100644 index 0000000000000000000000000000000000000000..daba87fdaf87936496a613d983e7a1a63c9817a3 GIT binary patch literal 25475 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 Nt-slP^7~av{a;#jx!nK& literal 0 HcmV?d00001 diff --git a/src/media/commons-logo-component.xcf b/src/media/commons-logo-component.xcf new file mode 100644 index 0000000000000000000000000000000000000000..2c78b608bf420f7053538dedf4ad78944f810d10 GIT binary patch literal 150711 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

    vV}Znc9o_9qOqUO0sbpX}9ug%l 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

    8D-=uSqvL;`|E0`!g|0qG<~sC_#zhwDS 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 z

    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≷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 literal 0 HcmV?d00001 diff --git a/src/media/logo.xcf b/src/media/logo.xcf deleted file mode 100644 index 8b4d18819ea6ff7fc8bcd61e10a6d73d003980e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17288 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 diff --git a/src/site/resources/images/logo.png b/src/site/resources/images/logo.png index 48d4609fec7a387dabaf06f7d5955ba6fbe35259..0c32a3e474662557f6cccc6cfd381a2fecf946ee 100644 GIT binary patch literal 9454 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 literal 10143 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 From 3ed9b5db4debb07953a69daca6c275ed1c8fd291 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 28 Nov 2025 13:29:28 +0000 Subject: [PATCH 160/265] Javadoc --- .../org/apache/commons/text/WordUtils.java | 4 ++-- .../commons/text/similarity/FuzzyScore.java | 6 +++--- .../text/similarity/JaroWinklerDistance.java | 12 ++++++------ .../text/similarity/JaroWinklerSimilarity.java | 12 ++++++------ .../LevenshteinDetailedDistance.java | 18 +++++++++--------- .../text/similarity/LevenshteinDistance.java | 18 +++++++++--------- 6 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/apache/commons/text/WordUtils.java b/src/main/java/org/apache/commons/text/WordUtils.java index ea84d548b7..83f2eec2f1 100644 --- a/src/main/java/org/apache/commons/text/WordUtils.java +++ b/src/main/java/org/apache/commons/text/WordUtils.java @@ -73,8 +73,8 @@ public class WordUtils { * WordUtils.abbreviate("Now is the time for all good men", 20, -1, "")); = "Now is the time for all" * WordUtils.abbreviate("Now is the time for all good men", 50, -1, "")); = "Now is the time for all good men" * WordUtils.abbreviate("Now is the time for all good men", 1000, -1, "")); = "Now is the time for all good men" - * WordUtils.abbreviate("Now is the time for all good men", 9, -10, null)); = IllegalArgumentException - * WordUtils.abbreviate("Now is the time for all good men", 10, 5, null)); = IllegalArgumentException + * WordUtils.abbreviate("Now is the time for all good men", 9, -10, null)); = Throws {@link IllegalArgumentException} + * WordUtils.abbreviate("Now is the time for all good men", 10, 5, null)); = Throws {@link IllegalArgumentException} *

    */ public static String abbreviate(final String str, int lower, int upper, final String appendToEnd) { diff --git a/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java b/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java index 78c96affc5..fd5c447dcd 100644 --- a/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java +++ b/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java @@ -57,9 +57,9 @@ public FuzzyScore(final Locale locale) { * Find the Fuzzy Score which indicates the similarity score between two Strings. * *
    -     * score.fuzzyScore(null, null)                          = IllegalArgumentException
    -     * score.fuzzyScore("not null", null)                    = IllegalArgumentException
    -     * score.fuzzyScore(null, "not null")                    = IllegalArgumentException
    +     * score.fuzzyScore(null, null)                          = Throws {@link IllegalArgumentException}
    +     * score.fuzzyScore("not null", null)                    = Throws {@link IllegalArgumentException}
    +     * score.fuzzyScore(null, "not null")                    = Throws {@link IllegalArgumentException}
          * score.fuzzyScore("", "")                              = 0
          * score.fuzzyScore("Workshop", "b")                     = 0
          * score.fuzzyScore("Room", "o")                         = 1
    diff --git a/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java b/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java
    index 5564b07b4e..cf11a864f7 100644
    --- a/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java
    +++ b/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java
    @@ -55,9 +55,9 @@ public JaroWinklerDistance() {
          * Computes the Jaro Winkler Distance between two character sequences.
          *
          * 
    -     * distance.apply(null, null)          = IllegalArgumentException
    -     * distance.apply("foo", null)         = IllegalArgumentException
    -     * distance.apply(null, "foo")         = IllegalArgumentException
    +     * distance.apply(null, null)          = Throws {@link IllegalArgumentException}
    +     * distance.apply("foo", null)         = Throws {@link IllegalArgumentException}
    +     * distance.apply(null, "foo")         = Throws {@link IllegalArgumentException}
          * distance.apply("", "")              = 0.0
          * distance.apply("foo", "foo")        = 0.0
          * distance.apply("foo", "foo ")       = 0.06
    @@ -92,9 +92,9 @@ public Double apply(final CharSequence left, final CharSequence right) {
          * Computes the Jaro Winkler Distance between two character sequences.
          *
          * 
    -     * distance.apply(null, null)          = IllegalArgumentException
    -     * distance.apply("foo", null)         = IllegalArgumentException
    -     * distance.apply(null, "foo")         = IllegalArgumentException
    +     * distance.apply(null, null)          = Throws {@link IllegalArgumentException}
    +     * distance.apply("foo", null)         = Throws {@link IllegalArgumentException}
    +     * distance.apply(null, "foo")         = Throws {@link IllegalArgumentException}
          * distance.apply("", "")              = 0.0
          * distance.apply("foo", "foo")        = 0.0
          * distance.apply("foo", "foo ")       = 0.06
    diff --git a/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java b/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java
    index e42650fe70..5e67595875 100644
    --- a/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java
    +++ b/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java
    @@ -130,9 +130,9 @@ public JaroWinklerSimilarity() {
          * Computes the Jaro Winkler Similarity between two character sequences.
          *
          * 
    -     * sim.apply(null, null)          = IllegalArgumentException
    -     * sim.apply("foo", null)         = IllegalArgumentException
    -     * sim.apply(null, "foo")         = IllegalArgumentException
    +     * sim.apply(null, null)          = Throws {@link IllegalArgumentException}
    +     * sim.apply("foo", null)         = Throws {@link IllegalArgumentException}
    +     * sim.apply(null, "foo")         = Throws {@link IllegalArgumentException}
          * sim.apply("", "")              = 1.0
          * sim.apply("foo", "foo")        = 1.0
          * sim.apply("foo", "foo ")       = 0.94
    @@ -167,9 +167,9 @@ public Double apply(final CharSequence left, final CharSequence right) {
          * Computes the Jaro Winkler Similarity between two character sequences.
          *
          * 
    -     * sim.apply(null, null)          = IllegalArgumentException
    -     * sim.apply("foo", null)         = IllegalArgumentException
    -     * sim.apply(null, "foo")         = IllegalArgumentException
    +     * sim.apply(null, null)          = Throws {@link IllegalArgumentException}
    +     * sim.apply("foo", null)         = Throws {@link IllegalArgumentException}
    +     * sim.apply(null, "foo")         = Throws {@link IllegalArgumentException}
          * sim.apply("", "")              = 1.0
          * sim.apply("foo", "foo")        = 1.0
          * sim.apply("foo", "foo ")       = 0.94
    diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java
    index bec6e7f131..556eaf1fc3 100644
    --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java
    +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java
    @@ -136,9 +136,9 @@ public static LevenshteinDetailedDistance getDefaultInstance() {
          * 

    * *
    -     * limitedCompare(null, *, *)             = IllegalArgumentException
    -     * limitedCompare(*, null, *)             = IllegalArgumentException
    -     * limitedCompare(*, *, -1)               = IllegalArgumentException
    +     * limitedCompare(null, *, *)             = Throws {@link IllegalArgumentException}
    +     * limitedCompare(*, null, *)             = Throws {@link IllegalArgumentException}
    +     * limitedCompare(*, *, -1)               = Throws {@link IllegalArgumentException}
          * limitedCompare("","", 0)               = 0
          * limitedCompare("aaapppp", "", 8)       = 7
          * limitedCompare("aaapppp", "", 7)       = 7
    @@ -285,8 +285,8 @@ private static  LevenshteinResults limitedCompare(SimilarityInput left, Si
          * 

    * *
    -     * unlimitedCompare(null, *)             = IllegalArgumentException
    -     * unlimitedCompare(*, null)             = IllegalArgumentException
    +     * unlimitedCompare(null, *)             = Throws {@link IllegalArgumentException}
    +     * unlimitedCompare(*, null)             = Throws {@link IllegalArgumentException}
          * unlimitedCompare("","")               = 0
          * unlimitedCompare("","a")              = 1
          * unlimitedCompare("aaapppp", "")       = 7
    @@ -428,8 +428,8 @@ public LevenshteinDetailedDistance(final Integer threshold) {
          * 

    * *
    -     * distance.apply(null, *)             = IllegalArgumentException
    -     * distance.apply(*, null)             = IllegalArgumentException
    +     * distance.apply(null, *)             = Throws {@link IllegalArgumentException}
    +     * distance.apply(*, null)             = Throws {@link IllegalArgumentException}
          * distance.apply("","")               = 0
          * distance.apply("","a")              = 1
          * distance.apply("aaapppp", "")       = 7
    @@ -471,8 +471,8 @@ public LevenshteinResults apply(final CharSequence left, final CharSequence righ
          * 

    * *
    -     * distance.apply(null, *)             = IllegalArgumentException
    -     * distance.apply(*, null)             = IllegalArgumentException
    +     * distance.apply(null, *)             = Throws {@link IllegalArgumentException}
    +     * distance.apply(*, null)             = Throws {@link IllegalArgumentException}
          * distance.apply("","")               = 0
          * distance.apply("","a")              = 1
          * distance.apply("aaapppp", "")       = 7
    diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
    index 7fdbc6fb8f..cb2e272983 100644
    --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
    +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
    @@ -59,9 +59,9 @@ public static LevenshteinDistance getDefaultInstance() {
          * 

    * *
    -     * limitedCompare(null, *, *)             = IllegalArgumentException
    -     * limitedCompare(*, null, *)             = IllegalArgumentException
    -     * limitedCompare(*, *, -1)               = IllegalArgumentException
    +     * limitedCompare(null, *, *)             = Throws {@link IllegalArgumentException}
    +     * limitedCompare(*, null, *)             = Throws {@link IllegalArgumentException}
    +     * limitedCompare(*, *, -1)               = Throws {@link IllegalArgumentException}
          * limitedCompare("","", 0)               = 0
          * limitedCompare("aaapppp", "", 8)       = 7
          * limitedCompare("aaapppp", "", 7)       = 7
    @@ -217,8 +217,8 @@ private static  int limitedCompare(SimilarityInput left, SimilarityInput

    * *
    -     * unlimitedCompare(null, *)             = IllegalArgumentException
    -     * unlimitedCompare(*, null)             = IllegalArgumentException
    +     * unlimitedCompare(null, *)             = Throws {@link IllegalArgumentException}
    +     * unlimitedCompare(*, null)             = Throws {@link IllegalArgumentException}
          * unlimitedCompare("","")               = 0
          * unlimitedCompare("","a")              = 1
          * unlimitedCompare("aaapppp", "")       = 7
    @@ -335,8 +335,8 @@ public LevenshteinDistance(final Integer threshold) {
          * 

    * *
    -     * distance.apply(null, *)             = IllegalArgumentException
    -     * distance.apply(*, null)             = IllegalArgumentException
    +     * distance.apply(null, *)             = Throws {@link IllegalArgumentException}
    +     * distance.apply(*, null)             = Throws {@link IllegalArgumentException}
          * distance.apply("","")               = 0
          * distance.apply("","a")              = 1
          * distance.apply("aaapppp", "")       = 7
    @@ -366,8 +366,8 @@ public Integer apply(final CharSequence left, final CharSequence right) {
          * 

    * *
    -     * distance.apply(null, *)             = IllegalArgumentException
    -     * distance.apply(*, null)             = IllegalArgumentException
    +     * distance.apply(null, *)             = Throws {@link IllegalArgumentException}
    +     * distance.apply(*, null)             = Throws {@link IllegalArgumentException}
          * distance.apply("","")               = 0
          * distance.apply("","a")              = 1
          * distance.apply("aaapppp", "")       = 7
    
    From ba672d32a19fb3958ce30c8e590a81b0aa0c065c Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Fri, 28 Nov 2025 21:32:17 +0000
    Subject: [PATCH 161/265] Bump github/codeql-action from 4.31.4 to 4.31.5
    
    ---
     .github/workflows/codeql-analysis.yml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
    index db1d51c381..a0aad2d98a 100644
    --- a/.github/workflows/codeql-analysis.yml
    +++ b/.github/workflows/codeql-analysis.yml
    @@ -57,7 +57,7 @@ jobs:
     
         # Initializes the CodeQL tools for scanning.
         - name: Initialize CodeQL
    -      uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4
    +      uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5
           with:
             languages: ${{ matrix.language }}
             # If you wish to specify custom queries, you can do so here or in a config file.
    
    From 79e1aa00cda149822e81734f42d1f0e07026c15f Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Fri, 28 Nov 2025 21:45:55 +0000
    Subject: [PATCH 162/265] Bump github/codeql-action from 4.31.4 to 4.31.5
    
    ---
     .github/workflows/codeql-analysis.yml     | 4 ++--
     .github/workflows/scorecards-analysis.yml | 2 +-
     2 files changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
    index a0aad2d98a..885ecfee98 100644
    --- a/.github/workflows/codeql-analysis.yml
    +++ b/.github/workflows/codeql-analysis.yml
    @@ -68,7 +68,7 @@ jobs:
         # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
         # If this step fails, then you should remove it and run the build manually (see below)
         - name: Autobuild
    -      uses: github/codeql-action/autobuild@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4
    +      uses: github/codeql-action/autobuild@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5
     
         # â„šī¸ Command-line programs to run using the OS shell.
         # 📚 https://git.io/JvXDl
    @@ -82,4 +82,4 @@ jobs:
         #   make release
     
         - name: Perform CodeQL Analysis
    -      uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4
    +      uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5
    diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
    index 4270678db1..a5607a52e8 100644
    --- a/.github/workflows/scorecards-analysis.yml
    +++ b/.github/workflows/scorecards-analysis.yml
    @@ -64,6 +64,6 @@ jobs:
               retention-days: 5
     
           - name: "Upload to code-scanning"
    -        uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4
    +        uses: github/codeql-action/upload-sarif@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5
             with:
               sarif_file: results.sarif
    
    From f730ec119fe9a74c7a2316f50dd1993ce851b5ff Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Sat, 29 Nov 2025 12:39:34 +0000
    Subject: [PATCH 163/265] Fix typo in local variable name
    
    ---
     .../org/apache/commons/text/translate/CsvTranslators.java | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/src/main/java/org/apache/commons/text/translate/CsvTranslators.java b/src/main/java/org/apache/commons/text/translate/CsvTranslators.java
    index 66b5dbd8c3..277b8d6316 100644
    --- a/src/main/java/org/apache/commons/text/translate/CsvTranslators.java
    +++ b/src/main/java/org/apache/commons/text/translate/CsvTranslators.java
    @@ -47,13 +47,13 @@ public CsvEscaper() {
     
             @Override
             void translateWhole(final CharSequence input, final Writer writer) throws IOException {
    -            final String inputSting = input.toString();
    -            if (StringUtils.containsNone(inputSting, CSV_SEARCH_CHARS)) {
    -                writer.write(inputSting);
    +            final String inputString = input.toString();
    +            if (StringUtils.containsNone(inputString, CSV_SEARCH_CHARS)) {
    +                writer.write(inputString);
                 } else {
                     // input needs quoting
                     writer.write(CSV_QUOTE);
    -                writer.write(StringUtils.replace(inputSting, CSV_QUOTE_STR, CSV_ESCAPED_QUOTE_STR));
    +                writer.write(StringUtils.replace(inputString, CSV_QUOTE_STR, CSV_ESCAPED_QUOTE_STR));
                     writer.write(CSV_QUOTE);
                 }
             }
    
    From df0be698a985b6a2d3634e6daa25718214112cf0 Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Sat, 29 Nov 2025 17:53:14 -0500
    Subject: [PATCH 164/265] Update from deprecated code
    
    ---
     .../org/apache/commons/text/translate/CsvTranslators.java    | 5 +++--
     1 file changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/src/main/java/org/apache/commons/text/translate/CsvTranslators.java b/src/main/java/org/apache/commons/text/translate/CsvTranslators.java
    index 277b8d6316..053dc174f8 100644
    --- a/src/main/java/org/apache/commons/text/translate/CsvTranslators.java
    +++ b/src/main/java/org/apache/commons/text/translate/CsvTranslators.java
    @@ -21,6 +21,7 @@
     
     import org.apache.commons.lang3.CharUtils;
     import org.apache.commons.lang3.StringUtils;
    +import org.apache.commons.lang3.Strings;
     
     /**
      * This class holds inner classes for escaping/unescaping Comma Separated Values.
    @@ -53,7 +54,7 @@ void translateWhole(final CharSequence input, final Writer writer) throws IOExce
                 } else {
                     // input needs quoting
                     writer.write(CSV_QUOTE);
    -                writer.write(StringUtils.replace(inputString, CSV_QUOTE_STR, CSV_ESCAPED_QUOTE_STR));
    +                writer.write(Strings.CS.replace(inputString, CSV_QUOTE_STR, CSV_ESCAPED_QUOTE_STR));
                     writer.write(CSV_QUOTE);
                 }
             }
    @@ -83,7 +84,7 @@ void translateWhole(final CharSequence input, final Writer writer) throws IOExce
     
                 if (StringUtils.containsAny(quoteless, CSV_SEARCH_CHARS)) {
                     // deal with escaped quotes; ie) ""
    -                writer.write(StringUtils.replace(quoteless, CSV_ESCAPED_QUOTE_STR, CSV_QUOTE_STR));
    +                writer.write(Strings.CS.replace(quoteless, CSV_ESCAPED_QUOTE_STR, CSV_QUOTE_STR));
                 } else {
                     writer.write(quoteless);
                 }
    
    From 557bd2e946123847d3227843b6e154b5e155bcd1 Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Sat, 29 Nov 2025 17:56:40 -0500
    Subject: [PATCH 165/265] Update from deprecated code
    
    ---
     src/main/java/org/apache/commons/text/WordUtils.java | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/src/main/java/org/apache/commons/text/WordUtils.java b/src/main/java/org/apache/commons/text/WordUtils.java
    index 83f2eec2f1..48b43caf85 100644
    --- a/src/main/java/org/apache/commons/text/WordUtils.java
    +++ b/src/main/java/org/apache/commons/text/WordUtils.java
    @@ -24,6 +24,7 @@
     
     import org.apache.commons.lang3.ArrayUtils;
     import org.apache.commons.lang3.StringUtils;
    +import org.apache.commons.lang3.Strings;
     import org.apache.commons.lang3.Validate;
     
     /**
    @@ -97,7 +98,7 @@ public static String abbreviate(final String str, int lower, int upper, final St
             }
     
             final StringBuilder result = new StringBuilder();
    -        final int index = StringUtils.indexOf(str, " ", lower);
    +        final int index = Strings.CS.indexOf(str, " ", lower);
             if (index == -1) {
                 result.append(str, 0, upper);
                 // only if abbreviation has occurred do we append the appendToEnd value
    
    From 1187d470ed7480647a5254ba9981321c9618191e Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Sun, 30 Nov 2025 07:56:43 -0500
    Subject: [PATCH 166/265] Javadoc
    
    ---
     src/main/java/org/apache/commons/text/similarity/Counter.java | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/src/main/java/org/apache/commons/text/similarity/Counter.java b/src/main/java/org/apache/commons/text/similarity/Counter.java
    index f38b206e2a..908bf9ed58 100644
    --- a/src/main/java/org/apache/commons/text/similarity/Counter.java
    +++ b/src/main/java/org/apache/commons/text/similarity/Counter.java
    @@ -47,7 +47,7 @@ public static Map of(final CharSequence[] tokens) {
         }
     
         /**
    -     * Hidden constructor.
    +     * No instance needed.
          */
         private Counter() {
         }
    
    From e35d94540c9fe8d65dc97e931d93be1c7d596fae Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Sun, 30 Nov 2025 07:57:43 -0500
    Subject: [PATCH 167/265] Inline single use local variable
    
    ---
     .../org/apache/commons/text/similarity/CosineDistance.java | 7 ++-----
     1 file changed, 2 insertions(+), 5 deletions(-)
    
    diff --git a/src/main/java/org/apache/commons/text/similarity/CosineDistance.java b/src/main/java/org/apache/commons/text/similarity/CosineDistance.java
    index b4afc76efa..4d98ab4be8 100644
    --- a/src/main/java/org/apache/commons/text/similarity/CosineDistance.java
    +++ b/src/main/java/org/apache/commons/text/similarity/CosineDistance.java
    @@ -44,11 +44,8 @@ public CosineDistance() {
     
         @Override
         public Double apply(final CharSequence left, final CharSequence right) {
    -        final CharSequence[] leftTokens = RegexTokenizer.INSTANCE.apply(left);
    -        final CharSequence[] rightTokens = RegexTokenizer.INSTANCE.apply(right);
    -
    -        final Map leftVector = Counter.of(leftTokens);
    -        final Map rightVector = Counter.of(rightTokens);
    +        final Map leftVector = Counter.of(RegexTokenizer.INSTANCE.apply(left));
    +        final Map rightVector = Counter.of(RegexTokenizer.INSTANCE.apply(right));
             final double similarity = CosineSimilarity.INSTANCE.cosineSimilarity(leftVector, rightVector);
             return 1.0 - similarity;
         }
    
    From 531f84596c3d3c397bdb3cd26292d54ea3fe217f Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Sun, 30 Nov 2025 07:59:17 -0500
    Subject: [PATCH 168/265] Reduce vertical whitespace
    
    ---
     .../commons/text/similarity/CosineSimilarity.java    | 12 +++---------
     1 file changed, 3 insertions(+), 9 deletions(-)
    
    diff --git a/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java b/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java
    index c0dd5c2c1a..2c5a123b72 100644
    --- a/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java
    +++ b/src/main/java/org/apache/commons/text/similarity/CosineSimilarity.java
    @@ -52,14 +52,11 @@ public CosineSimilarity() {
          * @param rightVector right vector.
          * @return cosine similarity between the two vectors.
          */
    -    public Double cosineSimilarity(final Map leftVector,
    -                                   final Map rightVector) {
    +    public Double cosineSimilarity(final Map leftVector, final Map rightVector) {
             if (leftVector == null || rightVector == null) {
                 throw new IllegalArgumentException("Vectors must not be null");
             }
    -
             final Set intersection = getIntersection(leftVector, rightVector);
    -
             final double dotProduct = dot(leftVector, rightVector, intersection);
             double d1 = 0.0d;
             for (final Integer value : leftVector.values()) {
    @@ -88,8 +85,7 @@ public Double cosineSimilarity(final Map leftVector,
          * @param intersection common elements.
          * @return The dot product.
          */
    -    private double dot(final Map leftVector, final Map rightVector,
    -            final Set intersection) {
    +    private double dot(final Map leftVector, final Map rightVector, final Set intersection) {
             long dotProduct = 0;
             for (final CharSequence key : intersection) {
                 dotProduct += leftVector.get(key) * (long) rightVector.get(key);
    @@ -104,11 +100,9 @@ private double dot(final Map leftVector, final Map getIntersection(final Map leftVector,
    -            final Map rightVector) {
    +    private Set getIntersection(final Map leftVector, final Map rightVector) {
             final Set intersection = new HashSet<>(leftVector.keySet());
             intersection.retainAll(rightVector.keySet());
             return intersection;
         }
    -
     }
    
    From edf191d2466b72dc96335f23cf58c34d2e0de721 Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Sun, 30 Nov 2025 08:02:23 -0500
    Subject: [PATCH 169/265] Javadoc
    
    Reduce vertical whitespace
    ---
     .../commons/text/similarity/FuzzyScore.java      | 16 ++--------------
     1 file changed, 2 insertions(+), 14 deletions(-)
    
    diff --git a/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java b/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java
    index fd5c447dcd..b35455dc66 100644
    --- a/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java
    +++ b/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java
    @@ -54,7 +54,7 @@ public FuzzyScore(final Locale locale) {
         }
     
         /**
    -     * Find the Fuzzy Score which indicates the similarity score between two Strings.
    +     * Computes the Fuzzy Score which indicates the similarity score between two Strings.
          *
          * 
          * score.fuzzyScore(null, null)                          = Throws {@link IllegalArgumentException}
    @@ -78,51 +78,39 @@ public Integer fuzzyScore(final CharSequence term, final CharSequence query) {
             if (term == null || query == null) {
                 throw new IllegalArgumentException("CharSequences must not be null");
             }
    -
             // fuzzy logic is case insensitive. We normalize the Strings to lower
             // case right from the start. Turning characters to lower case
             // via Character.toLowerCase(char) is unfortunately insufficient
             // as it does not accept a locale.
             final String termLowerCase = term.toString().toLowerCase(locale);
             final String queryLowerCase = query.toString().toLowerCase(locale);
    -
             // the resulting score
             int score = 0;
    -
             // the position in the term which will be scanned next for potential
             // query character matches
             int termIndex = 0;
    -
             // index of the previously matched character in the term
             int previousMatchingCharacterIndex = Integer.MIN_VALUE;
    -
             for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) {
                 final char queryChar = queryLowerCase.charAt(queryIndex);
    -
                 boolean termCharacterMatchFound = false;
    -            for (; termIndex < termLowerCase.length()
    -                    && !termCharacterMatchFound; termIndex++) {
    +            for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) {
                     final char termChar = termLowerCase.charAt(termIndex);
    -
                     if (queryChar == termChar) {
                         // simple character matches result in one point
                         score++;
    -
                         // subsequent character matches further improve
                         // the score.
                         if (previousMatchingCharacterIndex + 1 == termIndex) {
                             score += 2;
                         }
    -
                         previousMatchingCharacterIndex = termIndex;
    -
                         // we can leave the nested loop. Every character in the
                         // query can match at most one character in the term.
                         termCharacterMatchFound = true;
                     }
                 }
             }
    -
             return score;
         }
     
    
    From 1dd5be35db26cfef658cf095552e1b81173dcfa2 Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Sun, 30 Nov 2025 08:05:26 -0500
    Subject: [PATCH 170/265] Javadoc
    
    ---
     src/main/java/org/apache/commons/text/similarity/Tokenizer.java | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/src/main/java/org/apache/commons/text/similarity/Tokenizer.java b/src/main/java/org/apache/commons/text/similarity/Tokenizer.java
    index ac8689fdb1..c983caaa58 100644
    --- a/src/main/java/org/apache/commons/text/similarity/Tokenizer.java
    +++ b/src/main/java/org/apache/commons/text/similarity/Tokenizer.java
    @@ -20,7 +20,7 @@
     import java.util.function.Function;
     
     /**
    - * A tokenizer. Can produce arrays of tokens from a given type.
    + * Produces arrays of tokens for a given type.
      *
      * @param  The type to tokenize.
      * @param  The return array element type.
    
    From 685da724c45e74d30df08215bb96bbafdeac4ed6 Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Sun, 30 Nov 2025 08:13:52 -0500
    Subject: [PATCH 171/265] Javadoc
    
    ---
     .../java/org/apache/commons/text/diff/CommandVisitor.java | 3 +--
     .../java/org/apache/commons/text/diff/EditScript.java     | 2 +-
     .../org/apache/commons/text/diff/ReplacementsFinder.java  | 2 +-
     .../org/apache/commons/text/diff/ReplacementsHandler.java | 2 +-
     .../org/apache/commons/text/diff/StringsComparator.java   | 3 +--
     .../org/apache/commons/text/similarity/FuzzyScore.java    | 2 +-
     .../text/similarity/LevenshteinDetailedDistance.java      | 8 ++++----
     .../commons/text/similarity/SimilarityScoreFrom.java      | 6 +++---
     .../org/apache/commons/text/translate/CsvTranslators.java | 2 +-
     9 files changed, 14 insertions(+), 16 deletions(-)
    
    diff --git a/src/main/java/org/apache/commons/text/diff/CommandVisitor.java b/src/main/java/org/apache/commons/text/diff/CommandVisitor.java
    index 187c9f4161..247e0818de 100644
    --- a/src/main/java/org/apache/commons/text/diff/CommandVisitor.java
    +++ b/src/main/java/org/apache/commons/text/diff/CommandVisitor.java
    @@ -17,8 +17,7 @@
     package org.apache.commons.text.diff;
     
     /**
    - * This interface should be implemented by user object to walk
    - * through {@link EditScript EditScript} objects.
    + * Walks through {@link EditScript EditScript} objects.
      * 

    * Users should implement this interface in order to walk through * the {@link EditScript EditScript} object created by the comparison diff --git a/src/main/java/org/apache/commons/text/diff/EditScript.java b/src/main/java/org/apache/commons/text/diff/EditScript.java index 6b68424bf7..420754ad90 100644 --- a/src/main/java/org/apache/commons/text/diff/EditScript.java +++ b/src/main/java/org/apache/commons/text/diff/EditScript.java @@ -20,7 +20,7 @@ import java.util.List; /** - * This class gathers all the {@link EditCommand commands} needed to transform + * Gathers all the {@link EditCommand commands} needed to transform * one objects sequence into another objects sequence. *

    * An edit script is the most general view of the differences between two diff --git a/src/main/java/org/apache/commons/text/diff/ReplacementsFinder.java b/src/main/java/org/apache/commons/text/diff/ReplacementsFinder.java index 15f2ed5ff5..88994ac70e 100644 --- a/src/main/java/org/apache/commons/text/diff/ReplacementsFinder.java +++ b/src/main/java/org/apache/commons/text/diff/ReplacementsFinder.java @@ -20,7 +20,7 @@ import java.util.List; /** - * This class handles sequences of replacements resulting from a comparison. + * Handles sequences of replacements resulting from a comparison. *

    * The comparison of two objects sequences leads to the identification of common * parts and parts which only belong to the first or to the second sequence. The diff --git a/src/main/java/org/apache/commons/text/diff/ReplacementsHandler.java b/src/main/java/org/apache/commons/text/diff/ReplacementsHandler.java index 3f8040ad2a..1b749b1f3c 100644 --- a/src/main/java/org/apache/commons/text/diff/ReplacementsHandler.java +++ b/src/main/java/org/apache/commons/text/diff/ReplacementsHandler.java @@ -19,7 +19,7 @@ import java.util.List; /** - * This interface is devoted to handle synchronized replacement sequences. + * Handles synchronized replacement sequences. * * @param object type * @see ReplacementsFinder diff --git a/src/main/java/org/apache/commons/text/diff/StringsComparator.java b/src/main/java/org/apache/commons/text/diff/StringsComparator.java index db7ff5ac49..74ff0e62fb 100644 --- a/src/main/java/org/apache/commons/text/diff/StringsComparator.java +++ b/src/main/java/org/apache/commons/text/diff/StringsComparator.java @@ -53,8 +53,7 @@ public class StringsComparator { /** - * This class is a simple placeholder to hold the end part of a path - * under construction in a {@link StringsComparator StringsComparator}. + * Holds the end part of a path under construction in a {@link StringsComparator StringsComparator}. */ private static final class Snake { diff --git a/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java b/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java index b35455dc66..e1b605da9a 100644 --- a/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java +++ b/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java @@ -41,7 +41,7 @@ public class FuzzyScore { private final Locale locale; /** - * This returns a {@link Locale}-specific {@link FuzzyScore}. + * Constructs a new instance for a {@link Locale}-specific {@link FuzzyScore}. * * @param locale The string matching logic is case insensitive. A {@link Locale} is necessary to normalize both Strings to lower case. * @throws IllegalArgumentException This is thrown if the {@link Locale} parameter is {@code null}. diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java index 556eaf1fc3..d4148de4a6 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java @@ -380,9 +380,7 @@ private static LevenshteinResults unlimitedCompare(SimilarityInput left, private final Integer threshold; /** - *

    - * This returns the default instance that uses a version of the algorithm that does not use a threshold parameter. - *

    + * Constructs a new instance that uses a version of the algorithm that does not use a threshold parameter. * * @see LevenshteinDetailedDistance#getDefaultInstance() * @deprecated Use {@link #getDefaultInstance()}. @@ -393,8 +391,10 @@ public LevenshteinDetailedDistance() { } /** + * Constructs a new instance for a threshold. + *

    * If the threshold is not null, distance calculations will be limited to a maximum length. - * + *

    *

    * If the threshold is null, the unlimited version of the algorithm will be used. *

    diff --git a/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java b/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java index 470bb713da..6e7078a1e5 100644 --- a/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java +++ b/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java @@ -19,7 +19,7 @@ import org.apache.commons.lang3.Validate; /** - * This stores a {@link SimilarityScore} implementation and a {@link CharSequence} "left" string. + * Stores a {@link SimilarityScore} implementation and a {@link CharSequence} "left" string. * The {@link #apply(CharSequence right)} method accepts the "right" string and invokes the * comparison function for the pair of strings. * @@ -63,7 +63,7 @@ public class SimilarityScoreFrom { private final CharSequence left; /** - * This accepts the similarity score implementation and the "left" string. + * Constructs a new instance for a similarity score implementation and the "left" string. * * @param similarityScore This may not be null. * @param left This may be null here, @@ -78,7 +78,7 @@ public SimilarityScoreFrom(final SimilarityScore similarityScore, final CharS } /** - * This compares "left" field against the "right" parameter + * Compares "left" field against the "right" parameter * using the "similarity score" implementation. * * @param right the second CharSequence. diff --git a/src/main/java/org/apache/commons/text/translate/CsvTranslators.java b/src/main/java/org/apache/commons/text/translate/CsvTranslators.java index 053dc174f8..9a5f467136 100644 --- a/src/main/java/org/apache/commons/text/translate/CsvTranslators.java +++ b/src/main/java/org/apache/commons/text/translate/CsvTranslators.java @@ -24,7 +24,7 @@ import org.apache.commons.lang3.Strings; /** - * This class holds inner classes for escaping/unescaping Comma Separated Values. + * Holds inner classes for escaping/unescaping Comma Separated Values. *

    * In general the use a high level API like Apache Commons * CSV should be preferred over these low level classes. From 175fd68689ccfb96d4cf1267bdb69c0775e0f3f0 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 1 Dec 2025 09:59:20 -0500 Subject: [PATCH 172/265] Bump github/codeql-action from 4.31.5 to 4.31.6 --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 885ecfee98..62500fe146 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 + uses: github/codeql-action/init@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 + uses: github/codeql-action/autobuild@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 + uses: github/codeql-action/analyze@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 From 61ec6fd6ec37c73e576d8af84679421a2701964c Mon Sep 17 00:00:00 2001 From: Michael Hausegger Date: Mon, 1 Dec 2025 20:09:19 +0100 Subject: [PATCH 173/265] Removed unreachable threshold verification code from Levenshtein algorithm implementation classes (#730) Co-authored-by: TheRealHaui --- .../commons/text/similarity/DamerauLevenshteinDistance.java | 4 ---- .../commons/text/similarity/LevenshteinDetailedDistance.java | 4 +--- .../apache/commons/text/similarity/LevenshteinDistance.java | 3 --- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java index 0aa39accfa..4e0b9c65ee 100644 --- a/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java @@ -54,10 +54,6 @@ private static int limitedCompare(SimilarityInput left, SimilarityInput< 0) { - throw new IllegalArgumentException("Threshold can not be negative"); - } - // Implementation based on https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance#Optimal_string_alignment_distance int leftLength = left.length(); diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java index d4148de4a6..ac7b4018aa 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java @@ -159,9 +159,7 @@ private static LevenshteinResults limitedCompare(SimilarityInput left, Si if (left == null || right == null) { throw new IllegalArgumentException("CharSequences must not be null"); } - if (threshold < 0) { - throw new IllegalArgumentException("Threshold must not be negative"); - } + /* * This implementation only computes the distance if it's less than or equal to the threshold value, returning -1 if it's greater. The advantage is * performance: unbounded distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only computing a diagonal stripe of width 2k + 1 diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java index cb2e272983..8ab60eeec8 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java @@ -81,9 +81,6 @@ private static int limitedCompare(SimilarityInput left, SimilarityInput< 0) { - throw new IllegalArgumentException("Threshold must not be negative"); - } /* * This implementation only computes the distance if it's less than or equal to the threshold value, returning -1 if it's greater. The advantage is From 04c24ac259d15a47463dc6e65762c28b7779ad7d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 1 Dec 2025 14:10:23 -0500 Subject: [PATCH 174/265] Removed unreachable threshold verification code in src/main/java/org/apache/commons/text/similarity #730 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c6de2b3687..d0ab0b7d99 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,6 +52,7 @@ The type attribute can be add,update,fix,remove. Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724. Fix Apache RAT plugin console warnings. Fix site XML to use version 2.0.0 XML schema. + Removed unreachable threshold verification code in src/main/java/org/apache/commons/text/similarity #730. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. From 702afb18f56bfbc9ccda01d9b46283911b721108 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 1 Dec 2025 16:14:54 -0500 Subject: [PATCH 175/265] Bump github/codeql-action from 4.31.5 to 4.31.6 --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index a5607a52e8..4f87551686 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 + uses: github/codeql-action/upload-sarif@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 with: sarif_file: results.sarif From 9656bdeedc5fde6150b107b3a3eec2ab775b33b3 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 06:07:10 -0500 Subject: [PATCH 176/265] Enable secure processing for the XML parser (#729) Secure processing for XPath evaluation is already enabled but doesn't affect XML parsing. --- .../text/lookup/StringLookupFactory.java | 61 +++++++--- .../commons/text/lookup/XmlStringLookup.java | 115 +++++++++++++----- .../text/lookup/StringLookupFactoryTest.java | 13 ++ .../text/lookup/XmlStringLookupTest.java | 65 ++++++++-- .../commons/text/document-entity-ref.xml | 26 ++++ .../org/apache/commons/text/xml-entity.txt | 17 +++ 6 files changed, 242 insertions(+), 55 deletions(-) create mode 100644 src/test/resources/org/apache/commons/text/document-entity-ref.xml create mode 100644 src/test/resources/org/apache/commons/text/xml-entity.txt diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java index 2f163b8e05..f172f58870 100644 --- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java +++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java @@ -30,6 +30,7 @@ import java.util.function.Function; import java.util.function.Supplier; +import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPathFactory; import org.apache.commons.text.StringSubstitutor; @@ -1617,10 +1618,19 @@ public StringLookup xmlEncoderStringLookup() { * if a lookup causes causes a path to resolve outside of these fences. Otherwise, the result is unfenced to preserved behavior from previous versions. *

    *

    - * We look up the value for the key in the format "DocumentPath:XPath". + * We looks up values in an XML document in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. *

    *

    - * For example: "com/domain/document.xml:/path/to/node". + * For example: + *

    + *
      + *
    • {@code "com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • + *
    + *

    + * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure + * value in the key overrides instance settings given in the constructor. *

    *

    * Using a {@link StringLookup} from the {@link StringLookupFactory}: @@ -1644,7 +1654,7 @@ public StringLookup xmlEncoderStringLookup() { * @since 1.5 */ public StringLookup xmlStringLookup() { - return fences != null ? xmlStringLookup(XmlStringLookup.DEFAULT_FEATURES, fences) : XmlStringLookup.INSTANCE; + return fences != null ? xmlStringLookup(XmlStringLookup.DEFAULT_XPATH_FEATURES, fences) : XmlStringLookup.INSTANCE; } /** @@ -1654,10 +1664,19 @@ public StringLookup xmlStringLookup() { * if a lookup causes causes a path to resolve outside of these fences. Otherwise, the result is unfenced to preserved behavior from previous versions. *

    *

    - * We look up the value for the key in the format {@code "DocumentPath:XPath"}. + * We looks up values in an XML document in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. *

    *

    - * For example: {@code "com/domain/document.xml:/path/to/node"}. + * For example: + *

    + *
      + *
    • {@code "com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • + *
    + *

    + * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure + * value in the key overrides instance settings given in the constructor. *

    *

    * Using a {@link StringLookup} from the {@link StringLookupFactory}: @@ -1677,13 +1696,14 @@ public StringLookup xmlStringLookup() { * The examples above convert {@code "com/domain/document.xml:/path/to/node"} to the value of the XPath in the XML document. *

    * - * @param xPathFactoryFeatures XPathFactory features to set. + * @param factoryFeatures DocumentBuilderFactory and XPathFactory features to set. * @return An XML StringLookup instance. + * @see DocumentBuilderFactory#setFeature(String, boolean) * @see XPathFactory#setFeature(String, boolean) * @since 1.11.0 */ - public StringLookup xmlStringLookup(final Map xPathFactoryFeatures) { - return xmlStringLookup(xPathFactoryFeatures, fences); + public StringLookup xmlStringLookup(final Map factoryFeatures) { + return xmlStringLookup(factoryFeatures, fences); } /** @@ -1693,10 +1713,19 @@ public StringLookup xmlStringLookup(final Map xPathFactoryFeatu * if a lookup causes causes a path to resolve outside of these fences. Otherwise, the result is unfenced to preserved behavior from previous versions. *

    *

    - * We look up the value for the key in the format {@code "DocumentPath:XPath"}. + * We looks up values in an XML document in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. *

    *

    - * For example: {@code "com/domain/document.xml:/path/to/node"}. + * For example: + *

    + *
      + *
    • {@code "com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • + *
    + *

    + * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure + * value in the key overrides instance settings given in the constructor. *

    *

    * Using a {@link StringLookup} from the {@link StringLookupFactory} fenced by the current directory ({@code Paths.get("")}): @@ -1711,10 +1740,8 @@ public StringLookup xmlStringLookup(final Map xPathFactoryFeatu * *

          * StringLookupFactory.INSTANCE.xmlStringLookup(Paths.get("")).lookup("com/domain/document.xml:/path/to/node");
    -     *
          * // throws IllegalArgumentException
          * StringLookupFactory.INSTANCE.xmlStringLookup(Paths.get("")).lookup("/rootdir/foo/document.xml:/path/to/node");
    -     *
          * // throws IllegalArgumentException
          * StringLookupFactory.INSTANCE.xmlStringLookup(Paths.get("")).lookup("../com/domain/document.xml:/path/to/node");
          * 
    @@ -1726,12 +1753,14 @@ public StringLookup xmlStringLookup(final Map xPathFactoryFeatu * resolves in a fence. *

    * - * @param xPathFactoryFeatures XPathFactory features to set. - * @param fences The fences guarding Path resolution. + * @param factoryFeatures DocumentBuilderFactory and XPathFactory features to set. + * @param fences The fences guarding Path resolution. * @return An XML StringLookup instance. + * @see DocumentBuilderFactory#setFeature(String, boolean) + * @see XPathFactory#setFeature(String, boolean) * @since 1.12.0 */ - public StringLookup xmlStringLookup(final Map xPathFactoryFeatures, final Path... fences) { - return new XmlStringLookup(xPathFactoryFeatures, fences); + public StringLookup xmlStringLookup(final Map factoryFeatures, final Path... fences) { + return new XmlStringLookup(factoryFeatures, factoryFeatures, fences); } } diff --git a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java index a476cc0786..aa873a0088 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java @@ -26,38 +26,60 @@ import java.util.Objects; import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPathFactory; import org.apache.commons.lang3.StringUtils; -import org.xml.sax.InputSource; +import org.w3c.dom.Document; /** - * Looks up keys from an XML document. + * Looks up values in an XML document in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. *

    - * Looks up the value for a given key in the format "Document:XPath". + * For example: *

    + *
      + *
    • {@code "com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • + *
    *

    - * For example: "com/domain/document.xml:/path/to/node". + * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure + * value in the key overrides instance settings given in the constructor. *

    * * @since 1.5 */ final class XmlStringLookup extends AbstractPathFencedLookup { + /** + * Minimum number of key parts. + */ + private static final int KEY_PARTS_MIN = 2; + + /** + * Minimum number of key parts. + */ + private static final int KEY_PARTS_MAX = 3; + /** * Defines default XPath factory features. */ - static final Map DEFAULT_FEATURES; + static final Map DEFAULT_XPATH_FEATURES; + /** + * Defines default XML factory features. + */ + static final Map DEFAULT_XML_FEATURES; static { - DEFAULT_FEATURES = new HashMap<>(1); - DEFAULT_FEATURES.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); + DEFAULT_XPATH_FEATURES = new HashMap<>(1); + DEFAULT_XPATH_FEATURES.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); + DEFAULT_XML_FEATURES = new HashMap<>(1); + DEFAULT_XML_FEATURES.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); } - /** - * Defines the singleton for this class. + * Defines the singleton for this class with secure processing enabled. */ - static final XmlStringLookup INSTANCE = new XmlStringLookup(DEFAULT_FEATURES, (Path[]) null); + static final XmlStringLookup INSTANCE = new XmlStringLookup(DEFAULT_XML_FEATURES, DEFAULT_XPATH_FEATURES, (Path[]) null); /** * Defines XPath factory features. @@ -65,23 +87,40 @@ final class XmlStringLookup extends AbstractPathFencedLookup { private final Map xPathFactoryFeatures; /** - * No need to build instances for now. + * Defines XML factory features. + */ + private final Map xmlFactoryFeatures; + + /** + * Constructs a new instance. * - * @param xPathFactoryFeatures XPathFactory features to set. + * @param xmlFactoryFeatures The {@link DocumentBuilderFactory} features to set. + * @param xPathFactoryFeatures The {@link XPathFactory} features to set. + * @see DocumentBuilderFactory#setFeature(String, boolean) * @see XPathFactory#setFeature(String, boolean) */ - XmlStringLookup(final Map xPathFactoryFeatures, final Path... fences) { + XmlStringLookup(final Map xmlFactoryFeatures, final Map xPathFactoryFeatures, final Path... fences) { super(fences); + this.xmlFactoryFeatures = Objects.requireNonNull(xmlFactoryFeatures, "xmlFactoryFeatures"); this.xPathFactoryFeatures = Objects.requireNonNull(xPathFactoryFeatures, "xPathFfactoryFeatures"); } /** - * Looks up the value for the key in the format "DocumentPath:XPath". + * Looks up a value for the key in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. + *

    + * For example: + *

    + *
      + *
    • {@code "com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • + *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • + *
    *

    - * For example: "com/domain/document.xml:/path/to/node". + * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure + * value in the key overrides instance settings given in the constructor. *

    * - * @param key the key to be looked up, may be null + * @param key the key to be looked up, may be null. * @return The value associated with the key. */ @Override @@ -91,22 +130,42 @@ public String lookup(final String key) { } final String[] keys = key.split(SPLIT_STR); final int keyLen = keys.length; - if (keyLen != 2) { - throw IllegalArgumentExceptions.format("Bad XML key format [%s]; expected format is DocumentPath:XPath.", - key); + if (keyLen != KEY_PARTS_MIN && keyLen != KEY_PARTS_MAX) { + throw IllegalArgumentExceptions.format("Bad XML key format '%s'; the expected format is [secure=(true|false):]DocumentPath:XPath.", key); } - final String documentPath = keys[0]; - final String xpath = StringUtils.substringAfter(key, SPLIT_CH); - try (InputStream inputStream = Files.newInputStream(getPath(documentPath))) { - final XPathFactory factory = XPathFactory.newInstance(); - for (final Entry p : xPathFactoryFeatures.entrySet()) { - factory.setFeature(p.getKey(), p.getValue()); + final boolean isKeySecure = keyLen == KEY_PARTS_MAX; + final Boolean secure = isKeySecure ? parseSecureKey(keys, key) : null; + final String documentPath = isKeySecure ? keys[1] : keys[0]; + final String xpath = StringUtils.substringAfterLast(key, SPLIT_CH); + final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + try { + for (final Entry p : xmlFactoryFeatures.entrySet()) { + dbFactory.setFeature(p.getKey(), p.getValue()); + } + if (secure != null) { + dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure.booleanValue()); + } + try (InputStream inputStream = Files.newInputStream(getPath(documentPath))) { + final Document doc = dbFactory.newDocumentBuilder().parse(inputStream); + final XPathFactory factory = XPathFactory.newInstance(); + for (final Entry p : xPathFactoryFeatures.entrySet()) { + factory.setFeature(p.getKey(), p.getValue()); + } + if (secure != null) { + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure.booleanValue()); + } + return factory.newXPath().evaluate(xpath, doc); } - return factory.newXPath().evaluate(xpath, new InputSource(inputStream)); } catch (final Exception e) { - throw IllegalArgumentExceptions.format(e, "Error looking up XML document [%s] and XPath [%s].", - documentPath, xpath); + throw new IllegalArgumentException(e); } } + private Boolean parseSecureKey(final String[] args, final String key) { + final String[] secParts = args[0].split("="); + if (secParts.length != 2 && !Objects.equals(secParts[0], "secure")) { + throw IllegalArgumentExceptions.format("Bad XML key format '%s'; the expected format is [secure=(true|false):]DocumentPath:XPath.", key); + } + return Boolean.valueOf(secParts[1]); + } } diff --git a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java index 33897a7493..5ffe49f358 100644 --- a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java +++ b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java @@ -282,4 +282,17 @@ void testXmlStringLookup() { XmlStringLookupTest.assertLookup(stringLookupFactory.xmlStringLookup(features)); XmlStringLookupTest.assertLookup(stringLookupFactory.xmlStringLookup(new HashMap<>())); } + + @Test + void testXmlStringLookupExternalEntityOff() { + assertThrows(IllegalArgumentException.class, + () -> StringLookupFactory.INSTANCE.xmlStringLookup().apply(XmlStringLookupTest.DOC_DIR + "document-entity-ref.xml:/document/content")); + } + + @Test + void testXmlStringLookupExternalEntityOn() { + final String key = XmlStringLookupTest.DOC_DIR + "document-entity-ref.xml:/document/content"; + assertEquals(XmlStringLookupTest.DATA, StringLookupFactory.INSTANCE.xmlStringLookup(XmlStringLookupTest.EMPTY_MAP).apply(key).trim()); + } + } diff --git a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java index 40290f0b75..d24c40907e 100644 --- a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java @@ -26,11 +26,14 @@ import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; import java.util.HashMap; +import java.util.Map; import javax.xml.XMLConstants; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringSubstitutor; import org.junit.jupiter.api.Test; /** @@ -38,15 +41,18 @@ */ class XmlStringLookupTest { + static final String DATA = "Hello World!"; + static final Map EMPTY_MAP = Collections.emptyMap(); private static final Path CURRENT_PATH = Paths.get(StringUtils.EMPTY); // NOT "." private static final Path ABSENT_PATH = Paths.get("does not exist at all"); - private static final String DOC_RELATIVE = "src/test/resources/org/apache/commons/text/document.xml"; + static final String DOC_DIR = "src/test/resources/org/apache/commons/text/"; + private static final String DOC_RELATIVE = DOC_DIR + "document.xml"; private static final String DOC_ROOT = "/document.xml"; static void assertLookup(final StringLookup xmlStringLookup) { assertNotNull(xmlStringLookup); assertInstanceOf(XmlStringLookup.class, xmlStringLookup); - assertEquals("Hello World!", xmlStringLookup.apply(DOC_RELATIVE + ":/root/path/to/node")); + assertEquals(DATA, xmlStringLookup.apply(DOC_RELATIVE + ":/root/path/to/node")); assertNull(xmlStringLookup.apply(null)); } @@ -55,6 +61,44 @@ void testBadXPath() { assertThrows(IllegalArgumentException.class, () -> XmlStringLookup.INSTANCE.apply("docName")); } + @Test + void testExternalEntityOff() { + assertThrows(IllegalArgumentException.class, + () -> new XmlStringLookup(XmlStringLookup.DEFAULT_XML_FEATURES, EMPTY_MAP).apply(DOC_DIR + "document-entity-ref.xml:/document/content")); + } + + @Test + void testExternalEntityOn() { + final String key = DOC_DIR + "document-entity-ref.xml:/document/content"; + assertEquals(DATA, new XmlStringLookup(EMPTY_MAP, EMPTY_MAP).apply(key).trim()); + assertEquals(DATA, new XmlStringLookup(EMPTY_MAP, XmlStringLookup.DEFAULT_XPATH_FEATURES).apply(key).trim()); + } + + @Test + void testInterpolatorExternalEntityOff() { + final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); + assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:" + DOC_DIR + "document-entity-ref.xml:/document/content}")); + } + + @Test + void testInterpolatorExternalEntityOffOverride() { + final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); + assertEquals(DATA, stringSubstitutor.replace("${xml:secure=false:" + DOC_DIR + "document-entity-ref.xml:/document/content}").trim()); + } + + @Test + void testInterpolatorExternalEntityOn() { + final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); + assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:" + DOC_DIR + "document-entity-ref.xml:/document/content}")); + } + + @Test + void testInterpolatorExternalEntityOnOverride() { + final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); + assertThrows(IllegalArgumentException.class, + () -> stringSubstitutor.replace("${xml:secure=true:" + DOC_DIR + "document-entity-ref.xml:/document/content}")); + } + @Test void testMissingXPath() { assertThrows(IllegalArgumentException.class, () -> XmlStringLookup.INSTANCE.apply(DOC_RELATIVE + ":!JUNK!")); @@ -63,20 +107,20 @@ void testMissingXPath() { @Test void testNoFeatures() { final String xpath = "/root/path/to/node"; - assertEquals("Hello World!", new XmlStringLookup(new HashMap<>()).apply(DOC_RELATIVE + ":" + xpath)); - assertEquals("Hello World!", new XmlStringLookup(new HashMap<>(), CURRENT_PATH).apply(DOC_RELATIVE + ":" + xpath)); - assertEquals("Hello World!", new XmlStringLookup(new HashMap<>(), CURRENT_PATH, ABSENT_PATH).apply(DOC_RELATIVE + ":" + xpath)); - assertEquals("Hello World!", new XmlStringLookup(new HashMap<>(), ABSENT_PATH, CURRENT_PATH).apply(DOC_RELATIVE + ":" + xpath)); - assertThrows(IllegalArgumentException.class, () -> new XmlStringLookup(new HashMap<>(), ABSENT_PATH).apply(DOC_ROOT + ":" + xpath)); - assertThrows(IllegalArgumentException.class, () -> new XmlStringLookup(new HashMap<>(), CURRENT_PATH).apply(DOC_ROOT + ":" + xpath)); - assertThrows(IllegalArgumentException.class, () -> new XmlStringLookup(new HashMap<>(), ABSENT_PATH, CURRENT_PATH).apply(DOC_ROOT + ":" + xpath)); + assertEquals(DATA, new XmlStringLookup(EMPTY_MAP, EMPTY_MAP).apply(DOC_RELATIVE + ":" + xpath)); + assertEquals(DATA, new XmlStringLookup(EMPTY_MAP, EMPTY_MAP).apply(DOC_RELATIVE + ":" + xpath)); + assertEquals(DATA, new XmlStringLookup(EMPTY_MAP, EMPTY_MAP, CURRENT_PATH, ABSENT_PATH).apply(DOC_RELATIVE + ":" + xpath)); + assertEquals(DATA, new XmlStringLookup(EMPTY_MAP, EMPTY_MAP, ABSENT_PATH, CURRENT_PATH).apply(DOC_RELATIVE + ":" + xpath)); + assertThrows(IllegalArgumentException.class, () -> new XmlStringLookup(EMPTY_MAP, EMPTY_MAP, ABSENT_PATH).apply(DOC_ROOT + ":" + xpath)); + assertThrows(IllegalArgumentException.class, () -> new XmlStringLookup(EMPTY_MAP, EMPTY_MAP, CURRENT_PATH).apply(DOC_ROOT + ":" + xpath)); + assertThrows(IllegalArgumentException.class, () -> new XmlStringLookup(EMPTY_MAP, EMPTY_MAP, ABSENT_PATH, CURRENT_PATH).apply(DOC_ROOT + ":" + xpath)); } @Test void testNoFeaturesDefault() { final HashMap features = new HashMap<>(1); features.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); - assertLookup(new XmlStringLookup(features)); + assertLookup(new XmlStringLookup(EMPTY_MAP, features)); } @Test @@ -94,5 +138,4 @@ void testToString() { // does not blow up and gives some kind of string. assertFalse(XmlStringLookup.INSTANCE.toString().isEmpty()); } - } diff --git a/src/test/resources/org/apache/commons/text/document-entity-ref.xml b/src/test/resources/org/apache/commons/text/document-entity-ref.xml new file mode 100644 index 0000000000..bfd3609802 --- /dev/null +++ b/src/test/resources/org/apache/commons/text/document-entity-ref.xml @@ -0,0 +1,26 @@ + + + + + Example of an External Entity + + &ext; + + diff --git a/src/test/resources/org/apache/commons/text/xml-entity.txt b/src/test/resources/org/apache/commons/text/xml-entity.txt new file mode 100644 index 0000000000..4f2fa75854 --- /dev/null +++ b/src/test/resources/org/apache/commons/text/xml-entity.txt @@ -0,0 +1,17 @@ + +Hello World! From ad1b4234f7e7be1d093cc2eb6e2fb9ddd22b472e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 06:11:02 -0500 Subject: [PATCH 177/265] Enable secure processing for the XML parser in XmlStringLookup #729 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index d0ab0b7d99..21f15a2f7f 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,6 +53,7 @@ The type attribute can be add,update,fix,remove. Fix Apache RAT plugin console warnings. Fix site XML to use version 2.0.0 XML schema. Removed unreachable threshold verification code in src/main/java/org/apache/commons/text/similarity #730. + Enable secure processing for the XML parser in XmlStringLookup #729. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. From 1387b9905db83d3373c261c1c3264d1ea26839f2 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 06:17:55 -0500 Subject: [PATCH 178/265] Bump commons.bytebuddy.version from 1.18.1 to 1.18.2 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5a00fd7778..0c180d36f2 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content 3.20.0 - 1.18.1 + 1.18.2 1.6 false 1.37 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 21f15a2f7f..bfb7505e85 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -62,7 +62,7 @@ The type attribute can be add,update,fix,remove. Add test assertions for SimilarityCharacterInput#equals() #727. Bump org.apache.commons:commons-parent from 85 to 93 #704, #723, #726. - Bump commons.bytebuddy.version from 1.17.6 to 1.18.1 #696, #722. + Bump commons.bytebuddy.version from 1.17.6 to 1.18.2 #696, #722. Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-io:commons-io from 2.20.0 to 2.21.0. From a9332893f51f79459b68e46d152342502eeac0a6 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 06:32:43 -0500 Subject: [PATCH 179/265] Fix Javadoc @link --- src/main/java/org/apache/commons/text/Builder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/Builder.java b/src/main/java/org/apache/commons/text/Builder.java index 30063d1809..c0405b9a85 100644 --- a/src/main/java/org/apache/commons/text/Builder.java +++ b/src/main/java/org/apache/commons/text/Builder.java @@ -80,7 +80,7 @@ * @param the type of object that the builder will construct or compute. * @since 1.0 * @see Supplier - * @deprecated Use :@link Supplier}. + * @deprecated Use {@link Supplier}. */ @Deprecated public interface Builder extends Supplier { From 081a9336f02d88176f833e10c9334fe9bd4116ea Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 07:07:54 -0500 Subject: [PATCH 180/265] Add XmlStringLookupTest.testInterpolatorSecureOnBla() --- .../commons/text/lookup/XmlStringLookupTest.java | 8 ++++++++ .../resources/org/apache/commons/text/bla.xml | 15 +++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/test/resources/org/apache/commons/text/bla.xml diff --git a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java index d24c40907e..a37cafbead 100644 --- a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java @@ -99,6 +99,14 @@ void testInterpolatorExternalEntityOnOverride() { () -> stringSubstitutor.replace("${xml:secure=true:" + DOC_DIR + "document-entity-ref.xml:/document/content}")); } + @Test + void testInterpolatorSecureOnBla() { + final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); + assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:" + DOC_DIR + "bla.xml:/document/content}")); + assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:secure=true:" + DOC_DIR + "bla.xml:/document/content}")); + // Using secure=false allows the BLA to occur. + } + @Test void testMissingXPath() { assertThrows(IllegalArgumentException.class, () -> XmlStringLookup.INSTANCE.apply(DOC_RELATIVE + ":!JUNK!")); diff --git a/src/test/resources/org/apache/commons/text/bla.xml b/src/test/resources/org/apache/commons/text/bla.xml new file mode 100644 index 0000000000..75fb24cae3 --- /dev/null +++ b/src/test/resources/org/apache/commons/text/bla.xml @@ -0,0 +1,15 @@ + + +&lol9; From 2d7ee62c2dea7aa3c0ee9fb368fa96854c4da8a2 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 07:12:25 -0500 Subject: [PATCH 181/265] Add XmlStringLookupTest.testInterpolatorSecureOnBla() --- .../resources/org/apache/commons/text/bla.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/resources/org/apache/commons/text/bla.xml b/src/test/resources/org/apache/commons/text/bla.xml index 75fb24cae3..72d248b450 100644 --- a/src/test/resources/org/apache/commons/text/bla.xml +++ b/src/test/resources/org/apache/commons/text/bla.xml @@ -1,4 +1,20 @@ + Date: Wed, 3 Dec 2025 07:49:20 -0500 Subject: [PATCH 182/265] Move the User's Guide to the Javadoc Overview It should always match the release that way. --- .../apache/commons/text/doc-files/leaf.svg | 45 +++ .../apache/commons/text/doc-files/logo.png | Bin 0 -> 9454 bytes src/main/javadoc/overview.html | 262 ++++++++++++++++ src/site/site.xml | 2 +- src/site/xdoc/userguide.xml | 293 ------------------ 5 files changed, 308 insertions(+), 294 deletions(-) create mode 100644 src/main/java/org/apache/commons/text/doc-files/leaf.svg create mode 100644 src/main/java/org/apache/commons/text/doc-files/logo.png create mode 100644 src/main/javadoc/overview.html delete mode 100644 src/site/xdoc/userguide.xml diff --git a/src/main/java/org/apache/commons/text/doc-files/leaf.svg b/src/main/java/org/apache/commons/text/doc-files/leaf.svg new file mode 100644 index 0000000000..71de588c64 --- /dev/null +++ b/src/main/java/org/apache/commons/text/doc-files/leaf.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/apache/commons/text/doc-files/logo.png b/src/main/java/org/apache/commons/text/doc-files/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0c32a3e474662557f6cccc6cfd381a2fecf946ee GIT binary patch literal 9454 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 literal 0 HcmV?d00001 diff --git a/src/main/javadoc/overview.html b/src/main/javadoc/overview.html new file mode 100644 index 0000000000..1acbbbbab1 --- /dev/null +++ b/src/main/javadoc/overview.html @@ -0,0 +1,262 @@ + + + +Apache Commons Text Overview + + + Apache Commons Text + +
    +

    + leafIntroducing Apache Commons Text +

    +

    Apache Commons Text is a set of utility functions and reusable components for processing and manipulating text in a Java environment.

    +
    +
    +

    leafTable of Contents

    +
      +
    1. Description
    2. +
    3. Using the text package +
    4. +
    5. Using the text.diff package +
    6. +
    7. Using the text.lookup package +
    8. +
    9. tUsing the text.similarity package +
    10. +
    11. Using the text.translate package +
    12. +
    13. Requirements +
    14. +
    +
    +
    +

    leafDescription

    +

    The Commons Text library provides additions to the standard JDK's text handling. Our goal is to provide a consistent set of tools for processing text + generally from computing distances between Strings to being able to efficiently do String escaping of various types.

    +
    +
    +

    leafUsing the org.apache.commons.text package

    +

    + Originally the text package was added in Commons Lang 2.2. However, its new home is here. It provides, amongst other classes, a replacement for + StringBuffer + named + StrBuilder + , a class for substituting variables within a String named + StrSubstitutor + and a replacement for StringTokenizer named + StrTokenizer + . While somewhat ungainly, the + Str + prefix has been used to ensure we don't clash with any current or future standard Java classes. +

    +

    Beyond the text utilities ported over from Commons Lang, we have also included various string similarity and distance functions. Lastly, there are + also utilities for addressing differences between bodies of text for the sake of viewing these differences.

    +
    +

    Class StringEscapeUtils

    +

    + From Lang 3.5, we have moved into Text StringEscapeUtils and StrTokenizer. It provides ways in which to generate pieces of text, such as might be used + for default passwords. StringEscapeUtils contains methods to escape and unescape Java, JavaScript, HTML and XML. It is worth noting that the package + org.apache.commons.text.translate + holds the functionality underpinning the StringEscapeUtils with mappings and translations between such mappings for the sake of doing String escaping. + StrTokenizer is an improved alternative to java.util.StringTokenizer. +

    +
    +
    +

    Class StringSubstitutor

    +

    The simplest example is to use this class to replace Java System properties. For example:

    +
    +        StringSubstitutor.replaceSystemProperties(
    +          "You are running with java.version = ${java.version} and os.name = ${os.name}.");
    +        
    +

    + For details see StringSubstitutor. +

    +

    + Use a StringSubstitutorReader + to avoid reading a whole file into memory as a + String + to perform string substitution, for example, when a Servlet filters a file to a client. +

    +

    To build a default full-featured substitutor, use:

    + +

    + The available substitutions are defined in org.apache.commons.text.lookup.StringLookupFactory. +

    +
    +
    +

    Similarity and Distance

    +

    + The + org.apache.commons.text.similarity + packages contains various different mechanisms of calculating "similarity scores" as well as "edit distances between Strings. Note, the difference + between a "similarity score" and a "distance function" is that a distance functions meets the following qualifications: +

    +
      +
    • d(x,y) >= 0, non-negativity or separation axiom
    • +
    • d(x,y) == 0, if and only if, x == y
    • +
    • d(x,y) == d(y,x), symmetry, and
    • +
    • d(x,z) <= d(x,y) + d(y,z), the triangle inequality
    • +
    +

    whereas a "similarity score" need not satisfy all such properties. Though, it is fairly easy to "normalize" a similarity score to manufacture an + "edit distance."

    +

    The list of "edit distances" that we currently support follow:

    +
      +
    • Cosine Distance,
    • +
    • Hamming Distance,
    • +
    • Jaccard Distance,
    • +
    • Jaro Winkler Distance,
    • +
    • Levenshtein Distance,
    • +
    • Longest Commons Subsequence Distance,
    • +
    +

    and the list of "similarity scores" that we support follows:

    +
      +
    • Cosine Similarity,
    • +
    • Fuzzy Score Similarity,
    • +
    • Jaccard Similarity,
    • +
    • Jaro-Winkler Similarity, and
    • +
    • Longest Common Subsequence Similarity.
    • +
    +
    +
    +

    Text diff'ing

    +

    + The + org.apache.commons.text.diff + package contains code for doing diff between strings. The initial implementation of the Myers algorithm was adapted from the commons-collections + sequence package. +

    +
    +
    +
    +

    Package org.apache.commons.text.diff

    + +

    Provides algorithms for diff between strings.

    +

    The initial implementation of the Myers algorithm was adapted from the commons-collections sequence package.

    +
    +
    +

    leafUsing the org.apache.commons.text.lookup package

    +

    + Provides algorithms for looking up strings used by a StringSubstitutor. Standard lookups are + defined in StringLookupFactory + and the associated DefaultStringLookup + enum. +

    +

    + The example below demonstrates use of the default lookups for + StringSubstitutor + in order to construct a complex string. +

    +

    + NOTE: The list of lookups available by default changed in version 1.10.0. See the documentation for StringLookupFactory for + details and instructions on how to reproduce the previous behavior. +

    +
    +final StringSubstitutor interpolator = StringSubstitutor.createInterpolator();
    +final String text = interpolator.replace(
    +    "Base64 Decoder:        ${base64Decoder:SGVsbG9Xb3JsZCE=}\n" +
    +    "Base64 Encoder:        ${base64Encoder:HelloWorld!}\n" +
    +    "Java Constant:         ${const:java.awt.event.KeyEvent.VK_ESCAPE}\n" +
    +    "Date:                  ${date:yyyy-MM-dd}\n" +
    +    "Environment Variable:  ${env:USERNAME}\n" +
    +    "File Content:          ${file:UTF-8:src/test/resources/document.properties}\n" +
    +    "Java:                  ${java:version}\n" +
    +    "Local host:            ${localhost:canonical-name}\n" +
    +    "Loopback address:      ${loopbackAddress:canonical-name}\n" +
    +    "Properties File:       ${properties:src/test/resources/document.properties::mykey}\n" +
    +    "Resource Bundle:       ${resourceBundle:org.apache.commons.text.example.testResourceBundleLookup:mykey}\n" +
    +    "System Property:       ${sys:user.dir}\n" +
    +    "URL Decoder:           ${urlDecoder:Hello%20World%21}\n" +
    +    "URL Encoder:           ${urlEncoder:Hello World!}\n" +
    +    "XML Decoder:           ${xmlDecoder:&lt;element&gt;}\n" +
    +    "XML Encoder:           ${xmlEncoder:<element>}\n" +
    +    "XML XPath:             ${xml:src/test/resources/document.xml:/root/path/to/node}\n");
    +    
    +
    +
    +

    leafUsing the org.apache.commons.text.similarity package

    + +

    Provides algorithms for string similarity.

    +

    The algorithms that implement the EditDistance interface follow the same simple principle: the more similar (closer) strings are, the lower is the + distance. For example, the words house and hose are closer than house and trousers.

    +

    The following algorithms are available at the moment:

    +
      +
    • CosineDistance
    • +
    • CosineSimilarity
    • +
    • FuzzyScore
    • +
    • HammingDistance
    • +
    • JaroWinklerDistance
    • +
    • JaroWinklerSimilarity
    • +
    • LevenshteinDistance
    • +
    • LongestCommonSubsequenceDistance
    • +
    +

    + The + CosineDistance + utilises a + RegexTokenizer + regular expression tokenizer (\w+). And the + LevenshteinDistance + 's behavior can be changed to take into consideration a maximum throughput. +

    +
    +
    +

    leafUsing the org.apache.commons.text.translate package

    + +

    An API for creating text translation routines from a set of smaller building blocks. Initially created to make it possible for the user to customize + the rules in the StringEscapeUtils class.

    +

    These classes are immutable, and therefore thread-safe.

    +
    +
    +

    + leafRequirements +

    +
      +
    • Java 8 or above.
    • +
    • If using OSGi, R7 or above.
    • +
    +
    + \ No newline at end of file diff --git a/src/site/site.xml b/src/site/site.xml index 484a229cc1..b58c30f6ff 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -26,7 +26,7 @@ - + diff --git a/src/site/xdoc/userguide.xml b/src/site/xdoc/userguide.xml deleted file mode 100644 index 569256be8d..0000000000 --- a/src/site/xdoc/userguide.xml +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - Commons Text - User guide - Apache Commons Team - - - - -
    -
    -

    The Commons Text Package -

    -

    Users Guide

    -
    - [Description] - [text] - [text.diff] - [text.lookup] - [text.similarity] - [text.translate] -
    -
    -
    -
    - -
    -

    The Commons Text library provides additions to the standard JDK's - text handling. Our goal is to provide a consistent set of tools for - processing text generally from computing distances between Strings - to being able to efficiently do String escaping of various types. -

    -
    - -
    - -

    Originally the text package was added in Commons Lang 2.2. However, its - new home is here. It provides, amongst other - classes, a replacement for StringBuffer named - StrBuilder, a class for substituting variables within a String - named StrSubstitutor and a replacement for StringTokenizer - named StrTokenizer. While somewhat ungainly, the - Str - prefix has been used to ensure we don't clash with any current - or future standard Java classes. -

    - -

    Beyond the text utilities ported over from Commons Lang, we have also included various - string similarity and distance functions. Lastly, there are also utilities for - addressing differences between bodies of text for the sake of viewing these - differences. -

    - - -

    From Lang 3.5, we have moved into Text StringEscapeUtils and StrTokenizer. - It provides ways in which to generate pieces of text, such as might - be used for default passwords. StringEscapeUtils contains methods to - escape and unescape Java, JavaScript, HTML and XML. It is worth noting that - the package org.apache.commons.text.translate holds the - functionality underpinning the StringEscapeUtils with mappings and translations - between such mappings for the sake of doing String escaping. StrTokenizer is - an improved alternative to java.util.StringTokenizer. -

    -
    - - -

    - The simplest example is to use this class to replace Java System properties. For example: -

                  
    -        StringSubstitutor.replaceSystemProperties(
    -          "You are running with java.version = ${java.version} and os.name = ${os.name}.");
    -        
    -

    -

    - For details see StringSubstitutor. -

    -

    - Use a StringSubstitutorReader - to avoid reading a whole file into memory as a String to perform string substitution, for example, when a Servlet filters a file to a client. -

    -

    - To build a default full-featured substitutor, use: -

    - -

    - The available substitutions are defined in - org.apache.commons.text.lookup.StringLookupFactory. -

    -
    - - -

    The org.apache.commons.text.similarity packages contains various different mechanisms of - calculating "similarity scores" as well as "edit distances between Strings. Note, - the difference between a "similarity score" and a "distance function" is that - a distance functions meets the following qualifications: -

      -
    • d(x,y) >= 0, non-negativity or separation axiom -
    • -
    • d(x,y) == 0, if and only if, - x == y -
    • -
    • d(x,y) == d(y,x), symmetry, and -
    • -
    • d(x,z) <= d(x,y) + d(y,z), the triangle inequality -
    • -
    - whereas a "similarity score" need not satisfy all such properties. Though, it - is fairly easy to "normalize" a similarity score to manufacture an "edit distance." -

    -

    - The list of "edit distances" that we currently support follow: -

      -
    • Cosine Distance,
    • -
    • Hamming Distance,
    • -
    • Jaccard Distance,
    • -
    • Jaro Winkler Distance,
    • -
    • Levenshtein Distance,
    • -
    • Longest Commons Subsequence Distance,
    • -
    - and the list of "similarity scores" that we support follows: -
      -
    • Cosine Similarity,
    • -
    • Fuzzy Score Similarity,
    • -
    • Jaccard Similarity,
    • -
    • Jaro-Winkler Similarity, and
    • -
    • Longest Common Subsequence Similarity.
    • -
    -

    -
    - - -

    The org.apache.commons.text.diff package contains code for - doing diff between strings. The initial implementation of the Myers algorithm was adapted from the - commons-collections sequence package. -

    -
    - - -
    - -
    - -

    Provides algorithms for diff between strings.

    -

    The initial implementation of the Myers algorithm was adapted from the - commons-collections sequence package. -

    -
    - -
    -

    Provides algorithms for looking up strings used by a - StringSubstitutor. - Standard lookups are defined in - StringLookupFactory - and the associated - DefaultStringLookup - enum. -

    -

    - The example below demonstrates use of the default lookups for StringSubstitutor in order to - construct a complex string. -

    -

    NOTE: The list of lookups available by default changed in version 1.10.0. See the documentation for - StringLookupFactory - for details and instructions on how to reproduce the previous behavior. -

    - -final StringSubstitutor interpolator = StringSubstitutor.createInterpolator(); -final String text = interpolator.replace( - "Base64 Decoder: ${base64Decoder:SGVsbG9Xb3JsZCE=}\n" + - "Base64 Encoder: ${base64Encoder:HelloWorld!}\n" + - "Java Constant: ${const:java.awt.event.KeyEvent.VK_ESCAPE}\n" + - "Date: ${date:yyyy-MM-dd}\n" + - "Environment Variable: ${env:USERNAME}\n" + - "File Content: ${file:UTF-8:src/test/resources/document.properties}\n" + - "Java: ${java:version}\n" + - "Local host: ${localhost:canonical-name}\n" + - "Loopback address: ${loopbackAddress:canonical-name}\n" + - "Properties File: ${properties:src/test/resources/document.properties::mykey}\n" + - "Resource Bundle: ${resourceBundle:org.apache.commons.text.example.testResourceBundleLookup:mykey}\n" + - "System Property: ${sys:user.dir}\n" + - "URL Decoder: ${urlDecoder:Hello%20World%21}\n" + - "URL Encoder: ${urlEncoder:Hello World!}\n" + - "XML Decoder: ${xmlDecoder:&lt;element&gt;}\n" + - "XML Encoder: ${xmlEncoder:<element>}\n" + - "XML XPath: ${xml:src/test/resources/document.xml:/root/path/to/node}\n" -); - -
    - -
    - -

    Provides algorithms for string similarity.

    - -

    The algorithms that implement the EditDistance interface follow the - same - simple principle: the more similar (closer) strings are, the lower is the - distance. - For example, the words house and hose are closer than house and - trousers. -

    - -

    The following algorithms are available at the moment:

    - -
      -
    • - CosineDistance -
    • -
    • - CosineSimilarity -
    • -
    • - FuzzyScore -
    • -
    • - HammingDistance -
    • -
    • - JaroWinklerDistance -
    • -
    • - JaroWinklerSimilarity -
    • -
    • - LevenshteinDistance -
    • -
    • - LongestCommonSubsequenceDistance -
    • -
    - -

    The CosineDistance utilises a - RegexTokenizer - regular expression tokenizer (\w+). And the - LevenshteinDistance's - behavior can be changed to take into consideration a maximum - throughput. -

    -
    - -
    - -

    An API for creating text translation routines from a set of smaller - building blocks. Initially created to make it possible for the user to - customize the rules in the StringEscapeUtils class. -

    -

    These classes are immutable, and therefore thread-safe.

    -
    - - -
    From 66a0eac0102fde494ed4ff58b5c1687134b1e2bc Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 07:57:28 -0500 Subject: [PATCH 183/265] Normalize site menu --- src/site/site.xml | 56 +++++++++++++++++++++++------------------ src/site/xdoc/index.xml | 2 +- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/site/site.xml b/src/site/site.xml index b58c30f6ff..8a40a2ed93 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -17,30 +17,38 @@ --> - + xsi:schemaLocation="http://maven.apache.org/SITE/2.0.0 http://maven.apache.org/xsd/site-2.0.0.xsd" + name="Apache Commons Text"> + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index 3dc566a21e..dfbaffa0ac 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -32,7 +32,7 @@ Apache Commons Text is a library focused on algorithms working on strings.

    -We provide documentation in the form of a User Guide, +We provide documentation in the form of a User Guide, Javadoc, and Project Reports.

    From 04f779aa158b65d3089b99d4e9ed454eed9b0bf0 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 08:41:40 -0500 Subject: [PATCH 184/265] Better release description --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index bfb7505e85..e689fcd749 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -45,7 +45,7 @@ The type attribute can be add,update,fix,remove. Apache Commons Text Changes - + Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. From abce711cbf63098ad9c1e9f26b8bcf7111614dba Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 08:48:01 -0500 Subject: [PATCH 185/265] Javadoc --- .../text/lookup/ConstantStringLookup.java | 18 +++++++++--------- .../commons/text/lookup/DateStringLookup.java | 4 ++-- .../text/lookup/IllegalArgumentExceptions.java | 14 +++++++------- .../text/lookup/InetAddressStringLookup.java | 2 +- .../text/lookup/InterpolatorStringLookup.java | 4 ++-- .../text/lookup/JavaPlatformStringLookup.java | 4 ++-- .../text/lookup/PropertiesStringLookup.java | 2 +- .../lookup/ResourceBundleStringLookup.java | 2 +- .../text/lookup/ScriptStringLookup.java | 2 +- .../text/lookup/StringLookupFactory.java | 14 +++++++------- .../commons/text/lookup/UrlStringLookup.java | 2 +- 11 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java b/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java index dff4509846..ddd95e0343 100644 --- a/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java @@ -91,9 +91,9 @@ static void clear() { * * ClassUtils. * - * @param className the name of the class to be loaded - * @return The corresponding class object - * @throws ClassNotFoundException if the class cannot be loaded + * @param className the name of the class to be loaded. + * @return The corresponding class object. + * @throws ClassNotFoundException if the class cannot be loaded. */ protected Class fetchClass(final String className) throws ClassNotFoundException { return ClassUtils.getClass(className); @@ -105,8 +105,8 @@ protected Class fetchClass(final String className) throws ClassNotFoundExcept * cache. Otherwise this method will invoke the {@code resolveField()} method and pass in the name of the class and * the field. * - * @param key the name of the variable to be resolved - * @return The value of this variable or null if it cannot be resolved + * @param key the name of the variable to be resolved. + * @return The value of this variable or null if it cannot be resolved. */ @Override public synchronized String lookup(final String key) { @@ -141,10 +141,10 @@ public synchronized String lookup(final String key) { * {@code fetchClass()} to obtain the {@link Class} object for the target class. Then it will use * reflection to obtain the field's value. For this to work the field must be accessible. * - * @param className the name of the class - * @param fieldName the name of the member field of that class to read - * @return The field's value - * @throws ReflectiveOperationException if an error occurs + * @param className the name of the class. + * @param fieldName the name of the member field of that class to read. + * @return The field's value. + * @throws ReflectiveOperationException if an error occurs. */ protected Object resolveField(final String className, final String fieldName) throws ReflectiveOperationException { final Class clazz = fetchClass(className); diff --git a/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java b/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java index fe313c2bf3..a7dc0b7123 100644 --- a/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java @@ -66,9 +66,9 @@ private DateStringLookup() { /** * Formats the given {@code date} long with the given {@code format}. * - * @param dateMillis the date to format + * @param dateMillis the date to format. * @param format the format string for {@link SimpleDateFormat}. - * @return The formatted date + * @return The formatted date. */ private String formatDate(final long dateMillis, final String format) { FastDateFormat dateFormat = null; diff --git a/src/main/java/org/apache/commons/text/lookup/IllegalArgumentExceptions.java b/src/main/java/org/apache/commons/text/lookup/IllegalArgumentExceptions.java index 3eac7d4a2d..e52d5360b5 100644 --- a/src/main/java/org/apache/commons/text/lookup/IllegalArgumentExceptions.java +++ b/src/main/java/org/apache/commons/text/lookup/IllegalArgumentExceptions.java @@ -28,9 +28,9 @@ final class IllegalArgumentExceptions { * Creates an {@link IllegalArgumentException} with a message * formatted with {@link String#format(String,Object...)}. * - * @param format See {@link String#format(String,Object...)} - * @param args See {@link String#format(String,Object...)} - * @return an {@link IllegalArgumentException} with a message formatted with {@link String#format(String,Object...)} + * @param format See {@link String#format(String,Object...)}. + * @param args See {@link String#format(String,Object...)}. + * @return an {@link IllegalArgumentException} with a message formatted with {@link String#format(String,Object...)}. */ static IllegalArgumentException format(final String format, final Object... args) { return new IllegalArgumentException(String.format(format, args)); @@ -40,10 +40,10 @@ static IllegalArgumentException format(final String format, final Object... args * Creates an {@link IllegalArgumentException} with a message * formatted with {@link String#format(String,Object...)}. * - * @param t the throwable cause - * @param format See {@link String#format(String,Object...)} - * @param args See {@link String#format(String,Object...)} - * @return an {@link IllegalArgumentException} with a message formatted with {@link String#format(String,Object...)} + * @param t the throwable cause. + * @param format See {@link String#format(String,Object...)}. + * @param args See {@link String#format(String,Object...)}. + * @return an {@link IllegalArgumentException} with a message formatted with {@link String#format(String,Object...)}. */ static IllegalArgumentException format(final Throwable t, final String format, final Object... args) { return new IllegalArgumentException(String.format(format, args), t); diff --git a/src/main/java/org/apache/commons/text/lookup/InetAddressStringLookup.java b/src/main/java/org/apache/commons/text/lookup/InetAddressStringLookup.java index 6d0183db9c..5a9a72a359 100644 --- a/src/main/java/org/apache/commons/text/lookup/InetAddressStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/InetAddressStringLookup.java @@ -55,7 +55,7 @@ final class InetAddressStringLookup extends AbstractStringLookup { static final InetAddressStringLookup LOOPACK_ADDRESS = new InetAddressStringLookup(InetAddress::getLoopbackAddress); /** - * Supplies the InetAddress. + * Supplies the {@link InetAddress}. */ private final FailableSupplier inetAddressSupplier; diff --git a/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java b/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java index 17e3da7b93..9027c5d5f4 100644 --- a/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java @@ -113,8 +113,8 @@ public Map getStringLookupMap() { * the prefix stripped to the lookup object registered for this prefix. If no prefix can be found or if the * associated lookup object cannot resolve this variable, the default lookup object will be used. * - * @param key the name of the variable whose value is to be looked up - * @return The value of this variable or null if it cannot be resolved + * @param key the name of the variable whose value is to be looked up. + * @return The value of this variable or null if it cannot be resolved. */ @Override public String lookup(String key) { diff --git a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java index 734e2dd436..faf01ee9cb 100644 --- a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java @@ -156,7 +156,7 @@ private String getSystemProperty(final String name) { /** * Gets the given system property. * - * @param prefix the prefix to use for the result string + * @param prefix the prefix to use for the result string. * @param name a system property name. * @return The prefix + a system property value. */ @@ -192,7 +192,7 @@ String getVirtualMachine() { *

  • locale: "default locale: en_US, platform encoding: iso-8859-1"
  • * * - * @param key the key to be looked up, may be null + * @param key the key to be looked up, may be null. * @return The value of the environment variable. */ @Override diff --git a/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java b/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java index dab5f62d5d..b5aa177116 100644 --- a/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/PropertiesStringLookup.java @@ -78,7 +78,7 @@ static String toPropertyKey(final String file, final String key) { * Note the use of "::" instead of ":" to allow for "C:" drive letters in paths. *

    * - * @param key the key to be looked up, may be null + * @param key the key to be looked up, may be null. * @return The value associated with the key. */ @Override diff --git a/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java b/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java index a517058ecc..6ffcc5b4a9 100644 --- a/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java @@ -79,7 +79,7 @@ String getString(final String keyBundleName, final String bundleKey) { * * For example: "com.domain.messages:MyKey". * - * @param key the key to be looked up, may be null + * @param key the key to be looked up, may be null. * @return The value associated with the key. * @see ResourceBundle * @see ResourceBundle#getBundle(String) diff --git a/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java b/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java index 4151a732f7..2ed725b456 100644 --- a/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java @@ -66,7 +66,7 @@ private ScriptStringLookup() { * For example: {@code "javascript:3 + 4"}. *

    * - * @param key the engine:script to execute, may be null + * @param key the engine:script to execute, may be null. * @return The value returned by the execution. */ @Override diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java index f172f58870..3135f5fae3 100644 --- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java +++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java @@ -278,8 +278,8 @@ static final class DefaultStringLookupsHolder { * Adds the key and string lookup from {@code lookup} to {@code map}, also adding any additional key aliases if needed. Keys are normalized using the * {@link #toKey(String)} method. * - * @param lookup lookup to add - * @param map map to add to + * @param lookup lookup to add. + * @param map map to add to. */ private static void addLookup(final DefaultStringLookup lookup, final Map map) { map.put(toKey(lookup.getKey()), lookup.getStringLookup()); @@ -292,7 +292,7 @@ private static void addLookup(final DefaultStringLookup lookup, final Map createDefaultStringLookups() { final Map lookupMap = new HashMap<>(); @@ -320,8 +320,8 @@ private static Map createDefaultStringLookups() { * Constructs a lookup map by parsing the given string. The string is expected to contain comma or space-separated names of values from the * {@link DefaultStringLookup} enum. If the given string is null or empty, an empty map is returned. * - * @param str string to parse; may be null or empty - * @return lookup map parsed from the given string + * @param str string to parse; may be null or empty. + * @return lookup map parsed from the given string. */ private static Map parseStringLookups(final String str) { final Map lookupMap = new HashMap<>(); @@ -343,7 +343,7 @@ private static Map parseStringLookups(final String str) { /** * Constructs a new instance initialized with the given properties. * - * @param props initialization properties + * @param props initialization properties. */ DefaultStringLookupsHolder(final Properties props) { final Map lookups = props.containsKey(DEFAULT_STRING_LOOKUPS_PROPERTY) @@ -355,7 +355,7 @@ private static Map parseStringLookups(final String str) { /** * Gets the default string lookups map. * - * @return default string lookups map + * @return default string lookups map. */ Map getDefaultStringLookups() { return defaultStringLookups; diff --git a/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java index 948f2b1bef..473c546da4 100644 --- a/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java @@ -60,7 +60,7 @@ private UrlStringLookup() { * For example: "UTF-8:https://www.apache.org". *

    * - * @param key the key to be looked up, may be null + * @param key the key to be looked up, may be null. * @return The value associated with the key. */ @Override From fd98b6ed6403348f181f8440fb43781d6b5ec388 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 08:50:16 -0500 Subject: [PATCH 186/265] Javadoc --- .../text/matcher/AbstractStringMatcher.java | 102 +++++++++--------- .../commons/text/matcher/StringMatcher.java | 12 +-- .../text/matcher/StringMatcherFactory.java | 40 +++---- 3 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/main/java/org/apache/commons/text/matcher/AbstractStringMatcher.java b/src/main/java/org/apache/commons/text/matcher/AbstractStringMatcher.java index 68ec022d23..04dc401689 100644 --- a/src/main/java/org/apache/commons/text/matcher/AbstractStringMatcher.java +++ b/src/main/java/org/apache/commons/text/matcher/AbstractStringMatcher.java @@ -124,11 +124,11 @@ static final class CharArrayMatcher extends AbstractStringMatcher { /** * Returns the number of matching characters, {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param start the starting position for the match, valid for buffer - * @param bufferStart unused - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param start the starting position for the match, valid for buffer. + * @param bufferStart unused. + * @param bufferEnd the end index of the active buffer, valid for buffer. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final char[] buffer, final int start, final int bufferStart, final int bufferEnd) { @@ -148,11 +148,11 @@ public int isMatch(final char[] buffer, final int start, final int bufferStart, /** * Returns the number of matching characters, {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param start the starting position for the match, valid for buffer - * @param bufferStart unused - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param start the starting position for the match, valid for buffer. + * @param bufferStart unused. + * @param bufferEnd the end index of the active buffer, valid for buffer. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final CharSequence buffer, final int start, final int bufferStart, final int bufferEnd) { @@ -209,11 +209,11 @@ static final class CharMatcher extends AbstractStringMatcher { /** * Returns {@code 1} if there is a match, or {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param start the starting position for the match, valid for buffer - * @param bufferStart unused - * @param bufferEnd unused - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param start the starting position for the match, valid for buffer. + * @param bufferStart unused. + * @param bufferEnd unused. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final char[] buffer, final int start, final int bufferStart, final int bufferEnd) { @@ -223,11 +223,11 @@ public int isMatch(final char[] buffer, final int start, final int bufferStart, /** * Returns {@code 1} if there is a match, or {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param start the starting position for the match, valid for buffer - * @param bufferStart unused - * @param bufferEnd unused - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param start the starting position for the match, valid for buffer. + * @param bufferStart unused. + * @param bufferEnd unused. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final CharSequence buffer, final int start, final int bufferStart, final int bufferEnd) { @@ -264,7 +264,7 @@ static final class CharSetMatcher extends AbstractStringMatcher { /** * Constructs a matcher from a character array. * - * @param chars the characters to match, must not be null + * @param chars the characters to match, must not be null. */ CharSetMatcher(final char[] chars) { this.chars = chars.clone(); @@ -274,11 +274,11 @@ static final class CharSetMatcher extends AbstractStringMatcher { /** * Returns {@code 1} if there is a match, or {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param start the starting position for the match, valid for buffer - * @param bufferStart unused - * @param bufferEnd unused - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param start the starting position for the match, valid for buffer. + * @param bufferStart unused. + * @param bufferEnd unused. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final char[] buffer, final int start, final int bufferStart, final int bufferEnd) { @@ -288,11 +288,11 @@ public int isMatch(final char[] buffer, final int start, final int bufferStart, /** * Returns {@code 1} if there is a match, or {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param start the starting position for the match, valid for buffer - * @param bufferStart unused - * @param bufferEnd unused - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param start the starting position for the match, valid for buffer. + * @param bufferStart unused. + * @param bufferEnd unused. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final CharSequence buffer, final int start, final int bufferStart, final int bufferEnd) { @@ -333,11 +333,11 @@ static final class NoneMatcher extends AbstractStringMatcher { /** * Always returns {@code 0}. * - * @param buffer unused - * @param start unused - * @param bufferStart unused - * @param bufferEnd unused - * @return The number of matching characters, zero for no match + * @param buffer unused. + * @param start unused. + * @param bufferStart unused. + * @param bufferEnd unused. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final char[] buffer, final int start, final int bufferStart, final int bufferEnd) { @@ -347,11 +347,11 @@ public int isMatch(final char[] buffer, final int start, final int bufferStart, /** * Always returns {@code 0}. * - * @param buffer unused - * @param start unused - * @param bufferStart unused - * @param bufferEnd unused - * @return The number of matching characters, zero for no match + * @param buffer unused. + * @param start unused. + * @param bufferStart unused. + * @param bufferEnd unused. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final CharSequence buffer, final int start, final int bufferStart, final int bufferEnd) { @@ -392,11 +392,11 @@ static final class TrimMatcher extends AbstractStringMatcher { /** * Returns {@code 1} if there is a match, or {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param start the starting position for the match, valid for buffer - * @param bufferStart unused - * @param bufferEnd unused - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param start the starting position for the match, valid for buffer. + * @param bufferStart unused. + * @param bufferEnd unused. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final char[] buffer, final int start, final int bufferStart, final int bufferEnd) { @@ -406,11 +406,11 @@ public int isMatch(final char[] buffer, final int start, final int bufferStart, /** * Returns {@code 1} if there is a match, or {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param start the starting position for the match, valid for buffer - * @param bufferStart unused - * @param bufferEnd unused - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param start the starting position for the match, valid for buffer. + * @param bufferStart unused. + * @param bufferEnd unused. + * @return The number of matching characters, zero for no match. */ @Override public int isMatch(final CharSequence buffer, final int start, final int bufferStart, final int bufferEnd) { diff --git a/src/main/java/org/apache/commons/text/matcher/StringMatcher.java b/src/main/java/org/apache/commons/text/matcher/StringMatcher.java index af94b86831..57d93b5d19 100644 --- a/src/main/java/org/apache/commons/text/matcher/StringMatcher.java +++ b/src/main/java/org/apache/commons/text/matcher/StringMatcher.java @@ -53,9 +53,9 @@ default StringMatcher andThen(final StringMatcher stringMatcher) { * characters that matched. *

    * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param pos the starting position for the match, valid for buffer. + * @return The number of matching characters, zero for no match. * @since 1.9 */ default int isMatch(final char[] buffer, final int pos) { @@ -106,9 +106,9 @@ default int isMatch(final char[] buffer, final int pos) { * characters that matched. *

    * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @return The number of matching characters, zero for no match + * @param buffer the text content to match against, do not change. + * @param pos the starting position for the match, valid for buffer. + * @return The number of matching characters, zero for no match. * @since 1.9 */ default int isMatch(final CharSequence buffer, final int pos) { diff --git a/src/main/java/org/apache/commons/text/matcher/StringMatcherFactory.java b/src/main/java/org/apache/commons/text/matcher/StringMatcherFactory.java index 0a3b9d8afd..b3c1226575 100644 --- a/src/main/java/org/apache/commons/text/matcher/StringMatcherFactory.java +++ b/src/main/java/org/apache/commons/text/matcher/StringMatcherFactory.java @@ -91,7 +91,7 @@ private StringMatcherFactory() { /** * Creates a matcher that matches all of the given matchers in order. * - * @param stringMatchers the matcher + * @param stringMatchers the matcher. * @return a matcher that matches all of the given matchers in order. * @since 1.9 */ @@ -109,8 +109,8 @@ public StringMatcher andMatcher(final StringMatcher... stringMatchers) { /** * Constructor that creates a matcher from a character. * - * @param ch the character to match, must not be null - * @return a new Matcher for the given char + * @param ch the character to match, must not be null. + * @return a new Matcher for the given char. */ public StringMatcher charMatcher(final char ch) { return new AbstractStringMatcher.CharMatcher(ch); @@ -119,8 +119,8 @@ public StringMatcher charMatcher(final char ch) { /** * Constructor that creates a matcher from a set of characters. * - * @param chars the characters to match, null or empty matches nothing - * @return a new matcher for the given char[] + * @param chars the characters to match, null or empty matches nothing. + * @return a new matcher for the given char[]. */ public StringMatcher charSetMatcher(final char... chars) { final int len = ArrayUtils.getLength(chars); @@ -136,8 +136,8 @@ public StringMatcher charSetMatcher(final char... chars) { /** * Creates a matcher from a string representing a set of characters. * - * @param chars the characters to match, null or empty matches nothing - * @return a new Matcher for the given characters + * @param chars the characters to match, null or empty matches nothing. + * @return a new Matcher for the given characters. */ public StringMatcher charSetMatcher(final String chars) { final int len = StringUtils.length(chars); @@ -153,7 +153,7 @@ public StringMatcher charSetMatcher(final String chars) { /** * Returns a matcher which matches the comma character. * - * @return a matcher for a comma + * @return a matcher for a comma. */ public StringMatcher commaMatcher() { return COMMA_MATCHER; @@ -162,7 +162,7 @@ public StringMatcher commaMatcher() { /** * Returns a matcher which matches the double quote character. * - * @return a matcher for a double quote + * @return a matcher for a double quote. */ public StringMatcher doubleQuoteMatcher() { return DOUBLE_QUOTE_MATCHER; @@ -171,7 +171,7 @@ public StringMatcher doubleQuoteMatcher() { /** * Matches no characters. * - * @return a matcher that matches nothing + * @return a matcher that matches nothing. */ public StringMatcher noneMatcher() { return NONE_MATCHER; @@ -180,7 +180,7 @@ public StringMatcher noneMatcher() { /** * Returns a matcher which matches the single or double quote character. * - * @return a matcher for a single or double quote + * @return a matcher for a single or double quote. */ public StringMatcher quoteMatcher() { return QUOTE_MATCHER; @@ -189,7 +189,7 @@ public StringMatcher quoteMatcher() { /** * Returns a matcher which matches the single quote character. * - * @return a matcher for a single quote + * @return a matcher for a single quote. */ public StringMatcher singleQuoteMatcher() { return SINGLE_QUOTE_MATCHER; @@ -198,7 +198,7 @@ public StringMatcher singleQuoteMatcher() { /** * Returns a matcher which matches the space character. * - * @return a matcher for a space + * @return a matcher for a space. */ public StringMatcher spaceMatcher() { return SPACE_MATCHER; @@ -207,7 +207,7 @@ public StringMatcher spaceMatcher() { /** * Matches the same characters as StringTokenizer, namely space, tab, newline and form feed. * - * @return The split matcher + * @return The split matcher. */ public StringMatcher splitMatcher() { return SPLIT_MATCHER; @@ -216,8 +216,8 @@ public StringMatcher splitMatcher() { /** * Creates a matcher from a string. * - * @param chars the string to match, null or empty matches nothing - * @return a new Matcher for the given String + * @param chars the string to match, null or empty matches nothing. + * @return a new Matcher for the given String. * @since 1.9 */ public StringMatcher stringMatcher(final char... chars) { @@ -230,8 +230,8 @@ public StringMatcher stringMatcher(final char... chars) { /** * Creates a matcher from a string. * - * @param str the string to match, null or empty matches nothing - * @return a new Matcher for the given String + * @param str the string to match, null or empty matches nothing. + * @return a new Matcher for the given String. */ public StringMatcher stringMatcher(final String str) { return StringUtils.isEmpty(str) ? NONE_MATCHER : stringMatcher(str.toCharArray()); @@ -240,7 +240,7 @@ public StringMatcher stringMatcher(final String str) { /** * Returns a matcher which matches the tab character. * - * @return a matcher for a tab + * @return a matcher for a tab. */ public StringMatcher tabMatcher() { return TAB_MATCHER; @@ -249,7 +249,7 @@ public StringMatcher tabMatcher() { /** * Matches the String trim() whitespace characters. * - * @return The trim matcher + * @return The trim matcher. */ public StringMatcher trimMatcher() { return TRIM_MATCHER; From 5d574755cb932dc8edf5a035f0de5c64cb8c8303 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 08:59:09 -0500 Subject: [PATCH 187/265] Javadoc --- .../commons/text/numbers/DoubleFormat.java | 100 +++---- .../commons/text/numbers/ParsedDecimal.java | 245 +++++++++--------- 2 files changed, 179 insertions(+), 166 deletions(-) diff --git a/src/main/java/org/apache/commons/text/numbers/DoubleFormat.java b/src/main/java/org/apache/commons/text/numbers/DoubleFormat.java index 1ad97d5fd3..214f380f52 100644 --- a/src/main/java/org/apache/commons/text/numbers/DoubleFormat.java +++ b/src/main/java/org/apache/commons/text/numbers/DoubleFormat.java @@ -251,7 +251,7 @@ public String apply(final double d) { /** * Returns a formatted string representation of the given finite value. * - * @param d double value + * @param d double value. */ private String applyFinite(final double d) { final ParsedDecimal n = ParsedDecimal.from(d); @@ -268,7 +268,7 @@ private String applyFinite(final double d) { /** * Returns a formatted representation of the given rounded decimal value to {@code dst}. * - * @param val value to format + * @param val value to format. * @return a formatted representation of the given rounded decimal value to {@code dst}. */ protected abstract String applyFiniteInternal(ParsedDecimal val); @@ -411,7 +411,7 @@ private static String getDigitString(final DecimalFormatSymbols symbols) { /** * Builds a new instance that delegates double function construction to the given factory object. * - * @param factory factory function + * @param factory factory function. */ private Builder(final Function> factory) { this.factory = factory; @@ -423,8 +423,8 @@ private Builder(final Function> factory) { * returned, regardless of the sign of the input number. The default value is {@code true}. * * @param signedZero if {@code true}, the zero string may be returned with a preceding minus sign; if {@code false}, the zero string will only be - * returned in its positive form - * @return {@code this} instance + * returned in its positive form. + * @return {@code this} instance. */ public Builder allowSignedZero(final boolean signedZero) { this.signedZero = signedZero; @@ -436,8 +436,8 @@ public Builder allowSignedZero(final boolean signedZero) { * only applies to formats that use scientific notation, namely {@link DoubleFormat#SCIENTIFIC SCIENTIFIC}, {@link DoubleFormat#ENGINEERING * ENGINEERING}, and {@link DoubleFormat#MIXED MIXED}. The default value is {@code false}. * - * @param alwaysIncludeExponent if {@code true}, exponents will always be included in formatted output even if the exponent value is zero - * @return {@code this} instance + * @param alwaysIncludeExponent if {@code true}, exponents will always be included in formatted output even if the exponent value is zero. + * @return {@code this} instance. */ public Builder alwaysIncludeExponent(final boolean alwaysIncludeExponent) { this.alwaysIncludeExponent = alwaysIncludeExponent; @@ -459,8 +459,8 @@ public DoubleFunction build() { * Sets the decimal separator character, i.e., the character placed between the whole number and fractional portions of the formatted strings. The * default value is {@code '.'}. * - * @param decimalSeparator decimal separator character - * @return {@code this} instance + * @param decimalSeparator decimal separator character. + * @return {@code this} instance. */ public Builder decimalSeparator(final char decimalSeparator) { this.decimalSeparator = decimalSeparator; @@ -470,10 +470,10 @@ public Builder decimalSeparator(final char decimalSeparator) { /** * Sets the string containing the digit characters 0-9, in that order. The default value is the string {@code "0123456789"}. * - * @param digits string containing the digit characters 0-9 - * @return {@code this} instance - * @throws NullPointerException if the argument is {@code null} - * @throws IllegalArgumentException if the argument does not have a length of exactly 10 + * @param digits string containing the digit characters 0-9. + * @return {@code this} instance. + * @throws NullPointerException if the argument is {@code null}. + * @throws IllegalArgumentException if the argument does not have a length of exactly 10. */ public Builder digits(final String digits) { Objects.requireNonNull(digits, "digits"); @@ -489,9 +489,9 @@ public Builder digits(final String digits) { * Sets the exponent separator character, i.e., the string placed between the mantissa and the exponent. The default value is {@code "E"}, as in * {@code "1.2E6"}. * - * @param exponentSeparator exponent separator string - * @return {@code this} instance - * @throws NullPointerException if the argument is {@code null} + * @param exponentSeparator exponent separator string. + * @return {@code this} instance. + * @throws NullPointerException if the argument is {@code null}. */ public Builder exponentSeparator(final String exponentSeparator) { this.exponentSeparator = Objects.requireNonNull(exponentSeparator, "exponentSeparator"); @@ -512,9 +512,9 @@ public Builder exponentSeparator(final String exponentSeparator) { * The digit character string is constructed by starting at the configured {@link DecimalFormatSymbols#getZeroDigit() zero digit} and adding the next 9 * consecutive characters. * - * @param symbols format symbols - * @return {@code this} instance - * @throws NullPointerException if the argument is {@code null} + * @param symbols format symbols. + * @return {@code this} instance. + * @throws NullPointerException if the argument is {@code null}. */ public Builder formatSymbols(final DecimalFormatSymbols symbols) { Objects.requireNonNull(symbols, "symbols"); @@ -526,7 +526,7 @@ public Builder formatSymbols(final DecimalFormatSymbols symbols) { /** * Builds a new double format function. * - * @return format function + * @return a new double format function. */ @Override public DoubleFunction get() { @@ -536,8 +536,8 @@ public DoubleFunction get() { /** * Sets the character used to separate groups of thousands. Default value is {@code ','}. * - * @param groupingSeparator character used to separate groups of thousands - * @return {@code this} instance + * @param groupingSeparator character used to separate groups of thousands. + * @return {@code this} instance. * @see #groupThousands(boolean) */ public Builder groupingSeparator(final char groupingSeparator) { @@ -550,8 +550,8 @@ public Builder groupingSeparator(final char groupingSeparator) { * the number {@code 1000} could be formatted as {@code "1,000"}. This property only applies to the {@link DoubleFormat#PLAIN PLAIN} format. Default * value is {@code false}. * - * @param groupThousands if {@code true}, thousands will be grouped - * @return {@code this} instance + * @param groupThousands if {@code true}, thousands will be grouped. + * @return {@code this} instance. * @see #groupingSeparator(char) */ public Builder groupThousands(final boolean groupThousands) { @@ -565,8 +565,8 @@ public Builder groupThousands(final boolean groupThousands) { * is {@code true}. * * @param fractionPlaceholder if {@code true}, a zero character is placed in the fraction position when no fractional value is present; if - * {@code false}, fractional digits are only included when needed - * @return {@code this} instance + * {@code false}, fractional digits are only included when needed. + * @return {@code this} instance. */ public Builder includeFractionPlaceholder(final boolean fractionPlaceholder) { this.fractionPlaceholder = fractionPlaceholder; @@ -576,9 +576,9 @@ public Builder includeFractionPlaceholder(final boolean fractionPlaceholder) { /** * Sets the string used to represent infinity. For negative infinity, this string is prefixed with the {@link #minusSign(char) minus sign}. * - * @param infinity string used to represent infinity - * @return {@code this} instance - * @throws NullPointerException if the argument is {@code null} + * @param infinity string used to represent infinity. + * @return {@code this} instance. + * @throws NullPointerException if the argument is {@code null}. */ public Builder infinity(final String infinity) { this.infinity = Objects.requireNonNull(infinity, "infinity"); @@ -589,8 +589,8 @@ public Builder infinity(final String infinity) { * Sets the maximum number of significant decimal digits used in format results. A value of {@code 0} indicates no limit. The default value is * {@code 0}. * - * @param maxPrecision maximum precision - * @return {@code this} instance + * @param maxPrecision maximum precision. + * @return {@code this} instance. */ public Builder maxPrecision(final int maxPrecision) { this.maxPrecision = maxPrecision; @@ -603,8 +603,8 @@ public Builder maxPrecision(final int maxPrecision) { * {@code minDecimalExponent} is set to {@code -2} and the number {@code 3.14159} is formatted, the plain format result will be {@code "3.14"}. If * {@code 0.001} is formatted, then the result is the zero string. * - * @param minDecimalExponent minimum decimal exponent - * @return {@code this} instance + * @param minDecimalExponent minimum decimal exponent. + * @return {@code this} instance. */ public Builder minDecimalExponent(final int minDecimalExponent) { this.minDecimalExponent = minDecimalExponent; @@ -614,8 +614,8 @@ public Builder minDecimalExponent(final int minDecimalExponent) { /** * Sets the character used as the minus sign. * - * @param minusSign character to use as the minus sign - * @return {@code this} instance + * @param minusSign character to use as the minus sign. + * @return {@code this} instance. */ public Builder minusSign(final char minusSign) { this.minusSign = minusSign; @@ -625,9 +625,9 @@ public Builder minusSign(final char minusSign) { /** * Sets the string used to represent {@link Double#NaN}. * - * @param nan string used to represent {@link Double#NaN} - * @return {@code this} instance - * @throws NullPointerException if the argument is {@code null} + * @param nan string used to represent {@link Double#NaN}. + * @return {@code this} instance. + * @throws NullPointerException if the argument is {@code null}. */ public Builder nan(final String nan) { this.nan = Objects.requireNonNull(nan, "nan"); @@ -635,17 +635,19 @@ public Builder nan(final String nan) { } /** - * Sets the maximum decimal exponent for numbers formatted as plain decimal strings when using the {@link DoubleFormat#MIXED MIXED} format type. If the - * number being formatted has an absolute value less than 10plainFormatMaxDecimalExponent + 1 and greater than or equal to - * 10plainFormatMinDecimalExponent after any necessary rounding, then the formatted result will use the + * Sets the maximum decimal exponent for numbers formatted as plain decimal strings when using the {@link DoubleFormat#MIXED MIXED} format type. + *

    + * If the number being formatted has an absolute value less than 10plainFormatMaxDecimalExponent + 1 and greater than or equal + * to 10plainFormatMinDecimalExponent after any necessary rounding, then the formatted result will use the * {@link DoubleFormat#PLAIN PLAIN} format type. Otherwise, {@link DoubleFormat#SCIENTIFIC SCIENTIFIC} format will be used. For example, if this value * is set to {@code 2}, the number {@code 999} will be formatted as {@code "999.0"} while {@code 1000} will be formatted as {@code "1.0E3"}. - * + *

    *

    * The default value is {@code 6}. - * + *

    *

    * This value is ignored for formats other than {@link DoubleFormat#MIXED}. + *

    * * @param plainFormatMaxDecimalExponent maximum decimal exponent for values formatted as plain strings when using the {@link DoubleFormat#MIXED MIXED} * format type. @@ -658,17 +660,19 @@ public Builder plainFormatMaxDecimalExponent(final int plainFormatMaxDecimalExpo } /** - * Sets the minimum decimal exponent for numbers formatted as plain decimal strings when using the {@link DoubleFormat#MIXED MIXED} format type. If the - * number being formatted has an absolute value less than 10plainFormatMaxDecimalExponent + 1 and greater than or equal to - * 10plainFormatMinDecimalExponent after any necessary rounding, then the formatted result will use the + * Sets the minimum decimal exponent for numbers formatted as plain decimal strings when using the {@link DoubleFormat#MIXED MIXED} format type. + *

    + * If the number being formatted has an absolute value less than 10plainFormatMaxDecimalExponent + 1 and greater than or equal + * to 10plainFormatMinDecimalExponent after any necessary rounding, then the formatted result will use the * {@link DoubleFormat#PLAIN PLAIN} format type. Otherwise, {@link DoubleFormat#SCIENTIFIC SCIENTIFIC} format will be used. For example, if this value * is set to {@code -2}, the number {@code 0.01} will be formatted as {@code "0.01"} while {@code 0.0099} will be formatted as {@code "9.9E-3"}. - * + *

    *

    * The default value is {@code -3}. - * + *

    *

    * This value is ignored for formats other than {@link DoubleFormat#MIXED}. + *

    * * @param plainFormatMinDecimalExponent maximum decimal exponent for values formatted as plain strings when using the {@link DoubleFormat#MIXED MIXED} * format type. diff --git a/src/main/java/org/apache/commons/text/numbers/ParsedDecimal.java b/src/main/java/org/apache/commons/text/numbers/ParsedDecimal.java index 4bc4d1c681..d4541b0280 100644 --- a/src/main/java/org/apache/commons/text/numbers/ParsedDecimal.java +++ b/src/main/java/org/apache/commons/text/numbers/ParsedDecimal.java @@ -44,59 +44,64 @@ interface FormatOptions { /** * Gets the decimal separator character. + * * @return decimal separator character */ char getDecimalSeparator(); /** - * Gets an array containing the localized digit characters 0-9 in that order. - * This string must be non-null and have a length of 10. - * @return array containing the digit characters 0-9 + * Gets an array containing the localized digit characters 0-9 in that order. This string must be non-null and have a length of 10. + * + * @return array containing the digit characters 0-9. */ char[] getDigits(); /** * Gets the exponent separator as an array of characters. - * @return exponent separator as an array of characters + * + * @return exponent separator as an array of characters. */ char[] getExponentSeparatorChars(); /** * Gets the character used to separate thousands groupings. - * @return character used to separate thousands groupings + * + * @return character used to separate thousands groupings. */ char getGroupingSeparator(); /** * Gets the minus sign character. - * @return minus sign character + * + * @return minus sign character. */ char getMinusSign(); /** - * Return {@code true} if exponent values should always be included in - * formatted output, even if the value is zero. - * @return {@code true} if exponent values should always be included + * Return {@code true} if exponent values should always be included in formatted output, even if the value is zero. + * + * @return {@code true} if exponent values should always be included. */ boolean isAlwaysIncludeExponent(); /** * Return {@code true} if thousands should be grouped. - * @return {@code true} if thousand should be grouped + * + * @return {@code true} if thousand should be grouped. */ boolean isGroupThousands(); /** - * Return {@code true} if fraction placeholders (e.g., {@code ".0"} in {@code "1.0"}) - * should be included. - * @return {@code true} if fraction placeholders should be included + * Return {@code true} if fraction placeholders (e.g., {@code ".0"} in {@code "1.0"}) should be included. + * + * @return {@code true} if fraction placeholders should be included. */ boolean isIncludeFractionPlaceholder(); /** - * Return {@code true} if the string zero should be prefixed with the minus sign - * for negative zero values. - * @return {@code true} if the minus zero string should be allowed + * Return {@code true} if the string zero should be prefixed with the minus sign for negative zero values. + * + * @return {@code true} if the minus zero string should be allowed. */ boolean isSignedZero(); } @@ -128,8 +133,9 @@ interface FormatOptions { /** * Gets the numeric value of the given digit character. No validation of the * character type is performed. - * @param ch digit character - * @return numeric value of the digit character, ex: '1' = 1 + * + * @param ch digit character. + * @return numeric value of the digit character, ex: '1' = 1. */ private static int digitValue(final char ch) { return ch - ZERO_CHAR; @@ -137,9 +143,10 @@ private static int digitValue(final char ch) { /** * Constructs a new instance from the given double value. - * @param d double value - * @return a new instance containing the parsed components of the given double value - * @throws IllegalArgumentException if {@code d} is {@code NaN} or infinite + * + * @param d double value. + * @return a new instance containing the parsed components of the given double value. + * @throws IllegalArgumentException if {@code d} is {@code NaN} or infinite. */ public static ParsedDecimal from(final double d) { if (!Double.isFinite(d)) { @@ -206,9 +213,10 @@ public static ParsedDecimal from(final double d) { /** * Parses a double exponent value from {@code chars}, starting at the {@code start} * index and continuing through the end of the array. - * @param chars character array to parse a double exponent value from - * @param start start index - * @return parsed exponent value + * + * @param chars character array to parse a double exponent value from. + * @param start start index. + * @return parsed exponent value. */ private static int parseExponent(final char[] chars, final int start) { int i = start; @@ -245,10 +253,11 @@ private static int parseExponent(final char[] chars, final int start) { /** * Constructs a new instance from its parts. - * @param negative {@code true} if the value is negative - * @param digits array containing significant digits - * @param digitCount number of digits used from the {@code digits} array - * @param exponent exponent value + * + * @param negative {@code true} if the value is negative. + * @param digits array containing significant digits. + * @param digitCount number of digits used from the {@code digits} array. + * @param exponent exponent value. */ private ParsedDecimal(final boolean negative, final int[] digits, final int digitCount, final int exponent) { @@ -260,7 +269,8 @@ private ParsedDecimal(final boolean negative, final int[] digits, final int digi /** * Appends the given character to the output buffer. - * @param ch character to append + * + * @param ch character to append. */ private void append(final char ch) { outputChars[outputIdx++] = ch; @@ -268,7 +278,8 @@ private void append(final char ch) { /** * Appends the given character array directly to the output buffer. - * @param chars characters to append + * + * @param chars characters to append. */ private void append(final char[] chars) { for (final char c : chars) { @@ -278,10 +289,10 @@ private void append(final char[] chars) { /** * Appends the fractional component of the number to the current output buffer. - * @param zeroCount number of zeros to add after the decimal point and before the - * first significant digit - * @param startIdx significant digit start index - * @param opts format options + * + * @param zeroCount number of zeros to add after the decimal point and before the first significant digit. + * @param startIdx significant digit start index. + * @param opts format options. */ private void appendFraction(final int zeroCount, final int startIdx, final FormatOptions opts) { final char[] localizedDigits = opts.getDigits(); @@ -307,20 +318,20 @@ private void appendFraction(final int zeroCount, final int startIdx, final Forma /** * Appends the localized representation of the digit {@code n} to the output buffer. - * @param n digit to append - * @param digitChars character array containing localized versions of the digits {@code 0-9} - * in that order + * + * @param n digit to append. + * @param digitChars character array containing localized versions of the digits {@code 0-9} in that order. */ private void appendLocalizedDigit(final int n, final char[] digitChars) { append(digitChars[n]); } /** - * Appends the whole number portion of this value to the output buffer. No thousands - * separators are added. - * @param wholeCount total number of digits required to the left of the decimal point - * @param opts format options - * @return number of digits from {@code digits} appended to the output buffer + * Appends the whole number portion of this value to the output buffer. No thousands separators are added. + * + * @param wholeCount total number of digits required to the left of the decimal point. + * @param opts format options. + * @return number of digits from {@code digits} appended to the output buffer. * @see #appendWholeGrouped(int, FormatOptions) */ private int appendWhole(final int wholeCount, final FormatOptions opts) { @@ -350,11 +361,11 @@ private int appendWhole(final int wholeCount, final FormatOptions opts) { } /** - * Appends the whole number portion of this value to the output buffer, adding thousands - * separators as needed. + * Appends the whole number portion of this value to the output buffer, adding thousands separators as needed. + * * @param wholeCount total number of digits required to the right of the decimal point - * @param opts format options - * @return number of digits from {@code digits} appended to the output buffer + * @param opts format options. + * @return number of digits from {@code digits} appended to the output buffer. * @see #appendWhole(int, FormatOptions) */ private int appendWholeGrouped(final int wholeCount, final FormatOptions opts) { @@ -392,12 +403,12 @@ private int appendWholeGrouped(final int wholeCount, final FormatOptions opts) { } /** - * Gets the number of characters required for the digit portion of a string representation of - * this value. This excludes any exponent or thousands groupings characters. - * @param decimalPos decimal point position relative to the {@code digits} array - * @param opts format options - * @return number of characters required for the digit portion of a string representation of - * this value + * Gets the number of characters required for the digit portion of a string representation of this value. This excludes any exponent or thousands groupings + * characters. + * + * @param decimalPos decimal point position relative to the {@code digits} array. + * @param opts format options. + * @return number of characters required for the digit portion of a string representation of this value. */ private int getDigitStringSize(final int decimalPos, final FormatOptions opts) { int size = digitCount; @@ -425,21 +436,20 @@ private int getDigitStringSize(final int decimalPos, final FormatOptions opts) { } /** - * Gets the exponent value. This exponent produces a floating point value with the - * correct magnitude when applied to the internal unsigned integer. - * @return exponent value + * Gets the exponent value. This exponent produces a floating point value with the correct magnitude when applied to the internal unsigned integer. + * + * @return exponent value. */ public int getExponent() { return exponent; } /** - * Gets the number of characters required to create a plain format representation - * of this value. - * @param decimalPos decimal position relative to the {@code digits} array - * @param opts format options - * @return number of characters in the plain string representation of this value, - * created using the given parameters + * Gets the number of characters required to create a plain format representation of this value. + * + * @param decimalPos decimal position relative to the {@code digits} array. + * @param opts format options. + * @return number of characters in the plain string representation of this value, created using the given parameters. */ private int getPlainStringSize(final int decimalPos, final FormatOptions opts) { int size = getDigitStringSize(decimalPos, opts); @@ -453,30 +463,31 @@ private int getPlainStringSize(final int decimalPos, final FormatOptions opts) { } /** - * Gets the exponent that would be used when representing this number in scientific - * notation (i.e., with a single non-zero digit in front of the decimal point). - * @return the exponent that would be used when representing this number in scientific - * notation + * Gets the exponent that would be used when representing this number in scientific notation (i.e., with a single non-zero digit in front of the decimal + * point). + * + * @return the exponent that would be used when representing this number in scientific notation. */ public int getScientificExponent() { return digitCount + exponent - 1; } /** - * Tests {@code true} if this value is equal to zero. The sign field is ignored, - * meaning that this method will return {@code true} for both {@code +0} and {@code -0}. - * @return {@code true} if the value is equal to zero + * Tests {@code true} if this value is equal to zero. The sign field is ignored, meaning that this method will return {@code true} for both {@code +0} and + * {@code -0}. + * + * @return {@code true} if the value is equal to zero. */ boolean isZero() { return digits[0] == 0; } /** - * Ensures that this instance has at most the given number of significant digits - * (i.e. precision). If this instance already has a precision less than or equal - * to the argument, nothing is done. If the given precision requires a reduction in the number - * of digits, then the value is rounded using {@link java.math.RoundingMode#HALF_EVEN half-even rounding}. - * @param precision maximum number of significant digits to include + * Ensures that this instance has at most the given number of significant digits (i.e. precision). If this instance already has a precision less + * than or equal to the argument, nothing is done. If the given precision requires a reduction in the number of digits, then the value is rounded using + * {@link java.math.RoundingMode#HALF_EVEN half-even rounding}. + * + * @param precision maximum number of significant digits to include. */ public void maxPrecision(final int precision) { if (precision > 0 && precision < digitCount) { @@ -490,6 +501,7 @@ public void maxPrecision(final int precision) { /** * Gets the output buffer as a string. + * * @return output buffer as a string */ private String outputString() { @@ -500,7 +512,8 @@ private String outputString() { /** * Prepares the output buffer for a string of the given size. - * @param size buffer size + * + * @param size buffer size. */ private void prepareOutput(final int size) { outputChars = new char[size]; @@ -508,21 +521,20 @@ private void prepareOutput(final int size) { } /** - * Returns {@code true} if a grouping separator should be added after the whole digit - * character at the given position. - * @param pos whole digit character position, with values starting at 1 and increasing - * from right to left. - * @return {@code true} if a grouping separator should be added + * Returns {@code true} if a grouping separator should be added after the whole digit character at the given position. + * + * @param pos whole digit character position, with values starting at 1 and increasing from right to left. + * @return {@code true} if a grouping separator should be added. */ private boolean requiresGroupingSeparatorAfterPosition(final int pos) { return pos > 1 && pos % THOUSANDS_GROUP_SIZE == 1; } /** - * Rounds the instance to the given decimal exponent position using - * {@link java.math.RoundingMode#HALF_EVEN half-even rounding}. For example, a value of {@code -2} - * will round the instance to the digit at the position 10-2 (i.e. to the closest multiple of 0.01). - * @param roundExponent exponent defining the decimal place to round to + * Rounds the instance to the given decimal exponent position using {@link java.math.RoundingMode#HALF_EVEN half-even rounding}. For example, a value of + * {@code -2} will round the instance to the digit at the position 10-2 (i.e. to the closest multiple of 0.01). + * + * @param roundExponent exponent defining the decimal place to round to. */ public void round(final int roundExponent) { if (roundExponent > exponent) { @@ -543,8 +555,8 @@ public void round(final int roundExponent) { /** * Rounds the value up to the given number of digits. - * @param count target number of digits; must be greater than zero and - * less than the current number of digits + * + * @param count target number of digits; must be greater than zero and less than the current number of digits. */ private void roundUp(final int count) { int removedDigits = digitCount - count; @@ -572,10 +584,10 @@ private void roundUp(final int count) { } /** - * Sets the value of this instance to a single digit with the given exponent. - * The sign of the value is retained. - * @param digit digit value - * @param newExponent new exponent value + * Sets the value of this instance to a single digit with the given exponent. The sign of the value is retained. + * + * @param digit digit value. + * @param newExponent new exponent value. */ private void setSingleDigitValue(final int digit, final int newExponent) { digits[0] = digit; @@ -584,33 +596,31 @@ private void setSingleDigitValue(final int digit, final int newExponent) { } /** - * Returns {@code true} if a formatted string with the given target exponent should include - * the exponent field. - * @param targetExponent exponent of the formatted result - * @param opts format options - * @return {@code true} if the formatted string should include the exponent field + * Returns {@code true} if a formatted string with the given target exponent should include the exponent field. + * + * @param targetExponent exponent of the formatted result. + * @param opts format options. + * @return {@code true} if the formatted string should include the exponent field. */ private boolean shouldIncludeExponent(final int targetExponent, final FormatOptions opts) { return targetExponent != 0 || opts.isAlwaysIncludeExponent(); } /** - * Returns {@code true} if formatted strings should include the minus sign, considering - * the value of this instance and the given format options. - * @param opts format options - * @return {@code true} if a minus sign should be included in the output + * Returns {@code true} if formatted strings should include the minus sign, considering the value of this instance and the given format options. + * + * @param opts format options. + * @return {@code true} if a minus sign should be included in the output. */ private boolean shouldIncludeMinus(final FormatOptions opts) { return negative && (opts.isSignedZero() || !isZero()); } /** - * Returns {@code true} if a rounding operation for the given number of digits should - * round up. - * @param count number of digits to round to; must be greater than zero and less - * than the current number of digits - * @return {@code true} if a rounding operation for the given number of digits should - * round up + * Returns {@code true} if a rounding operation for the given number of digits should round up. + * + * @param count number of digits to round to; must be greater than zero and less than the current number of digits. + * @return {@code true} if a rounding operation for the given number of digits should round up. */ private boolean shouldRoundUp(final int count) { // Round up in the following cases: @@ -639,8 +649,8 @@ private boolean shouldRoundUp(final int count) { * 1e11 = "100.0E9" *
    * - * @param opts format options - * @return value in engineering format + * @param opts format options. + * @return value in engineering format. */ public String toEngineeringString(final FormatOptions opts) { final int decimalPos = 1 + Math.floorMod(getScientificExponent(), ENG_EXPONENT_MOD); @@ -659,8 +669,8 @@ public String toEngineeringString(final FormatOptions opts) { * 1e11 = "100000000000.0" *
    * - * @param opts format options - * @return value in plain format + * @param opts format options. + * @return value in plain format. */ public String toPlainString(final FormatOptions opts) { final int decimalPos = digitCount + exponent; @@ -692,20 +702,19 @@ public String toPlainString(final FormatOptions opts) { * 1e11 = "1.0E11" *
    * - * @param opts format options - * @return value in scientific format + * @param opts format options. + * @return value in scientific format. */ public String toScientificString(final FormatOptions opts) { return toScientificString(1, opts); } /** - * Returns a string representation of the value in scientific notation using the - * given decimal point position. - * @param decimalPos decimal position relative to the {@code digits} array; this value - * is expected to be greater than 0 - * @param opts format options - * @return value in scientific format + * Returns a string representation of the value in scientific notation using the given decimal point position. + * + * @param decimalPos decimal position relative to the {@code digits} array; this value is expected to be greater than 0. + * @param opts format options. + * @return value in scientific format. */ private String toScientificString(final int decimalPos, final FormatOptions opts) { final int targetExponent = digitCount + exponent - decimalPos; @@ -759,8 +768,8 @@ private String toScientificString(final int decimalPos, final FormatOptions opts /** * Truncates the value to the given number of digits. - * @param count number of digits; must be greater than zero and less than - * the current number of digits + * + * @param count number of digits; must be greater than zero and less than the current number of digits. */ private void truncate(final int count) { // trim all trailing zero digits, making sure to leave From 63be79d2bd8f5df4344955cbad4ea2ccc07b75b0 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 09:03:08 -0500 Subject: [PATCH 188/265] Javadoc --- .../text/similarity/DamerauLevenshteinDistance.java | 8 ++++---- .../commons/text/similarity/IntersectionResult.java | 11 +++++------ .../commons/text/similarity/JaroWinklerDistance.java | 5 ++--- .../commons/text/similarity/SimilarityScoreFrom.java | 8 ++------ 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java index 4e0b9c65ee..93f4627cc1 100644 --- a/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java @@ -33,9 +33,9 @@ public class DamerauLevenshteinDistance implements EditDistance { /** * Utility function to ensure distance is valid according to threshold. * - * @param distance The distance value - * @param threshold The threshold value - * @return The distance value, or {@code -1} if distance is greater than threshold + * @param distance The distance value. + * @param threshold The threshold value. + * @return The distance value, or {@code -1} if distance is greater than threshold. */ private static int clampDistance(final int distance, final int threshold) { return distance > threshold ? -1 : distance; @@ -47,7 +47,7 @@ private static int clampDistance(final int distance, final int threshold) { * @param left the first SimilarityInput, must not be null. * @param right the second SimilarityInput, must not be null. * @param threshold the target threshold, must not be negative. - * @return result distance, or -1 if distance exceeds threshold + * @return result distance, or -1 if distance exceeds threshold. */ private static int limitedCompare(SimilarityInput left, SimilarityInput right, final int threshold) { if (left == null || right == null) { diff --git a/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java b/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java index 01f4f09a2c..b55adb3921 100644 --- a/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java +++ b/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java @@ -49,11 +49,10 @@ public class IntersectionResult { /** * Constructs the results for an intersection between two sets. * - * @param sizeA the size of set A ({@code |A|}). - * @param sizeB the size of set B ({@code |B|}). + * @param sizeA the size of set A ({@code |A|}). + * @param sizeB the size of set B ({@code |B|}). * @param intersection the size of the intersection of A and B ({@code |A ∩ B|}). - * @throws IllegalArgumentException if the sizes are negative or the intersection is greater - * than the minimum of the two set sizes. + * @throws IllegalArgumentException if the sizes are negative or the intersection is greater than the minimum of the two set sizes. */ public IntersectionResult(final int sizeA, final int sizeB, final int intersection) { if (sizeA < 0) { @@ -94,7 +93,7 @@ public int getIntersection() { /** * Gets the size of set A. * - * @return |A| + * @return {@code |A|} */ public int getSizeA() { return sizeA; @@ -103,7 +102,7 @@ public int getSizeA() { /** * Gets the size of set B. * - * @return |B| + * @return {@code |B|} */ public int getSizeB() { return sizeB; diff --git a/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java b/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java index cf11a864f7..8bd8d7b7a8 100644 --- a/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java @@ -33,11 +33,10 @@ public class JaroWinklerDistance implements EditDistance { /** * Computes the Jaro-Winkler string matches, half transpositions, prefix array. * - * @param first the first string to be matched. + * @param first the first string to be matched. * @param second the second string to be matched. * @return array containing: matches, half transpositions, and prefix - * @deprecated Deprecated as of 1.7. This method will be removed in 2.0, and moved to a Jaro Winkler similarity - * class. TODO see TEXT-104. + * @deprecated Deprecated as of 1.7. This method will be removed in 2.0, and moved to a Jaro Winkler similarity class. TODO see TEXT-104. */ @Deprecated protected static int[] matches(final CharSequence first, final CharSequence second) { diff --git a/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java b/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java index 6e7078a1e5..e39ec6c158 100644 --- a/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java +++ b/src/main/java/org/apache/commons/text/similarity/SimilarityScoreFrom.java @@ -66,20 +66,16 @@ public class SimilarityScoreFrom { * Constructs a new instance for a similarity score implementation and the "left" string. * * @param similarityScore This may not be null. - * @param left This may be null here, - * but the SimilarityScore#compare(CharSequence left, CharSequence right) - * implementation may not accept nulls. + * @param left This may be null here, but the SimilarityScore#compare(CharSequence left, CharSequence right) implementation may not accept nulls. */ public SimilarityScoreFrom(final SimilarityScore similarityScore, final CharSequence left) { Validate.isTrue(similarityScore != null, "The edit distance may not be null."); - this.similarityScore = similarityScore; this.left = left; } /** - * Compares "left" field against the "right" parameter - * using the "similarity score" implementation. + * Compares "left" field against the "right" parameter using the "similarity score" implementation. * * @param right the second CharSequence. * @return The similarity score between two CharSequences. From bbbc11154ae60a8c216591ae9708b5e672437abc Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 09:07:58 -0500 Subject: [PATCH 189/265] Javadoc --- .../text/translate/AggregateTranslator.java | 2 +- .../translate/CharSequenceTranslator.java | 25 +++++----- .../text/translate/CodePointTranslator.java | 8 ++-- .../commons/text/translate/EntityArrays.java | 4 +- .../text/translate/JavaUnicodeEscaper.java | 47 +++++++------------ .../text/translate/LookupTranslator.java | 3 +- .../text/translate/NumericEntityEscaper.java | 26 +++++----- .../translate/NumericEntityUnescaper.java | 23 ++++++--- .../text/translate/OctalUnescaper.java | 8 ++-- .../text/translate/SinglePassTranslator.java | 8 ++-- .../text/translate/UnicodeEscaper.java | 30 ++++++------ 11 files changed, 92 insertions(+), 92 deletions(-) diff --git a/src/main/java/org/apache/commons/text/translate/AggregateTranslator.java b/src/main/java/org/apache/commons/text/translate/AggregateTranslator.java index 3ec685bdff..576eccf5dd 100644 --- a/src/main/java/org/apache/commons/text/translate/AggregateTranslator.java +++ b/src/main/java/org/apache/commons/text/translate/AggregateTranslator.java @@ -39,7 +39,7 @@ public class AggregateTranslator extends CharSequenceTranslator { /** * Specify the translators to be used at creation time. * - * @param translators CharSequenceTranslator array to aggregate + * @param translators CharSequenceTranslator array to aggregate. */ public AggregateTranslator(final CharSequenceTranslator... translators) { if (translators != null) { diff --git a/src/main/java/org/apache/commons/text/translate/CharSequenceTranslator.java b/src/main/java/org/apache/commons/text/translate/CharSequenceTranslator.java index dd1caf9a91..459aca7394 100644 --- a/src/main/java/org/apache/commons/text/translate/CharSequenceTranslator.java +++ b/src/main/java/org/apache/commons/text/translate/CharSequenceTranslator.java @@ -58,8 +58,9 @@ public CharSequenceTranslator() { /** * Helper for non-Writer usage. - * @param input CharSequence to be translated - * @return String output of translation + * + * @param input CharSequence to be translated. + * @return String output of translation. */ public final String translate(final CharSequence input) { if (input == null) { @@ -81,11 +82,11 @@ public final String translate(final CharSequence input) { * and the only IOExceptions thrown must be from interacting with the Writer so that * the top level API may reliably ignore StringWriter IOExceptions. * - * @param input CharSequence that is being translated - * @param index int representing the current point of translation - * @param writer Writer to translate the text to - * @return int count of code points consumed - * @throws IOException if and only if the Writer produces an IOException + * @param input CharSequence that is being translated. + * @param index int representing the current point of translation. + * @param writer Writer to translate the text to. + * @return int count of code points consumed. + * @throws IOException if and only if the Writer produces an IOException. */ public abstract int translate(CharSequence input, int index, Writer writer) throws IOException; @@ -93,9 +94,9 @@ public final String translate(final CharSequence input) { * Translate an input onto a Writer. This is intentionally final as its algorithm is * tightly coupled with the abstract method of this class. * - * @param input CharSequence that is being translated - * @param writer Writer to translate the text to - * @throws IOException if and only if the Writer produces an IOException + * @param input CharSequence that is being translated. + * @param writer Writer to translate the text to. + * @throws IOException if and only if the Writer produces an IOException. */ public final void translate(final CharSequence input, final Writer writer) throws IOException { Validate.isTrue(writer != null, "The Writer must not be null"); @@ -133,8 +134,8 @@ public final void translate(final CharSequence input, final Writer writer) throw * Helper method to create a merger of this translator with another set of * translators. Useful in customizing the standard functionality. * - * @param translators CharSequenceTranslator array of translators to merge with this one - * @return CharSequenceTranslator merging this translator with the others + * @param translators CharSequenceTranslator array of translators to merge with this one. + * @return CharSequenceTranslator merging this translator with the others. */ public final CharSequenceTranslator with(final CharSequenceTranslator... translators) { final CharSequenceTranslator[] newArray = new CharSequenceTranslator[translators.length + 1]; diff --git a/src/main/java/org/apache/commons/text/translate/CodePointTranslator.java b/src/main/java/org/apache/commons/text/translate/CodePointTranslator.java index 50b660847e..266f197e80 100644 --- a/src/main/java/org/apache/commons/text/translate/CodePointTranslator.java +++ b/src/main/java/org/apache/commons/text/translate/CodePointTranslator.java @@ -44,10 +44,10 @@ public final int translate(final CharSequence input, final int index, final Writ /** * Translates the specified code point into another. * - * @param codePoint int character input to translate - * @param writer Writer to optionally push the translated output to - * @return boolean as to whether translation occurred or not - * @throws IOException if and only if the Writer produces an IOException + * @param codePoint int character input to translate. + * @param writer Writer to optionally push the translated output to. + * @return boolean as to whether translation occurred or not. + * @throws IOException if and only if the Writer produces an IOException. */ public abstract boolean translate(int codePoint, Writer writer) throws IOException; diff --git a/src/main/java/org/apache/commons/text/translate/EntityArrays.java b/src/main/java/org/apache/commons/text/translate/EntityArrays.java index 262fd52451..c8ab97a0a5 100644 --- a/src/main/java/org/apache/commons/text/translate/EntityArrays.java +++ b/src/main/java/org/apache/commons/text/translate/EntityArrays.java @@ -440,8 +440,8 @@ public class EntityArrays { /** * Inverts an escape Map into an unescape Map. * - * @param map Map<String, String> to be inverted - * @return Map<String, String> inverted array + * @param map Map<String, String> to be inverted. + * @return Map<String, String> inverted array. */ public static Map invert(final Map map) { return map.entrySet().stream().collect(Collectors.toMap(Entry::getValue, Entry::getKey)); diff --git a/src/main/java/org/apache/commons/text/translate/JavaUnicodeEscaper.java b/src/main/java/org/apache/commons/text/translate/JavaUnicodeEscaper.java index fc45350dd5..65076c5ca7 100644 --- a/src/main/java/org/apache/commons/text/translate/JavaUnicodeEscaper.java +++ b/src/main/java/org/apache/commons/text/translate/JavaUnicodeEscaper.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.text.translate; /** @@ -26,9 +27,8 @@ public class JavaUnicodeEscaper extends UnicodeEscaper { /** * Constructs a {@code JavaUnicodeEscaper} above the specified value (exclusive). * - * @param codePoint - * above which to escape - * @return The newly created {@code UnicodeEscaper} instance + * @param codePoint above which to escape. + * @return The newly created {@code UnicodeEscaper} instance. */ public static JavaUnicodeEscaper above(final int codePoint) { return outsideOf(0, codePoint); @@ -37,9 +37,8 @@ public static JavaUnicodeEscaper above(final int codePoint) { /** * Constructs a {@code JavaUnicodeEscaper} below the specified value (exclusive). * - * @param codePoint - * below which to escape - * @return The newly created {@code UnicodeEscaper} instance + * @param codePoint below which to escape. + * @return The newly created {@code UnicodeEscaper} instance. */ public static JavaUnicodeEscaper below(final int codePoint) { return outsideOf(codePoint, Integer.MAX_VALUE); @@ -48,11 +47,9 @@ public static JavaUnicodeEscaper below(final int codePoint) { /** * Constructs a {@code JavaUnicodeEscaper} between the specified values (inclusive). * - * @param codePointLow - * above which to escape - * @param codePointHigh - * below which to escape - * @return The newly created {@code UnicodeEscaper} instance + * @param codePointLow above which to escape. + * @param codePointHigh below which to escape. + * @return The newly created {@code UnicodeEscaper} instance. */ public static JavaUnicodeEscaper between(final int codePointLow, final int codePointHigh) { return new JavaUnicodeEscaper(codePointLow, codePointHigh, true); @@ -61,27 +58,21 @@ public static JavaUnicodeEscaper between(final int codePointLow, final int codeP /** * Constructs a {@code JavaUnicodeEscaper} outside of the specified values (exclusive). * - * @param codePointLow - * below which to escape - * @param codePointHigh - * above which to escape - * @return The newly created {@code UnicodeEscaper} instance + * @param codePointLow below which to escape. + * @param codePointHigh above which to escape. + * @return The newly created {@code UnicodeEscaper} instance. */ public static JavaUnicodeEscaper outsideOf(final int codePointLow, final int codePointHigh) { return new JavaUnicodeEscaper(codePointLow, codePointHigh, false); } /** - * Constructs a {@code JavaUnicodeEscaper} for the specified range. This is the underlying method for the - * other constructors/builders. The {@code below} and {@code above} boundaries are inclusive when - * {@code between} is {@code true} and exclusive when it is {@code false}. + * Constructs a {@code JavaUnicodeEscaper} for the specified range. This is the underlying method for the other constructors/builders. The {@code below} and + * {@code above} boundaries are inclusive when {@code between} is {@code true} and exclusive when it is {@code false}. * - * @param below - * int value representing the lowest code point boundary - * @param above - * int value representing the highest code point boundary - * @param between - * whether to escape between the boundaries or outside them + * @param below int value representing the lowest code point boundary. + * @param above int value representing the highest code point boundary. + * @param between whether to escape between the boundaries or outside them. */ public JavaUnicodeEscaper(final int below, final int above, final boolean between) { super(below, above, between); @@ -90,14 +81,12 @@ public JavaUnicodeEscaper(final int below, final int above, final boolean betwee /** * Converts the given code point to a hexadecimal string of the form {@code "\\uXXXX\\uXXXX"}. * - * @param codePoint - * a Unicode code point - * @return The hexadecimal string for the given code point + * @param codePoint a Unicode code point. + * @return The hexadecimal string for the given code point. */ @Override protected String toUtf16Escape(final int codePoint) { final char[] surrogatePair = Character.toChars(codePoint); return "\\u" + hex(surrogatePair[0]) + "\\u" + hex(surrogatePair[1]); } - } diff --git a/src/main/java/org/apache/commons/text/translate/LookupTranslator.java b/src/main/java/org/apache/commons/text/translate/LookupTranslator.java index e9d5d40645..931344c55e 100644 --- a/src/main/java/org/apache/commons/text/translate/LookupTranslator.java +++ b/src/main/java/org/apache/commons/text/translate/LookupTranslator.java @@ -42,9 +42,10 @@ public class LookupTranslator extends CharSequenceTranslator { /** * Constructs the lookup table to be used in translation. - * + *

    * Note that, as of Lang 3.1 (the origin of this code), the key to the lookup table is converted to a {@link String}. This is because we need the key to * support hashCode and equals(Object), allowing it to be the key for a HashMap. See LANG-882. + *

    * * @param lookupMap Map<CharSequence, CharSequence> table of translator mappings, may not be null. */ diff --git a/src/main/java/org/apache/commons/text/translate/NumericEntityEscaper.java b/src/main/java/org/apache/commons/text/translate/NumericEntityEscaper.java index 965fb529d7..768a90c904 100644 --- a/src/main/java/org/apache/commons/text/translate/NumericEntityEscaper.java +++ b/src/main/java/org/apache/commons/text/translate/NumericEntityEscaper.java @@ -31,8 +31,8 @@ public class NumericEntityEscaper extends CodePointTranslator { /** * Constructs a {@code NumericEntityEscaper} above the specified value (exclusive). * - * @param codePoint above which to escape - * @return The newly created {@code NumericEntityEscaper} instance + * @param codePoint above which to escape. + * @return The newly created {@code NumericEntityEscaper} instance. */ public static NumericEntityEscaper above(final int codePoint) { return outsideOf(0, codePoint); @@ -41,8 +41,8 @@ public static NumericEntityEscaper above(final int codePoint) { /** * Constructs a {@code NumericEntityEscaper} below the specified value (exclusive). * - * @param codePoint below which to escape - * @return The newly created {@code NumericEntityEscaper} instance + * @param codePoint below which to escape. + * @return The newly created {@code NumericEntityEscaper} instance. */ public static NumericEntityEscaper below(final int codePoint) { return outsideOf(codePoint, Integer.MAX_VALUE); @@ -51,9 +51,9 @@ public static NumericEntityEscaper below(final int codePoint) { /** * Constructs a {@code NumericEntityEscaper} between the specified values (inclusive). * - * @param codePointLow above which to escape - * @param codePointHigh below which to escape - * @return The newly created {@code NumericEntityEscaper} instance + * @param codePointLow above which to escape. + * @param codePointHigh below which to escape. + * @return The newly created {@code NumericEntityEscaper} instance. */ public static NumericEntityEscaper between(final int codePointLow, final int codePointHigh) { return new NumericEntityEscaper(codePointLow, codePointHigh, true); @@ -62,9 +62,9 @@ public static NumericEntityEscaper between(final int codePointLow, final int cod /** * Constructs a {@code NumericEntityEscaper} outside of the specified values (exclusive). * - * @param codePointLow below which to escape - * @param codePointHigh above which to escape - * @return The newly created {@code NumericEntityEscaper} instance + * @param codePointLow below which to escape. + * @param codePointHigh above which to escape. + * @return The newly created {@code NumericEntityEscaper} instance. */ public static NumericEntityEscaper outsideOf(final int codePointLow, final int codePointHigh) { return new NumericEntityEscaper(codePointLow, codePointHigh, false); @@ -89,9 +89,9 @@ public NumericEntityEscaper() { * and {@code above} boundaries are inclusive when {@code between} is * {@code true} and exclusive when it is {@code false}. * - * @param below int value representing the lowest code point boundary - * @param above int value representing the highest code point boundary - * @param between whether to escape between the boundaries or outside them + * @param below int value representing the lowest code point boundary. + * @param above int value representing the highest code point boundary. + * @param between whether to escape between the boundaries or outside them. */ private NumericEntityEscaper(final int below, final int above, final boolean between) { this.range = Range.of(below, above); diff --git a/src/main/java/org/apache/commons/text/translate/NumericEntityUnescaper.java b/src/main/java/org/apache/commons/text/translate/NumericEntityUnescaper.java index e184b0bfc0..fbae351b66 100644 --- a/src/main/java/org/apache/commons/text/translate/NumericEntityUnescaper.java +++ b/src/main/java/org/apache/commons/text/translate/NumericEntityUnescaper.java @@ -63,16 +63,25 @@ public enum OPTION { /** * Creates a UnicodeUnescaper. * - * The constructor takes a list of options, only one type of which is currently - * available (whether to allow, error or ignore the semicolon on the end of a + * The constructor takes a list of options, only one type of which is currently available (whether to allow, error or ignore the semicolon on the end of a * numeric entity to being missing). - * + *

    * For example, to support numeric entities without a ';': - * new NumericEntityUnescaper(NumericEntityUnescaper.OPTION.semiColonOptional) + *

    + * + *
    +     * new NumericEntityUnescaper(NumericEntityUnescaper.OPTION.semiColonOptional)
    +     * 
    + *

    * and to throw an IllegalArgumentException when they're missing: - * new NumericEntityUnescaper(NumericEntityUnescaper.OPTION.errorIfNoSemiColon) + *

    * + *
    +     * new NumericEntityUnescaper(NumericEntityUnescaper.OPTION.errorIfNoSemiColon)
    +     * 
    + *

    * Note that the default behavior is to ignore them. + *

    * * @param options to apply to this unescaper */ @@ -83,8 +92,8 @@ public NumericEntityUnescaper(final OPTION... options) { /** * Tests whether the passed in option is currently set. * - * @param option to check state of - * @return whether the option is set + * @param option to check state of. + * @return whether the option is set. */ public boolean isSet(final OPTION option) { return options.contains(option); diff --git a/src/main/java/org/apache/commons/text/translate/OctalUnescaper.java b/src/main/java/org/apache/commons/text/translate/OctalUnescaper.java index 9902784c1e..9d78726776 100644 --- a/src/main/java/org/apache/commons/text/translate/OctalUnescaper.java +++ b/src/main/java/org/apache/commons/text/translate/OctalUnescaper.java @@ -41,8 +41,8 @@ public OctalUnescaper() { /** * Tests if the given char is an octal digit. Octal digits are the character representations of the digits 0 to 7. * - * @param ch the char to check - * @return true if the given char is the character representation of one of the digits from 0 to 7 + * @param ch the char to check. + * @return true if the given char is the character representation of one of the digits from 0 to 7. */ private boolean isOctalDigit(final char ch) { return ch >= '0' && ch <= '7'; @@ -51,8 +51,8 @@ private boolean isOctalDigit(final char ch) { /** * Tests if the given char is the character representation of one of the digit from 0 to 3. * - * @param ch the char to check - * @return true if the given char is the character representation of one of the digits from 0 to 3 + * @param ch the char to check. + * @return true if the given char is the character representation of one of the digits from 0 to 3. */ private boolean isZeroToThree(final char ch) { return ch >= '0' && ch <= '3'; diff --git a/src/main/java/org/apache/commons/text/translate/SinglePassTranslator.java b/src/main/java/org/apache/commons/text/translate/SinglePassTranslator.java index 9f92f05ef7..90dd7f23bc 100644 --- a/src/main/java/org/apache/commons/text/translate/SinglePassTranslator.java +++ b/src/main/java/org/apache/commons/text/translate/SinglePassTranslator.java @@ -37,7 +37,7 @@ private String getClassName() { /** * {@inheritDoc} - * @throws IllegalArgumentException if {@code index != 0} + * @throws IllegalArgumentException if {@code index != 0}. */ @Override public int translate(final CharSequence input, final int index, final Writer writer) throws IOException { @@ -54,9 +54,9 @@ public int translate(final CharSequence input, final int index, final Writer wri /** * Translates whole set of code points passed in input. * - * @param input CharSequence that is being translated - * @param writer Writer to translate the text to - * @throws IOException if and only if the Writer produces an IOException + * @param input CharSequence that is being translated. + * @param writer Writer to translate the text to. + * @throws IOException if and only if the Writer produces an IOException. */ abstract void translateWhole(CharSequence input, Writer writer) throws IOException; } diff --git a/src/main/java/org/apache/commons/text/translate/UnicodeEscaper.java b/src/main/java/org/apache/commons/text/translate/UnicodeEscaper.java index b403f08676..a2e2c75157 100644 --- a/src/main/java/org/apache/commons/text/translate/UnicodeEscaper.java +++ b/src/main/java/org/apache/commons/text/translate/UnicodeEscaper.java @@ -29,8 +29,8 @@ public class UnicodeEscaper extends CodePointTranslator { /** * Constructs a {@code UnicodeEscaper} above the specified value (exclusive). * - * @param codePoint above which to escape - * @return The newly created {@code UnicodeEscaper} instance + * @param codePoint above which to escape. + * @return The newly created {@code UnicodeEscaper} instance. */ public static UnicodeEscaper above(final int codePoint) { return outsideOf(0, codePoint); @@ -38,8 +38,8 @@ public static UnicodeEscaper above(final int codePoint) { /** * Constructs a {@code UnicodeEscaper} below the specified value (exclusive). * - * @param codePoint below which to escape - * @return The newly created {@code UnicodeEscaper} instance + * @param codePoint below which to escape. + * @return The newly created {@code UnicodeEscaper} instance. */ public static UnicodeEscaper below(final int codePoint) { return outsideOf(codePoint, Integer.MAX_VALUE); @@ -47,9 +47,9 @@ public static UnicodeEscaper below(final int codePoint) { /** * Constructs a {@code UnicodeEscaper} between the specified values (inclusive). * - * @param codePointLow above which to escape - * @param codePointHigh below which to escape - * @return The newly created {@code UnicodeEscaper} instance + * @param codePointLow above which to escape. + * @param codePointHigh below which to escape. + * @return The newly created {@code UnicodeEscaper} instance. */ public static UnicodeEscaper between(final int codePointLow, final int codePointHigh) { return new UnicodeEscaper(codePointLow, codePointHigh, true); @@ -58,9 +58,9 @@ public static UnicodeEscaper between(final int codePointLow, final int codePoint /** * Constructs a {@code UnicodeEscaper} outside of the specified values (exclusive). * - * @param codePointLow below which to escape - * @param codePointHigh above which to escape - * @return The newly created {@code UnicodeEscaper} instance + * @param codePointLow below which to escape. + * @param codePointHigh above which to escape. + * @return The newly created {@code UnicodeEscaper} instance. */ public static UnicodeEscaper outsideOf(final int codePointLow, final int codePointHigh) { return new UnicodeEscaper(codePointLow, codePointHigh, false); @@ -88,9 +88,9 @@ public UnicodeEscaper() { * and {@code above} boundaries are inclusive when {@code between} is * {@code true} and exclusive when it is {@code false}. * - * @param below int value representing the lowest code point boundary - * @param above int value representing the highest code point boundary - * @param between whether to escape between the boundaries or outside them + * @param below int value representing the lowest code point boundary. + * @param above int value representing the highest code point boundary. + * @param between whether to escape between the boundaries or outside them. */ protected UnicodeEscaper(final int below, final int above, final boolean between) { this.below = below; @@ -102,8 +102,8 @@ protected UnicodeEscaper(final int below, final int above, final boolean between * Converts the given code point to a hexadecimal string of the form {@code "\\uXXXX"}. * * @param codePoint - * a Unicode code point - * @return The hexadecimal string for the given code point + * a Unicode code point. + * @return The hexadecimal string for the given code point. */ protected String toUtf16Escape(final int codePoint) { return "\\u" + hex(codePoint); From 677e57ff055ecce65bf9775ac3a5ddc4ba2a2983 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 09:08:06 -0500 Subject: [PATCH 190/265] Javadoc --- .../org/apache/commons/text/io/StringSubstitutorReader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/text/io/StringSubstitutorReader.java b/src/main/java/org/apache/commons/text/io/StringSubstitutorReader.java index 57088f0eeb..99f648fedf 100644 --- a/src/main/java/org/apache/commons/text/io/StringSubstitutorReader.java +++ b/src/main/java/org/apache/commons/text/io/StringSubstitutorReader.java @@ -145,7 +145,7 @@ private boolean isDraining() { * Reads a single character. * * @return a character as an {@code int} or {@code -1} for end-of-stream. - * @throws IOException If an I/O error occurs + * @throws IOException If an I/O error occurs. */ @Override public int read() throws IOException { @@ -168,7 +168,7 @@ public int read() throws IOException { * @param targetIndexIn Index in the target at which to start storing characters. * @param targetLengthIn Maximum number of characters to read. * @return The number of characters read, or -1 on end of stream. - * @throws IOException If an I/O error occurs + * @throws IOException If an I/O error occurs. */ @Override public int read(final char[] target, final int targetIndexIn, final int targetLengthIn) throws IOException { From bbe118f6df88957c13beb956705d40543630cf4f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 09:12:34 -0500 Subject: [PATCH 191/265] Javadoc --- .../commons/text/diff/CommandVisitor.java | 6 +- .../commons/text/diff/DeleteCommand.java | 4 +- .../apache/commons/text/diff/EditCommand.java | 10 +-- .../apache/commons/text/diff/EditScript.java | 12 +-- .../commons/text/diff/InsertCommand.java | 4 +- .../apache/commons/text/diff/KeepCommand.java | 10 +-- .../commons/text/diff/ReplacementsFinder.java | 17 ++--- .../text/diff/ReplacementsHandler.java | 24 +++--- .../commons/text/diff/StringsComparator.java | 76 ++++++++----------- 9 files changed, 71 insertions(+), 92 deletions(-) diff --git a/src/main/java/org/apache/commons/text/diff/CommandVisitor.java b/src/main/java/org/apache/commons/text/diff/CommandVisitor.java index 247e0818de..4dba623e09 100644 --- a/src/main/java/org/apache/commons/text/diff/CommandVisitor.java +++ b/src/main/java/org/apache/commons/text/diff/CommandVisitor.java @@ -125,21 +125,21 @@ public interface CommandVisitor { /** * Method called when a delete command is encountered. * - * @param object object to delete (this object comes from the first sequence) + * @param object object to delete (this object comes from the first sequence). */ void visitDeleteCommand(T object); /** * Method called when an insert command is encountered. * - * @param object object to insert (this object comes from the second sequence) + * @param object object to insert (this object comes from the second sequence). */ void visitInsertCommand(T object); /** * Method called when a keep command is encountered. * - * @param object object to keep (this object comes from the first sequence) + * @param object object to keep (this object comes from the first sequence). */ void visitKeepCommand(T object); diff --git a/src/main/java/org/apache/commons/text/diff/DeleteCommand.java b/src/main/java/org/apache/commons/text/diff/DeleteCommand.java index 66c1bb035f..e0f14a0432 100644 --- a/src/main/java/org/apache/commons/text/diff/DeleteCommand.java +++ b/src/main/java/org/apache/commons/text/diff/DeleteCommand.java @@ -36,7 +36,7 @@ public class DeleteCommand extends EditCommand { /** * Constructs a new instance of {@link DeleteCommand}. * - * @param object the object of the first sequence that should be deleted + * @param object the object of the first sequence that should be deleted. */ public DeleteCommand(final T object) { super(object); @@ -46,7 +46,7 @@ public DeleteCommand(final T object) { * Accepts a visitor. When a {@code DeleteCommand} accepts a visitor, it calls * its {@link CommandVisitor#visitDeleteCommand visitDeleteCommand} method. * - * @param visitor the visitor to be accepted + * @param visitor the visitor to be accepted. */ @Override public void accept(final CommandVisitor visitor) { diff --git a/src/main/java/org/apache/commons/text/diff/EditCommand.java b/src/main/java/org/apache/commons/text/diff/EditCommand.java index 2ba8d7fd68..ddcfbedec3 100644 --- a/src/main/java/org/apache/commons/text/diff/EditCommand.java +++ b/src/main/java/org/apache/commons/text/diff/EditCommand.java @@ -58,8 +58,7 @@ public abstract class EditCommand { /** * Constructs a new instance of EditCommand. * - * @param object reference to the object associated with this command, this - * refers to an element of one of the sequences being compared + * @param object reference to the object associated with this command, this refers to an element of one of the sequences being compared. */ protected EditCommand(final T object) { this.object = object; @@ -68,18 +67,17 @@ protected EditCommand(final T object) { /** * Accepts a visitor. *

    - * This method is invoked for each commands belonging to - * an {@link EditScript EditScript}, in order to implement the visitor design pattern + * This method is invoked for each commands belonging to an {@link EditScript EditScript}, in order to implement the visitor design pattern *

    * - * @param visitor the visitor to be accepted + * @param visitor the visitor to be accepted. */ public abstract void accept(CommandVisitor visitor); /** * Gets the object associated with this command. * - * @return The object on which the command is applied + * @return The object on which the command is applied. */ protected T getObject() { return object; diff --git a/src/main/java/org/apache/commons/text/diff/EditScript.java b/src/main/java/org/apache/commons/text/diff/EditScript.java index 420754ad90..1170c89e54 100644 --- a/src/main/java/org/apache/commons/text/diff/EditScript.java +++ b/src/main/java/org/apache/commons/text/diff/EditScript.java @@ -67,7 +67,7 @@ public EditScript() { /** * Appends a delete command to the script. * - * @param command command to add + * @param command command to add. */ public void append(final DeleteCommand command) { commands.add(command); @@ -77,7 +77,7 @@ public void append(final DeleteCommand command) { /** * Appends an insert command to the script. * - * @param command command to add + * @param command command to add. */ public void append(final InsertCommand command) { commands.add(command); @@ -87,7 +87,7 @@ public void append(final InsertCommand command) { /** * Appends a keep command to the script. * - * @param command command to add + * @param command command to add. */ public void append(final KeepCommand command) { commands.add(command); @@ -99,7 +99,7 @@ public void append(final KeepCommand command) { * longest common subsequence is the number of {@link KeepCommand keep * commands} in the script. * - * @return length of the Longest Common Subsequence + * @return length of the Longest Common Subsequence. */ public int getLCSLength() { return lcsLength; @@ -110,7 +110,7 @@ public int getLCSLength() { * modification is the number of {@link DeleteCommand delete} and * {@link InsertCommand insert} commands in the script. * - * @return number of effective modifications + * @return number of effective modifications. */ public int getModifications() { return modifications; @@ -123,7 +123,7 @@ public int getModifications() { * commands in order and call the appropriate method as each command is * encountered. * - * @param visitor the visitor that will visit all commands in turn + * @param visitor the visitor that will visit all commands in turn. */ public void visit(final CommandVisitor visitor) { commands.forEach(command -> command.accept(visitor)); diff --git a/src/main/java/org/apache/commons/text/diff/InsertCommand.java b/src/main/java/org/apache/commons/text/diff/InsertCommand.java index dad4b75ef7..d7545d6ebc 100644 --- a/src/main/java/org/apache/commons/text/diff/InsertCommand.java +++ b/src/main/java/org/apache/commons/text/diff/InsertCommand.java @@ -36,7 +36,7 @@ public class InsertCommand extends EditCommand { /** * Constructs a new instance of InsertCommand. * - * @param object the object of the second sequence that should be inserted + * @param object the object of the second sequence that should be inserted. */ public InsertCommand(final T object) { super(object); @@ -47,7 +47,7 @@ public InsertCommand(final T object) { * it calls its {@link CommandVisitor#visitInsertCommand visitInsertCommand} * method. * - * @param visitor the visitor to be accepted + * @param visitor the visitor to be accepted. */ @Override public void accept(final CommandVisitor visitor) { diff --git a/src/main/java/org/apache/commons/text/diff/KeepCommand.java b/src/main/java/org/apache/commons/text/diff/KeepCommand.java index 63f3546da2..cb5d1b2a34 100644 --- a/src/main/java/org/apache/commons/text/diff/KeepCommand.java +++ b/src/main/java/org/apache/commons/text/diff/KeepCommand.java @@ -36,19 +36,17 @@ public class KeepCommand extends EditCommand { /** * Constructs a new instance of KeepCommand. * - * @param object the object belonging to both sequences (the object is a - * reference to the instance in the first sequence which is known - * to be equal to an instance in the second sequence) + * @param object the object belonging to both sequences (the object is a reference to the instance in the first sequence which is known to be equal to an + * instance in the second sequence) */ public KeepCommand(final T object) { super(object); } /** - * Accepts a visitor. When a {@code KeepCommand} accepts a visitor, it - * calls its {@link CommandVisitor#visitKeepCommand visitKeepCommand} method. + * Accepts a visitor. When a {@code KeepCommand} accepts a visitor, it calls its {@link CommandVisitor#visitKeepCommand visitKeepCommand} method. * - * @param visitor the visitor to be accepted + * @param visitor the visitor to be accepted. */ @Override public void accept(final CommandVisitor visitor) { diff --git a/src/main/java/org/apache/commons/text/diff/ReplacementsFinder.java b/src/main/java/org/apache/commons/text/diff/ReplacementsFinder.java index 88994ac70e..9931e05057 100644 --- a/src/main/java/org/apache/commons/text/diff/ReplacementsFinder.java +++ b/src/main/java/org/apache/commons/text/diff/ReplacementsFinder.java @@ -72,19 +72,19 @@ public class ReplacementsFinder implements CommandVisitor { /** * Constructs a new instance of {@link ReplacementsFinder}. * - * @param handler handler to call when synchronized sequences are found + * @param handler handler to call when synchronized sequences are found */ public ReplacementsFinder(final ReplacementsHandler handler) { pendingInsertions = new ArrayList<>(); - pendingDeletions = new ArrayList<>(); - skipped = 0; - this.handler = handler; + pendingDeletions = new ArrayList<>(); + skipped = 0; + this.handler = handler; } /** * Add an object to the pending deletions set. * - * @param object object to delete + * @param object object to delete. */ @Override public void visitDeleteCommand(final T object) { @@ -94,7 +94,7 @@ public void visitDeleteCommand(final T object) { /** * Add an object to the pending insertions set. * - * @param object object to insert + * @param object object to insert. */ @Override public void visitInsertCommand(final T object) { @@ -104,11 +104,10 @@ public void visitInsertCommand(final T object) { /** * Handle a synchronization object. *

    - * When a synchronization object is identified, the pending insertions and - * pending deletions sets are provided to the user handler as subsequences. + * When a synchronization object is identified, the pending insertions and pending deletions sets are provided to the user handler as subsequences. *

    * - * @param object synchronization object detected + * @param object synchronization object detected. */ @Override public void visitKeepCommand(final T object) { diff --git a/src/main/java/org/apache/commons/text/diff/ReplacementsHandler.java b/src/main/java/org/apache/commons/text/diff/ReplacementsHandler.java index 1b749b1f3c..6bfa5f5d7d 100644 --- a/src/main/java/org/apache/commons/text/diff/ReplacementsHandler.java +++ b/src/main/java/org/apache/commons/text/diff/ReplacementsHandler.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.text.diff; import java.util.List; @@ -30,25 +31,18 @@ public interface ReplacementsHandler { /** * Handle two synchronized sequences. *

    - * This method is called by a {@link ReplacementsFinder ReplacementsFinder} - * instance when it has synchronized two sub-sequences of object arrays - * being compared, and at least one of the sequences is non-empty. Since the - * sequences are synchronized, the objects before the two sub-sequences are - * equals (if they exist). This property also holds for the objects after - * the two sub-sequences. + * This method is called by a {@link ReplacementsFinder ReplacementsFinder} instance when it has synchronized two sub-sequences of object arrays being + * compared, and at least one of the sequences is non-empty. Since the sequences are synchronized, the objects before the two sub-sequences are equals (if + * they exist). This property also holds for the objects after the two sub-sequences. *

    *

    - * The replacement is defined as replacing the {@code from} - * sub-sequence into the {@code to} sub-sequence. + * The replacement is defined as replacing the {@code from} sub-sequence into the {@code to} sub-sequence. *

    * - * @param skipped number of tokens skipped since the last call (i.e. number of - * tokens that were in both sequences), this number should be strictly positive - * except on the very first call where it can be zero (if the first object of - * the two sequences are different) - * @param from sub-sequence of objects coming from the first sequence - * @param to sub-sequence of objects coming from the second sequence + * @param skipped number of tokens skipped since the last call (i.e. number of tokens that were in both sequences), this number should be strictly positive + * except on the very first call where it can be zero (if the first object of the two sequences are different). + * @param from sub-sequence of objects coming from the first sequence. + * @param to sub-sequence of objects coming from the second sequence. */ void handleReplacement(int skipped, List from, List to); - } diff --git a/src/main/java/org/apache/commons/text/diff/StringsComparator.java b/src/main/java/org/apache/commons/text/diff/StringsComparator.java index 74ff0e62fb..9f9813a959 100644 --- a/src/main/java/org/apache/commons/text/diff/StringsComparator.java +++ b/src/main/java/org/apache/commons/text/diff/StringsComparator.java @@ -69,9 +69,9 @@ private static final class Snake { /** * Constructs a new instance of Snake with specified indices. * - * @param start start index of the snake - * @param end end index of the snake - * @param diag diagonal number + * @param start start index of the snake. + * @param end end index of the snake. + * @param diag diagonal number. */ Snake(final int start, final int end, final int diag) { this.start = start; @@ -82,7 +82,7 @@ private static final class Snake { /** * Gets the diagonal number of the snake. * - * @return diagonal number of the snake + * @return diagonal number of the snake. */ public int getDiag() { return diag; @@ -91,7 +91,7 @@ public int getDiag() { /** * Gets the end index of the snake. * - * @return end index of the snake + * @return end index of the snake. */ public int getEnd() { return end; @@ -100,7 +100,7 @@ public int getEnd() { /** * Gets the start index of the snake. * - * @return start index of the snake + * @return start index of the snake. */ public int getStart() { return start; @@ -127,15 +127,13 @@ public int getStart() { /** * Constructs a new instance of StringsComparator. *

    - * It is guaranteed that the comparisons will always be done as - * {@code o1.equals(o2)} where {@code o1} belongs to the first - * sequence and {@code o2} belongs to the second sequence. This can be - * important if subclassing is used for some elements in the first sequence - * and the {@code equals} method is specialized. + * It is guaranteed that the comparisons will always be done as {@code o1.equals(o2)} where {@code o1} belongs to the first sequence and {@code o2} + * belongs to the second sequence. This can be important if subclassing is used for some elements in the first sequence and the {@code equals} method is + * specialized. *

    * - * @param left first character sequence to be compared - * @param right second character sequence to be compared + * @param left first character sequence to be compared. + * @param right second character sequence to be compared. */ public StringsComparator(final String left, final String right) { this.left = left; @@ -149,11 +147,11 @@ public StringsComparator(final String left, final String right) { /** * Builds an edit script. * - * @param start1 the begin of the first sequence to be compared - * @param end1 the end of the first sequence to be compared - * @param start2 the begin of the second sequence to be compared - * @param end2 the end of the second sequence to be compared - * @param script the edited script + * @param start1 the begin of the first sequence to be compared. + * @param end1 the end of the first sequence to be compared. + * @param start2 the begin of the second sequence to be compared. + * @param end2 the end of the second sequence to be compared. + * @param script the edited script. */ private void buildScript(final int start1, final int end1, final int start2, final int end2, final EditScript script) { @@ -196,11 +194,11 @@ private void buildScript(final int start1, final int end1, final int start2, fin /** * Builds a snake. * - * @param start the value of the start of the snake - * @param diag the value of the diagonal of the snake - * @param end1 the value of the end of the first sequence to be compared - * @param end2 the value of the end of the second sequence to be compared - * @return The snake built + * @param start the value of the start of the snake. + * @param diag the value of the diagonal of the snake. + * @param end1 the value of the end of the first sequence to be compared. + * @param end2 the value of the end of the second sequence to be compared. + * @return The snake built. */ private Snake buildSnake(final int start, final int diag, final int end1, final int end2) { int end = start; @@ -213,21 +211,17 @@ private Snake buildSnake(final int start, final int diag, final int end1, final } /** - * Gets the middle snake corresponding to two subsequences of the - * main sequences. + * Gets the middle snake corresponding to two subsequences of the main sequences. *

    - * The snake is found using the MYERS Algorithm (this algorithms has - * also been implemented in the GNU diff program). This algorithm is - * explained in Eugene Myers article: - * - * An O(ND) Difference Algorithm and Its Variations. + * The snake is found using the MYERS Algorithm (this algorithms has also been implemented in the GNU diff program). This algorithm is explained in Eugene + * Myers article: An O(ND) Difference Algorithm and Its Variations. *

    * - * @param start1 the begin of the first sequence to be compared - * @param end1 the end of the first sequence to be compared - * @param start2 the begin of the second sequence to be compared - * @param end2 the end of the second sequence to be compared - * @return The middle snake + * @param start1 the begin of the first sequence to be compared. + * @param end1 the end of the first sequence to be compared. + * @param start2 the begin of the second sequence to be compared. + * @param end2 the end of the second sequence to be compared. + * @return The middle snake. */ private Snake getMiddleSnake(final int start1, final int end1, final int start2, final int end2) { // Myers Algorithm @@ -301,16 +295,12 @@ private Snake getMiddleSnake(final int start1, final int end1, final int start2, /** * Gets the {@link EditScript} object. *

    - * It is guaranteed that the objects embedded in the {@link InsertCommand - * insert commands} come from the second sequence and that the objects - * embedded in either the {@link DeleteCommand delete commands} or - * {@link KeepCommand keep commands} come from the first sequence. This can - * be important if subclassing is used for some elements in the first - * sequence and the {@code equals} method is specialized. + * It is guaranteed that the objects embedded in the {@link InsertCommand insert commands} come from the second sequence and that the objects embedded in + * either the {@link DeleteCommand delete commands} or {@link KeepCommand keep commands} come from the first sequence. This can be important if subclassing + * is used for some elements in the first sequence and the {@code equals} method is specialized. *

    * - * @return The edit script resulting from the comparison of the two - * sequences + * @return The edit script resulting from the comparison of the two sequences. */ public EditScript getScript() { final EditScript script = new EditScript<>(); From 42297416a0bc8bee97a62ecc1b299a92ba168c77 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 10:59:50 -0500 Subject: [PATCH 192/265] Javadoc --- .../commons/text/AlphabetConverter.java | 80 +- .../commons/text/CharacterPredicate.java | 10 +- .../apache/commons/text/CompositeFormat.java | 26 +- .../commons/text/ExtendedMessageFormat.java | 87 +- .../apache/commons/text/FormatFactory.java | 13 +- .../apache/commons/text/FormattableUtils.java | 98 +-- .../commons/text/RandomStringGenerator.java | 2 +- .../org/apache/commons/text/StrBuilder.java | 574 ++++++------ .../org/apache/commons/text/StrLookup.java | 16 +- .../org/apache/commons/text/StrMatcher.java | 98 +-- .../apache/commons/text/StrSubstitutor.java | 526 +++++------ .../org/apache/commons/text/StrTokenizer.java | 330 ++++--- .../commons/text/StringEscapeUtils.java | 356 ++++---- .../commons/text/StringSubstitutor.java | 335 ++++--- .../apache/commons/text/StringTokenizer.java | 374 +++----- .../commons/text/TextStringBuilder.java | 831 +++++++++--------- .../org/apache/commons/text/WordUtils.java | 99 +-- 17 files changed, 1838 insertions(+), 2017 deletions(-) diff --git a/src/main/java/org/apache/commons/text/AlphabetConverter.java b/src/main/java/org/apache/commons/text/AlphabetConverter.java index 46feb8ae3c..3864ac6a7f 100644 --- a/src/main/java/org/apache/commons/text/AlphabetConverter.java +++ b/src/main/java/org/apache/commons/text/AlphabetConverter.java @@ -82,8 +82,8 @@ public final class AlphabetConverter { /** * Creates new String that contains just the given code point. * - * @param i code point - * @return a new string with the new code point + * @param i code point. + * @return a new string with the new code point. * @see "http://www.oracle.com/us/technologies/java/supplementary-142654.html" */ private static String codePointToString(final int i) { @@ -96,8 +96,8 @@ private static String codePointToString(final int i) { /** * Converts characters to integers. * - * @param chars array of characters - * @return an equivalent array of integers + * @param chars array of characters. + * @return an equivalent array of integers. */ private static Integer[] convertCharsToIntegers(final Character[] chars) { if (ArrayUtils.isEmpty(chars)) { @@ -109,22 +109,19 @@ private static Integer[] convertCharsToIntegers(final Character[] chars) { } /** - * Creates an alphabet converter, for converting from the original alphabet, - * to the encoded alphabet, while leaving - * the characters in doNotEncode as they are (if possible). + * Creates an alphabet converter, for converting from the original alphabet, to the encoded alphabet, while leaving the characters in doNotEncode + * as they are (if possible). * - *

    Duplicate letters in either original or encoding will be ignored.

    + *

    + * Duplicate letters in either original or encoding will be ignored. + *

    * - * @param original an array of ints representing the original alphabet in - * code points - * @param encoding an array of ints representing the alphabet to be used for - * encoding, in code points - * @param doNotEncode an array of ints representing the chars to be encoded - * using the original alphabet - every char - * here must appear in both the previous params - * @return The AlphabetConverter - * @throws IllegalArgumentException if an AlphabetConverter cannot be - * constructed + * @param original an array of ints representing the original alphabet in code points. + * @param encoding an array of ints representing the alphabet to be used for encoding, in code points. + * @param doNotEncode an array of ints representing the chars to be encoded using the original alphabet - every char here must appear in both the previous + * params. + * @return The AlphabetConverter. + * @throws IllegalArgumentException if an AlphabetConverter cannot be constructed. */ public static AlphabetConverter createConverter( final Integer[] original, @@ -251,8 +248,8 @@ public static AlphabetConverter createConverterFromChars( /** * Creates a new converter from a map. * - * @param originalToEncoded a map returned from getOriginalToEncoded() - * @return The reconstructed AlphabetConverter + * @param originalToEncoded a map returned from getOriginalToEncoded(). + * @return The reconstructed AlphabetConverter. * @see AlphabetConverter#getOriginalToEncoded() */ public static AlphabetConverter createConverterFromMap(final Map originalToEncoded) { @@ -290,9 +287,9 @@ public static AlphabetConverter createConverterFromMap(final Map
    * - * @param standard the separator if builder is not empty, null means no separator - * @param defaultIfEmpty the separator if builder is empty, null means no separator + * @param standard the separator if builder is not empty, null means no separator. + * @param defaultIfEmpty the separator if builder is empty, null means no separator. * @return {@code this} instance. */ public StrBuilder appendSeparator(final String standard, final String defaultIfEmpty) { @@ -1302,8 +1302,8 @@ public StrBuilder appendSeparator(final String standard, final String defaultIfE * This method tries to avoid doing any extra copies of contents. *

    * - * @param appendable the appendable to append data to - * @throws IOException if an I/O error occurs + * @param appendable the appendable to append data to. + * @throws IOException if an I/O error occurs. * @see #readFrom(Readable) */ public void appendTo(final Appendable appendable) throws IOException { @@ -1324,8 +1324,8 @@ public void appendTo(final Appendable appendable) throws IOException { * Appends an iterable placing separators between each value, but not before the first or after the last. Appending a null iterable will have no effect. * Each object is appended using {@link #append(Object)}. * - * @param iterable the iterable to append - * @param separator the separator to use, null means no separator + * @param iterable the iterable to append. + * @param separator the separator to use, null means no separator. * @return {@code this} instance. */ public StrBuilder appendWithSeparators(final Iterable iterable, final String separator) { @@ -1339,8 +1339,8 @@ public StrBuilder appendWithSeparators(final Iterable iterable, final String * Appends an iterator placing separators between each value, but not before the first or after the last. Appending a null iterator will have no effect. * Each object is appended using {@link #append(Object)}. * - * @param iterator the iterator to append - * @param separator the separator to use, null means no separator + * @param iterator the iterator to append. + * @param separator the separator to use, null means no separator. * @return {@code this} instance. */ public StrBuilder appendWithSeparators(final Iterator iterator, final String separator) { @@ -1360,8 +1360,8 @@ public StrBuilder appendWithSeparators(final Iterator iterator, final String * Appends an array placing separators between each value, but not before the first or after the last. Appending a null array will have no effect. Each * object is appended using {@link #append(Object)}. * - * @param array the array to append - * @param separator the separator to use, null means no separator + * @param array the array to append. + * @param separator the separator to use, null means no separator. * @return {@code this} instance. */ public StrBuilder appendWithSeparators(final Object[] array, final String separator) { @@ -1393,7 +1393,7 @@ public StrBuilder appendWithSeparators(final Object[] array, final String separa * The returned reader supports marking, and ignores the flush method. *

    * - * @return a reader that reads from this builder + * @return a reader that reads from this builder. */ public Reader asReader() { return new StrBuilderReader(); @@ -1429,7 +1429,7 @@ public Reader asReader() { * Calling {@link StrTokenizer#reset(String)} or {@link StrTokenizer#reset(char[])} with a non-null value will break the link with the builder. *

    * - * @return a tokenizer that is linked to this builder + * @return a tokenizer that is linked to this builder. */ public StrTokenizer asTokenizer() { return new StrBuilderTokenizer(); @@ -1453,7 +1453,7 @@ public StrTokenizer asTokenizer() { * The returned writer ignores the close and flush methods. *

    * - * @return a writer that populates this builder + * @return a writer that populates this builder. */ public Writer asWriter() { return new StrBuilderWriter(); @@ -1462,7 +1462,7 @@ public Writer asWriter() { /** * Converts this instance to a String. * - * @return This instance as a String + * @return This instance as a String. * @see #toString() * @deprecated Use {@link #get()}. */ @@ -1484,11 +1484,11 @@ public int capacity() { /** * Gets the character at the specified index. * - * @see #setCharAt(int, char) - * @see #deleteCharAt(int) * @param index the index to retrieve, must be valid * @return The character at the index * @throws IndexOutOfBoundsException if the index is invalid + * @see #setCharAt(int, char) + * @see #deleteCharAt(int) */ @Override public char charAt(final int index) { @@ -1517,8 +1517,8 @@ public StrBuilder clear() { /** * Checks if the string builder contains the specified char. * - * @param ch the character to find - * @return true if the builder contains the character + * @param ch the character to find. + * @return true if the builder contains the character. */ public boolean contains(final char ch) { final char[] thisBuf = buffer; @@ -1533,8 +1533,8 @@ public boolean contains(final char ch) { /** * Tests if the string builder contains the specified string. * - * @param str the string to find - * @return true if the builder contains the string + * @param str the string to find. + * @return true if the builder contains the string. */ public boolean contains(final String str) { return indexOf(str, 0) >= 0; @@ -1546,8 +1546,8 @@ public boolean contains(final String str) { * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to search for the character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @return true if the matcher finds a match in the builder + * @param matcher the matcher to use, null returns -1. + * @return true if the matcher finds a match in the builder. */ public boolean contains(final StrMatcher matcher) { return indexOf(matcher, 0) >= 0; @@ -1556,10 +1556,10 @@ public boolean contains(final StrMatcher matcher) { /** * Deletes the characters between the two specified indices. * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder delete(final int startIndex, int endIndex) { endIndex = validateRange(startIndex, endIndex); @@ -1573,7 +1573,7 @@ public StrBuilder delete(final int startIndex, int endIndex) { /** * Deletes the character wherever it occurs in the builder. * - * @param ch the character to delete + * @param ch the character to delete. * @return {@code this} instance. */ public StrBuilder deleteAll(final char ch) { @@ -1596,7 +1596,7 @@ public StrBuilder deleteAll(final char ch) { /** * Deletes the string wherever it occurs in the builder. * - * @param str the string to delete, null causes no action + * @param str the string to delete, null causes no action. * @return {@code this} instance. */ public StrBuilder deleteAll(final String str) { @@ -1618,7 +1618,7 @@ public StrBuilder deleteAll(final String str) { * followed by a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action + * @param matcher the matcher to use to find the deletion, null causes no action. * @return {@code this} instance. */ public StrBuilder deleteAll(final StrMatcher matcher) { @@ -1628,11 +1628,11 @@ public StrBuilder deleteAll(final StrMatcher matcher) { /** * Deletes the character at the specified index. * + * @param index the index to delete. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. * @see #charAt(int) * @see #setCharAt(int, char) - * @param index the index to delete - * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid */ public StrBuilder deleteCharAt(final int index) { if (index < 0 || index >= size) { @@ -1645,7 +1645,7 @@ public StrBuilder deleteCharAt(final int index) { /** * Deletes the character wherever it occurs in the builder. * - * @param ch the character to delete + * @param ch the character to delete. * @return {@code this} instance. */ public StrBuilder deleteFirst(final char ch) { @@ -1661,7 +1661,7 @@ public StrBuilder deleteFirst(final char ch) { /** * Deletes the string wherever it occurs in the builder. * - * @param str the string to delete, null causes no action + * @param str the string to delete, null causes no action. * @return {@code this} instance. */ public StrBuilder deleteFirst(final String str) { @@ -1682,7 +1682,7 @@ public StrBuilder deleteFirst(final String str) { * number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action + * @param matcher the matcher to use to find the deletion, null causes no action. * @return {@code this} instance. */ public StrBuilder deleteFirst(final StrMatcher matcher) { @@ -1692,10 +1692,10 @@ public StrBuilder deleteFirst(final StrMatcher matcher) { /** * Internal method to delete a range without validation. * - * @param startIndex the start index, must be valid - * @param endIndex the end index (exclusive), must be valid - * @param len the length, must be valid - * @throws IndexOutOfBoundsException if any index is invalid + * @param startIndex the start index, must be valid. + * @param endIndex the end index (exclusive), must be valid. + * @param len the length, must be valid. + * @throws IndexOutOfBoundsException if any index is invalid. */ private void deleteImpl(final int startIndex, final int endIndex, final int len) { System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex); @@ -1708,8 +1708,8 @@ private void deleteImpl(final int startIndex, final int endIndex, final int len) * Note that this method handles null input quietly, unlike String. *

    * - * @param str the string to search for, null returns false - * @return true if the builder ends with the string + * @param str the string to search for, null returns false. + * @return true if the builder ends with the string. */ public boolean endsWith(final String str) { if (str == null) { @@ -1734,7 +1734,7 @@ public boolean endsWith(final String str) { /** * Tests the capacity and ensures that it is at least the size specified. * - * @param capacity the capacity to ensure + * @param capacity the capacity to ensure. * @return {@code this} instance. */ public StrBuilder ensureCapacity(final int capacity) { @@ -1749,8 +1749,8 @@ public StrBuilder ensureCapacity(final int capacity) { /** * Tests the contents of this builder against another to see if they contain the same character content. * - * @param obj the object to check, null returns false - * @return true if the builders contain the same characters in the same order + * @param obj the object to check, null returns false. + * @return true if the builders contain the same characters in the same order. */ @Override public boolean equals(final Object obj) { @@ -1760,8 +1760,8 @@ public boolean equals(final Object obj) { /** * Tests the contents of this builder against another to see if they contain the same character content. * - * @param other the object to check, null returns false - * @return true if the builders contain the same characters in the same order + * @param other the object to check, null returns false. + * @return true if the builders contain the same characters in the same order. */ public boolean equals(final StrBuilder other) { if (this == other) { @@ -1786,8 +1786,8 @@ public boolean equals(final StrBuilder other) { /** * Tests the contents of this builder against another to see if they contain the same character content ignoring case. * - * @param other the object to check, null returns false - * @return true if the builders contain the same characters in the same order + * @param other the object to check, null returns false. + * @return true if the builders contain the same characters in the same order. */ public boolean equalsIgnoreCase(final StrBuilder other) { if (this == other) { @@ -1811,7 +1811,7 @@ public boolean equalsIgnoreCase(final StrBuilder other) { /** * Converts this instance to a String. * - * @return This instance as a String + * @return This instance as a String. * @see #toString() * @since 1.12.0 */ @@ -1823,8 +1823,8 @@ public String get() { /** * Copies the character array into the specified array. * - * @param destination the destination array, null will cause an array to be created - * @return The input array, unless that was null or too small + * @param destination the destination array, null will cause an array to be created. + * @return The input array, unless that was null or too small. */ public char[] getChars(char[] destination) { final int len = length(); @@ -1838,12 +1838,12 @@ public char[] getChars(char[] destination) { /** * Copies the character array into the specified array. * - * @param startIndex first index to copy, inclusive, must be valid - * @param endIndex last index, exclusive, must be valid - * @param destination the destination array, must not be null or too small - * @param destinationIndex the index to start copying in destination - * @throws NullPointerException if the array is null - * @throws IndexOutOfBoundsException if any index is invalid + * @param startIndex first index to copy, inclusive, must be valid. + * @param endIndex last index, exclusive, must be valid. + * @param destination the destination array, must not be null or too small. + * @param destinationIndex the index to start copying in destination. + * @throws NullPointerException if the array is null. + * @throws IndexOutOfBoundsException if any index is invalid. */ public void getChars(final int startIndex, final int endIndex, final char[] destination, final int destinationIndex) { if (startIndex < 0) { @@ -1870,7 +1870,7 @@ public String getNewLineText() { /** * Gets the text to be appended when null is added. * - * @return The null text, null means no append + * @return The null text, null means no append. */ public String getNullText() { return nullText; @@ -1879,7 +1879,7 @@ public String getNullText() { /** * Gets a suitable hash code for this builder. * - * @return a hash code + * @return a hash code. */ @Override public int hashCode() { @@ -1894,8 +1894,8 @@ public int hashCode() { /** * Searches the string builder to find the first reference to the specified char. * - * @param ch the character to find - * @return The first index of the character, or -1 if not found + * @param ch the character to find. + * @return The first index of the character, or -1 if not found. */ public int indexOf(final char ch) { return indexOf(ch, 0); @@ -1904,9 +1904,9 @@ public int indexOf(final char ch) { /** * Searches the string builder to find the first reference to the specified char. * - * @param ch the character to find - * @param startIndex the index to start at, invalid index rounded to edge - * @return The first index of the character, or -1 if not found + * @param ch the character to find. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The first index of the character, or -1 if not found. */ public int indexOf(final char ch, int startIndex) { startIndex = Math.max(startIndex, 0); @@ -1928,8 +1928,8 @@ public int indexOf(final char ch, int startIndex) { * Note that a null input string will return -1, whereas the JDK throws an exception. *

    * - * @param str the string to find, null returns -1 - * @return The first index of the string, or -1 if not found + * @param str the string to find, null returns -1. + * @return The first index of the string, or -1 if not found. */ public int indexOf(final String str) { return indexOf(str, 0); @@ -1941,9 +1941,9 @@ public int indexOf(final String str) { * Note that a null input string will return -1, whereas the JDK throws an exception. *

    * - * @param str the string to find, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return The first index of the string, or -1 if not found + * @param str the string to find, null returns -1. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The first index of the string, or -1 if not found. */ public int indexOf(final String str, int startIndex) { startIndex = Math.max(0, startIndex); @@ -1980,8 +1980,8 @@ public int indexOf(final String str, int startIndex) { * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @return The first index matched, or -1 if not found + * @param matcher the matcher to use, null returns -1. + * @return The first index matched, or -1 if not found. */ public int indexOf(final StrMatcher matcher) { return indexOf(matcher, 0); @@ -1993,9 +1993,9 @@ public int indexOf(final StrMatcher matcher) { * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return The first index matched, or -1 if not found + * @param matcher the matcher to use, null returns -1. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The first index matched, or -1 if not found. */ public int indexOf(final StrMatcher matcher, int startIndex) { startIndex = Math.max(startIndex, 0); @@ -2015,10 +2015,10 @@ public int indexOf(final StrMatcher matcher, int startIndex) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert + * @param index the index to add at, must be valid. + * @param value the value to insert. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder insert(int index, final boolean value) { validateIndex(index); @@ -2046,10 +2046,10 @@ public StrBuilder insert(int index, final boolean value) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert + * @param index the index to add at, must be valid. + * @param value the value to insert. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder insert(final int index, final char value) { validateIndex(index); @@ -2063,10 +2063,10 @@ public StrBuilder insert(final int index, final char value) { /** * Inserts the character array into this builder. Inserting null will use the stored null text value. * - * @param index the index to add at, must be valid - * @param chars the char array to insert + * @param index the index to add at, must be valid. + * @param chars the char array to insert. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder insert(final int index, final char[] chars) { validateIndex(index); @@ -2086,12 +2086,12 @@ public StrBuilder insert(final int index, final char[] chars) { /** * Inserts part of the character array into this builder. Inserting null will use the stored null text value. * - * @param index the index to add at, must be valid - * @param chars the char array to insert - * @param offset the offset into the character array to start at, must be valid - * @param length the length of the character array part to copy, must be positive + * @param index the index to add at, must be valid. + * @param chars the char array to insert. + * @param offset the offset into the character array to start at, must be valid. + * @param length the length of the character array part to copy, must be positive. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if any index is invalid + * @throws IndexOutOfBoundsException if any index is invalid. */ public StrBuilder insert(final int index, final char[] chars, final int offset, final int length) { validateIndex(index); @@ -2116,10 +2116,10 @@ public StrBuilder insert(final int index, final char[] chars, final int offset, /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert + * @param index the index to add at, must be valid. + * @param value the value to insert. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder insert(final int index, final double value) { return insert(index, String.valueOf(value)); @@ -2128,10 +2128,10 @@ public StrBuilder insert(final int index, final double value) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert + * @param index the index to add at, must be valid. + * @param value the value to insert. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder insert(final int index, final float value) { return insert(index, String.valueOf(value)); @@ -2140,10 +2140,10 @@ public StrBuilder insert(final int index, final float value) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert + * @param index the index to add at, must be valid. + * @param value the value to insert. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder insert(final int index, final int value) { return insert(index, String.valueOf(value)); @@ -2152,10 +2152,10 @@ public StrBuilder insert(final int index, final int value) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert + * @param index the index to add at, must be valid. + * @param value the value to insert. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder insert(final int index, final long value) { return insert(index, String.valueOf(value)); @@ -2164,10 +2164,10 @@ public StrBuilder insert(final int index, final long value) { /** * Inserts the string representation of an object into this builder. Inserting null will use the stored null text value. * - * @param index the index to add at, must be valid - * @param obj the object to insert + * @param index the index to add at, must be valid. + * @param obj the object to insert. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder insert(final int index, final Object obj) { if (obj == null) { @@ -2179,10 +2179,10 @@ public StrBuilder insert(final int index, final Object obj) { /** * Inserts the string into this builder. Inserting null will use the stored null text value. * - * @param index the index to add at, must be valid - * @param str the string to insert + * @param index the index to add at, must be valid. + * @param str the string to insert. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder insert(final int index, String str) { validateIndex(index); @@ -2230,8 +2230,8 @@ public boolean isNotEmpty() { /** * Searches the string builder to find the last reference to the specified char. * - * @param ch the character to find - * @return The last index of the character, or -1 if not found + * @param ch the character to find. + * @return The last index of the character, or -1 if not found. */ public int lastIndexOf(final char ch) { return lastIndexOf(ch, size - 1); @@ -2240,9 +2240,9 @@ public int lastIndexOf(final char ch) { /** * Searches the string builder to find the last reference to the specified char. * - * @param ch the character to find - * @param startIndex the index to start at, invalid index rounded to edge - * @return The last index of the character, or -1 if not found + * @param ch the character to find. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The last index of the character, or -1 if not found. */ public int lastIndexOf(final char ch, int startIndex) { startIndex = startIndex >= size ? size - 1 : startIndex; @@ -2263,8 +2263,8 @@ public int lastIndexOf(final char ch, int startIndex) { * Note that a null input string will return -1, whereas the JDK throws an exception. *

    * - * @param str the string to find, null returns -1 - * @return The last index of the string, or -1 if not found + * @param str the string to find, null returns -1. + * @return The last index of the string, or -1 if not found. */ public int lastIndexOf(final String str) { return lastIndexOf(str, size - 1); @@ -2276,9 +2276,9 @@ public int lastIndexOf(final String str) { * Note that a null input string will return -1, whereas the JDK throws an exception. *

    * - * @param str the string to find, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return The last index of the string, or -1 if not found + * @param str the string to find, null returns -1. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The last index of the string, or -1 if not found. */ public int lastIndexOf(final String str, int startIndex) { startIndex = startIndex >= size ? size - 1 : startIndex; @@ -2313,8 +2313,8 @@ public int lastIndexOf(final String str, int startIndex) { * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @return The last index matched, or -1 if not found + * @param matcher the matcher to use, null returns -1. + * @return The last index matched, or -1 if not found. */ public int lastIndexOf(final StrMatcher matcher) { return lastIndexOf(matcher, size); @@ -2326,9 +2326,9 @@ public int lastIndexOf(final StrMatcher matcher) { * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return The last index matched, or -1 if not found + * @param matcher the matcher to use, null returns -1. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The last index matched, or -1 if not found. */ public int lastIndexOf(final StrMatcher matcher, int startIndex) { startIndex = startIndex >= size ? size - 1 : startIndex; @@ -2352,8 +2352,8 @@ public int lastIndexOf(final StrMatcher matcher, int startIndex) { * the returned string may be shorter than the length requested. *

    * - * @param length the number of characters to extract, negative returns empty string - * @return The new string + * @param length the number of characters to extract, negative returns empty string. + * @return The new string. */ public String leftString(final int length) { if (length <= 0) { @@ -2383,9 +2383,9 @@ public int length() { * available in the builder, as much as possible is returned. Thus the returned string may be shorter than the length requested. *

    * - * @param index the index to start at, negative means zero - * @param length the number of characters to extract, negative returns empty string - * @return The new string + * @param index the index to start at, negative means zero. + * @param length the number of characters to extract, negative returns empty string. + * @return The new string. */ public String midString(int index, final int length) { if (index < 0) { @@ -2417,8 +2417,8 @@ public StrBuilder minimizeCapacity() { /** * If possible, reads chars from the provided {@link Readable} directly into underlying character buffer without making extra copies. * - * @param readable object to read from - * @return The number of characters read + * @param readable object to read from. + * @return The number of characters read. * @throws IOException if an I/O error occurs. * @see #appendTo(Appendable) */ @@ -2455,11 +2455,11 @@ public int readFrom(final Readable readable) throws IOException { /** * Replaces a portion of the string builder with another string. The length of the inserted string does not have to match the removed length. * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @param replaceStr the string to replace with, null means delete range + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @param replaceStr the string to replace with, null means delete range. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid + * @throws IndexOutOfBoundsException if the index is invalid. */ public StrBuilder replace(final int startIndex, int endIndex, final String replaceStr) { endIndex = validateRange(startIndex, endIndex); @@ -2475,13 +2475,13 @@ public StrBuilder replace(final int startIndex, int endIndex, final String repla * a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @param replaceStr the string to replace the match with, null is a delete - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @param replaceCount the number of times to replace, -1 for replace all + * @param matcher the matcher to use to find the deletion, null causes no action. + * @param replaceStr the string to replace the match with, null is a delete. + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @param replaceCount the number of times to replace, -1 for replace all. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if start index is invalid + * @throws IndexOutOfBoundsException if start index is invalid. */ public StrBuilder replace(final StrMatcher matcher, final String replaceStr, final int startIndex, int endIndex, final int replaceCount) { endIndex = validateRange(startIndex, endIndex); @@ -2491,8 +2491,8 @@ public StrBuilder replace(final StrMatcher matcher, final String replaceStr, fin /** * Replaces the search character with the replace character throughout the builder. * - * @param search the search character - * @param replace the replace character + * @param search the search character. + * @param replace the replace character. * @return {@code this} instance. */ public StrBuilder replaceAll(final char search, final char replace) { @@ -2509,8 +2509,8 @@ public StrBuilder replaceAll(final char search, final char replace) { /** * Replaces the search string with the replace string throughout the builder. * - * @param searchStr the search string, null causes no action to occur - * @param replaceStr the replace string, null is equivalent to an empty string + * @param searchStr the search string, null causes no action to occur. + * @param replaceStr the replace string, null is equivalent to an empty string. * @return {@code this} instance. */ public StrBuilder replaceAll(final String searchStr, final String replaceStr) { @@ -2533,8 +2533,8 @@ public StrBuilder replaceAll(final String searchStr, final String replaceStr) { * followed by a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @param replaceStr the replace string, null is equivalent to an empty string + * @param matcher the matcher to use to find the deletion, null causes no action. + * @param replaceStr the replace string, null is equivalent to an empty string. * @return {@code this} instance. */ public StrBuilder replaceAll(final StrMatcher matcher, final String replaceStr) { @@ -2544,8 +2544,8 @@ public StrBuilder replaceAll(final StrMatcher matcher, final String replaceStr) /** * Replaces the first instance of the search character with the replace character in the builder. * - * @param search the search character - * @param replace the replace character + * @param search the search character. + * @param replace the replace character. * @return {@code this} instance. */ public StrBuilder replaceFirst(final char search, final char replace) { @@ -2563,8 +2563,8 @@ public StrBuilder replaceFirst(final char search, final char replace) { /** * Replaces the first instance of the search string with the replace string. * - * @param searchStr the search string, null causes no action to occur - * @param replaceStr the replace string, null is equivalent to an empty string + * @param searchStr the search string, null causes no action to occur. + * @param replaceStr the replace string, null is equivalent to an empty string. * @return {@code this} instance. */ public StrBuilder replaceFirst(final String searchStr, final String replaceStr) { @@ -2586,8 +2586,8 @@ public StrBuilder replaceFirst(final String searchStr, final String replaceStr) * number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @param replaceStr the replace string, null is equivalent to an empty string + * @param matcher the matcher to use to find the deletion, null causes no action. + * @param replaceStr the replace string, null is equivalent to an empty string. * @return {@code this} instance. */ public StrBuilder replaceFirst(final StrMatcher matcher, final String replaceStr) { @@ -2597,12 +2597,12 @@ public StrBuilder replaceFirst(final StrMatcher matcher, final String replaceStr /** * Internal method to delete a range without validation. * - * @param startIndex the start index, must be valid - * @param endIndex the end index (exclusive), must be valid - * @param removeLen the length to remove (endIndex - startIndex), must be valid - * @param insertStr the string to replace with, null means delete range - * @param insertLen the length of the insert string, must be valid - * @throws IndexOutOfBoundsException if any index is invalid + * @param startIndex the start index, must be valid. + * @param endIndex the end index (exclusive), must be valid. + * @param removeLen the length to remove (endIndex - startIndex), must be valid. + * @param insertStr the string to replace with, null means delete range. + * @param insertLen the length of the insert string, must be valid. + * @throws IndexOutOfBoundsException if any index is invalid. */ private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr, final int insertLen) { final int newSize = size - removeLen + insertLen; @@ -2623,13 +2623,13 @@ private void replaceImpl(final int startIndex, final int endIndex, final int rem * a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @param replaceStr the string to replace the match with, null is a delete - * @param from the start index, must be valid - * @param to the end index (exclusive), must be valid - * @param replaceCount the number of times to replace, -1 for replace all + * @param matcher the matcher to use to find the deletion, null causes no action. + * @param replaceStr the string to replace the match with, null is a delete. + * @param from the start index, must be valid. + * @param to the end index (exclusive), must be valid. + * @param replaceCount the number of times to replace, -1 for replace all. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if any index is invalid + * @throws IndexOutOfBoundsException if any index is invalid. */ private StrBuilder replaceImpl(final StrMatcher matcher, final String replaceStr, final int from, int to, int replaceCount) { if (matcher == null || size == 0) { @@ -2678,8 +2678,8 @@ public StrBuilder reverse() { * the returned string may be shorter than the length requested. *

    * - * @param length the number of characters to extract, negative returns empty string - * @return The new string + * @param length the number of characters to extract, negative returns empty string. + * @return The new string. */ public String rightString(final int length) { if (length <= 0) { @@ -2694,12 +2694,12 @@ public String rightString(final int length) { /** * Sets the character at the specified index. * + * @param index the index to set. + * @param ch the new character. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. * @see #charAt(int) * @see #deleteCharAt(int) - * @param index the index to set - * @param ch the new character - * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the index is invalid */ public StrBuilder setCharAt(final int index, final char ch) { if (index < 0 || index >= length()) { @@ -2712,9 +2712,9 @@ public StrBuilder setCharAt(final int index, final char ch) { /** * Updates the length of the builder by either dropping the last characters or adding filler of Unicode zero. * - * @param length the length to set to, must be zero or positive + * @param length the length to set to, must be zero or positive. * @return {@code this} instance. - * @throws IndexOutOfBoundsException if the length is negative + * @throws IndexOutOfBoundsException if the length is negative. */ public StrBuilder setLength(final int length) { if (length < 0) { @@ -2744,7 +2744,7 @@ public StrBuilder setNewLineText(final String newLine) { /** * Sets the text to be appended when null is added. * - * @param nullText the null text, null means no append + * @param nullText the null text, null means no append. * @return {@code this} instance. */ public StrBuilder setNullText(String nullText) { @@ -2761,7 +2761,7 @@ public StrBuilder setNullText(String nullText) { * This method is the same as {@link #length()} and is provided to match the API of Collections. *

    * - * @return The length + * @return The length. */ public int size() { return size; @@ -2773,8 +2773,8 @@ public int size() { * Note that this method handles null input quietly, unlike String. *

    * - * @param str the string to search for, null returns false - * @return true if the builder starts with the string + * @param str the string to search for, null returns false. + * @return true if the builder starts with the string. */ public boolean startsWith(final String str) { if (str == null) { @@ -2815,9 +2815,9 @@ public CharSequence subSequence(final int startIndex, final int endIndex) { /** * Extracts a portion of this string builder as a string. * - * @param start the start index, inclusive, must be valid - * @return The new string - * @throws IndexOutOfBoundsException if the index is invalid + * @param start the start index, inclusive, must be valid. + * @return The new string. + * @throws IndexOutOfBoundsException if the index is invalid. */ public String substring(final int start) { return substring(start, size); @@ -2829,10 +2829,10 @@ public String substring(final int start) { * Note: This method treats an endIndex greater than the length of the builder as equal to the length of the builder, and continues without error, unlike * StringBuffer or String. * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @return The new string - * @throws IndexOutOfBoundsException if the index is invalid + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @return The new string. + * @throws IndexOutOfBoundsException if the index is invalid. */ public String substring(final int startIndex, int endIndex) { endIndex = validateRange(startIndex, endIndex); @@ -2842,7 +2842,7 @@ public String substring(final int startIndex, int endIndex) { /** * Copies the builder's character array into a new character array. * - * @return a new array that represents the contents of the builder + * @return a new array that represents the contents of the builder. */ public char[] toCharArray() { return size == 0 ? ArrayUtils.EMPTY_CHAR_ARRAY : Arrays.copyOf(buffer, size); @@ -2851,10 +2851,10 @@ public char[] toCharArray() { /** * Copies part of the builder's character array into a new character array. * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @return a new array that holds part of the contents of the builder - * @throws IndexOutOfBoundsException if startIndex is invalid, or if endIndex is invalid (but endIndex greater than size is valid) + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @return a new array that holds part of the contents of the builder. + * @throws IndexOutOfBoundsException if startIndex is invalid, or if endIndex is invalid (but endIndex greater than size is valid). */ public char[] toCharArray(final int startIndex, int endIndex) { endIndex = validateRange(startIndex, endIndex); @@ -2873,7 +2873,7 @@ public char[] toCharArray(final int startIndex, int endIndex) { * Note that unlike StringBuffer, the string version returned is independent of the string builder. *

    * - * @return The builder as a String + * @return The builder as a String. */ @Override public String toString() { @@ -2883,7 +2883,7 @@ public String toString() { /** * Gets a StringBuffer version of the string builder, creating a new instance each time the method is called. * - * @return The builder as a StringBuffer + * @return The builder as a StringBuffer. */ public StringBuffer toStringBuffer() { return new StringBuffer(size).append(buffer, 0, size); @@ -2892,7 +2892,7 @@ public StringBuffer toStringBuffer() { /** * Gets a StringBuilder version of the string builder, creating a new instance each time the method is called. * - * @return The builder as a StringBuilder + * @return The builder as a StringBuilder. */ public StringBuilder toStringBuilder() { return new StringBuilder(size).append(buffer, 0, size); @@ -2928,8 +2928,8 @@ public StrBuilder trim() { /** * Validates parameters defining a single index in the builder. * - * @param index the index, must be valid - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index, must be valid. + * @throws IndexOutOfBoundsException if the index is invalid. */ protected void validateIndex(final int index) { if (index < 0 || index > size) { @@ -2940,10 +2940,10 @@ protected void validateIndex(final int index) { /** * Validates parameters defining a range of the builder. * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @return The new string - * @throws IndexOutOfBoundsException if the index is invalid + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @return The new string. + * @throws IndexOutOfBoundsException if the index is invalid. */ protected int validateRange(final int startIndex, int endIndex) { if (startIndex < 0) { diff --git a/src/main/java/org/apache/commons/text/StrLookup.java b/src/main/java/org/apache/commons/text/StrLookup.java index 113b313e4b..b21778138f 100644 --- a/src/main/java/org/apache/commons/text/StrLookup.java +++ b/src/main/java/org/apache/commons/text/StrLookup.java @@ -96,7 +96,7 @@ private static final class ResourceBundleLookup extends StrLookup { /** * Creates a new instance backed by a ResourceBundle. * - * @param resourceBundle the ResourceBundle of keys to values, may be null + * @param resourceBundle the ResourceBundle of keys to values, may be null. */ private ResourceBundleLookup(final ResourceBundle resourceBundle) { this.resourceBundle = resourceBundle; @@ -162,9 +162,9 @@ public String lookup(final String key) { * using toString(). *

    * - * @param the type of the values supported by the lookup - * @param map the map of keys to values, may be null - * @return a lookup using the map, not null + * @param the type of the values supported by the lookup. + * @param map the map of keys to values, may be null. + * @return a lookup using the map, not null. */ public static StrLookup mapLookup(final Map map) { return new MapStrLookup<>(map); @@ -173,7 +173,7 @@ public static StrLookup mapLookup(final Map map) { /** * Returns a lookup which always returns null. * - * @return a lookup that always returns null, not null + * @return a lookup that always returns null, not null. */ public static StrLookup noneLookup() { return NONE_LOOKUP; @@ -186,8 +186,8 @@ public static StrLookup noneLookup() { * to a string using toString(). *

    * - * @param resourceBundle the map of keys to values, may be null - * @return a lookup using the map, not null + * @param resourceBundle the map of keys to values, may be null. + * @return a lookup using the map, not null. * @see StringLookupFactory#resourceBundleStringLookup(String) */ public static StrLookup resourceBundleLookup(final ResourceBundle resourceBundle) { @@ -203,7 +203,7 @@ public static StrLookup resourceBundleLookup(final ResourceBundle resour * If a null key is used, this lookup will throw a NullPointerException. *

    * - * @return a lookup using system properties, not null + * @return a lookup using system properties, not null. */ public static StrLookup systemPropertiesLookup() { return SYSTEM_PROPERTIES_LOOKUP; diff --git a/src/main/java/org/apache/commons/text/StrMatcher.java b/src/main/java/org/apache/commons/text/StrMatcher.java index 98bc545cc6..c9c24bb58d 100644 --- a/src/main/java/org/apache/commons/text/StrMatcher.java +++ b/src/main/java/org/apache/commons/text/StrMatcher.java @@ -46,7 +46,7 @@ private static final class CharMatcher extends StrMatcher { /** * Constructor that creates a matcher that matches a single character. * - * @param ch the character to match + * @param ch the character to match. */ private CharMatcher(final char ch) { this.ch = ch; @@ -55,11 +55,11 @@ private CharMatcher(final char ch) { /** * Returns {@code 1} if there is a match, or {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return The number of matching characters, or zero if there is no match + * @param buffer the text content to match against, do not change. + * @param pos the starting position for the match, valid for buffer. + * @param bufferStart the first active index in the buffer, valid for buffer. + * @param bufferEnd the end index of the active buffer, valid for buffer. + * @return The number of matching characters, or zero if there is no match. */ @Override public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { @@ -88,11 +88,11 @@ private CharSetMatcher(final char[] chars) { /** * Returns {@code 1} if there is a match, or {@code 0} if there is no match. * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return The number of matching characters, or zero if there is no match + * @param buffer the text content to match against, do not change. + * @param pos the starting position for the match, valid for buffer. + * @param bufferStart the first active index in the buffer, valid for buffer. + * @param bufferEnd the end index of the active buffer, valid for buffer. + * @return The number of matching characters, or zero if there is no match. */ @Override public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { @@ -114,11 +114,11 @@ private NoMatcher() { /** * Always returns {@code 0}. * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return The number of matching characters, or zero if there is no match + * @param buffer the text content to match against, do not change. + * @param pos the starting position for the match, valid for buffer. + * @param bufferStart the first active index in the buffer, valid for buffer. + * @param bufferEnd the end index of the active buffer, valid for buffer. + * @return The number of matching characters, or zero if there is no match. */ @Override public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { @@ -146,11 +146,11 @@ private StringMatcher(final String str) { /** * Returns the number of matching characters, or zero if there is no match. * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return The number of matching characters, or zero if there is no match + * @param buffer the text content to match against, do not change. + * @param pos the starting position for the match, valid for buffer. + * @param bufferStart the first active index in the buffer, valid for buffer. + * @param bufferEnd the end index of the active buffer, valid for buffer. + * @return The number of matching characters, or zero if there is no match. */ @Override public int isMatch(final char[] buffer, int pos, final int bufferStart, final int bufferEnd) { @@ -187,11 +187,11 @@ private TrimMatcher() { /** * Returns whether or not the given character matches. * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return The number of matching characters, or zero if there is no match + * @param buffer the text content to match against, do not change. + * @param pos the starting position for the match, valid for buffer. + * @param bufferStart the first active index in the buffer, valid for buffer. + * @param bufferEnd the end index of the active buffer, valid for buffer. + * @return The number of matching characters, or zero if there is no match. */ @Override public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { @@ -248,8 +248,8 @@ public int isMatch(final char[] buffer, final int pos, final int bufferStart, fi /** * Creates a matcher from a character. * - * @param ch the character to match, must not be null - * @return a new Matcher for the given char + * @param ch the character to match, must not be null. + * @return a new Matcher for the given char. */ public static StrMatcher charMatcher(final char ch) { return new CharMatcher(ch); @@ -258,8 +258,8 @@ public static StrMatcher charMatcher(final char ch) { /** * Creates a matcher from a set of characters. * - * @param chars the characters to match, null or empty matches nothing - * @return a new matcher for the given char[] + * @param chars the characters to match, null or empty matches nothing. + * @return a new matcher for the given char[]. */ public static StrMatcher charSetMatcher(final char... chars) { if (ArrayUtils.isEmpty(chars)) { @@ -274,8 +274,8 @@ public static StrMatcher charSetMatcher(final char... chars) { /** * Creates a matcher from a string representing a set of characters. * - * @param chars the characters to match, null or empty matches nothing - * @return a new Matcher for the given characters + * @param chars the characters to match, null or empty matches nothing. + * @return a new Matcher for the given characters. */ public static StrMatcher charSetMatcher(final String chars) { if (chars == null || chars.isEmpty()) { @@ -290,7 +290,7 @@ public static StrMatcher charSetMatcher(final String chars) { /** * Returns a matcher which matches the comma character. * - * @return a matcher for a comma + * @return a matcher for a comma. */ public static StrMatcher commaMatcher() { return COMMA_MATCHER; @@ -299,7 +299,7 @@ public static StrMatcher commaMatcher() { /** * Returns a matcher which matches the double quote character. * - * @return a matcher for a double quote + * @return a matcher for a double quote. */ public static StrMatcher doubleQuoteMatcher() { return DOUBLE_QUOTE_MATCHER; @@ -308,7 +308,7 @@ public static StrMatcher doubleQuoteMatcher() { /** * Matches no characters. * - * @return a matcher that matches nothing + * @return a matcher that matches nothing. */ public static StrMatcher noneMatcher() { return NONE_MATCHER; @@ -317,7 +317,7 @@ public static StrMatcher noneMatcher() { /** * Returns a matcher which matches the single or double quote character. * - * @return a matcher for a single or double quote + * @return a matcher for a single or double quote. */ public static StrMatcher quoteMatcher() { return QUOTE_MATCHER; @@ -326,7 +326,7 @@ public static StrMatcher quoteMatcher() { /** * Returns a matcher which matches the single quote character. * - * @return a matcher for a single quote + * @return a matcher for a single quote. */ public static StrMatcher singleQuoteMatcher() { return SINGLE_QUOTE_MATCHER; @@ -335,7 +335,7 @@ public static StrMatcher singleQuoteMatcher() { /** * Returns a matcher which matches the space character. * - * @return a matcher for a space + * @return a matcher for a space. */ public static StrMatcher spaceMatcher() { return SPACE_MATCHER; @@ -345,7 +345,7 @@ public static StrMatcher spaceMatcher() { * Matches the same characters as StringTokenizer, * namely space, tab, newline and form feed. * - * @return The split matcher + * @return The split matcher. */ public static StrMatcher splitMatcher() { return SPLIT_MATCHER; @@ -367,7 +367,7 @@ public static StrMatcher stringMatcher(final String str) { /** * Returns a matcher which matches the tab character. * - * @return a matcher for a tab + * @return a matcher for a tab. */ public static StrMatcher tabMatcher() { return TAB_MATCHER; @@ -376,7 +376,7 @@ public static StrMatcher tabMatcher() { /** * Matches the String trim() whitespace characters. * - * @return The trim matcher + * @return The trim matcher. */ public static StrMatcher trimMatcher() { return TRIM_MATCHER; @@ -406,9 +406,9 @@ protected StrMatcher() { * The number indicates the number of characters that matched. *

    * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @return The number of matching characters, or zero if there is no match + * @param buffer the text content to match against, do not change. + * @param pos the starting position for the match, valid for buffer. + * @return The number of matching characters, or zero if there is no match. */ public int isMatch(final char[] buffer, final int pos) { return isMatch(buffer, pos, 0, buffer.length); @@ -437,11 +437,11 @@ public int isMatch(final char[] buffer, final int pos) { * The number indicates the number of characters that matched. *

    * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index (exclusive) of the active buffer, valid for buffer - * @return The number of matching characters, or zero if there is no match + * @param buffer the text content to match against, do not change. + * @param pos the starting position for the match, valid for buffer. + * @param bufferStart the first active index in the buffer, valid for buffer. + * @param bufferEnd the end index (exclusive) of the active buffer, valid for buffer. + * @return The number of matching characters, or zero if there is no match. */ public abstract int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd); diff --git a/src/main/java/org/apache/commons/text/StrSubstitutor.java b/src/main/java/org/apache/commons/text/StrSubstitutor.java index aa839710d4..8e8c23e2f8 100644 --- a/src/main/java/org/apache/commons/text/StrSubstitutor.java +++ b/src/main/java/org/apache/commons/text/StrSubstitutor.java @@ -150,10 +150,10 @@ public class StrSubstitutor { * Replaces all the occurrences of variables in the given source object with * their matching values from the map. * - * @param the type of the values in the map - * @param source the source text containing the variables to substitute, null returns null - * @param valueMap the map with the values, may be null - * @return The result of the replace operation + * @param the type of the values in the map. + * @param source the source text containing the variables to substitute, null returns null. + * @param valueMap the map with the values, may be null. + * @return The result of the replace operation. */ public static String replace(final Object source, final Map valueMap) { return new StrSubstitutor(valueMap).replace(source); @@ -164,13 +164,13 @@ public static String replace(final Object source, final Map value * their matching values from the map. This method allows to specify a * custom variable prefix and suffix * - * @param the type of the values in the map - * @param source the source text containing the variables to substitute, null returns null - * @param valueMap the map with the values, may be null - * @param prefix the prefix of variables, not null - * @param suffix the suffix of variables, not null - * @return The result of the replace operation - * @throws IllegalArgumentException if the prefix or suffix is null + * @param the type of the values in the map. + * @param source the source text containing the variables to substitute, null returns null. + * @param valueMap the map with the values, may be null. + * @param prefix the prefix of variables, not null. + * @param suffix the suffix of variables, not null. + * @return The result of the replace operation. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public static String replace(final Object source, final Map valueMap, @@ -183,9 +183,9 @@ public static String replace(final Object source, * Replaces all the occurrences of variables in the given source object with their matching * values from the properties. * - * @param source the source text containing the variables to substitute, null returns null - * @param valueProperties the properties with values, may be null - * @return The result of the replace operation + * @param source the source text containing the variables to substitute, null returns null. + * @param valueProperties the properties with values, may be null. + * @return The result of the replace operation. */ public static String replace(final Object source, final Properties valueProperties) { if (valueProperties == null) { @@ -198,8 +198,8 @@ public static String replace(final Object source, final Properties valueProperti * Replaces all the occurrences of variables in the given source object with * their matching values from the system properties. * - * @param source the source text containing the variables to substitute, null returns null - * @return The result of the replace operation + * @param source the source text containing the variables to substitute, null returns null. + * @return The result of the replace operation. */ public static String replaceSystemProperties(final Object source) { return new StrSubstitutor(StrLookup.systemPropertiesLookup()).replace(source); @@ -257,8 +257,8 @@ public StrSubstitutor() { * Constructs a new instance and initializes it. Uses defaults for variable * prefix and suffix and the escaping character. * - * @param the type of the values in the map - * @param valueMap the map with the variables' values, may be null + * @param the type of the values in the map. + * @param valueMap the map with the variables' values, may be null. */ public StrSubstitutor(final Map valueMap) { this(StrLookup.mapLookup(valueMap), DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_ESCAPE); @@ -267,11 +267,11 @@ public StrSubstitutor(final Map valueMap) { /** * Constructs a new instance and initializes it. Uses a default escaping character. * - * @param the type of the values in the map - * @param valueMap the map with the variables' values, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @throws IllegalArgumentException if the prefix or suffix is null + * @param the type of the values in the map. + * @param valueMap the map with the variables' values, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StrSubstitutor(final Map valueMap, final String prefix, final String suffix) { this(StrLookup.mapLookup(valueMap), prefix, suffix, DEFAULT_ESCAPE); @@ -280,12 +280,12 @@ public StrSubstitutor(final Map valueMap, final String prefix, fi /** * Constructs a new instance and initializes it. * - * @param the type of the values in the map - * @param valueMap the map with the variables' values, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @param escape the escape character - * @throws IllegalArgumentException if the prefix or suffix is null + * @param the type of the values in the map. + * @param valueMap the map with the variables' values, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @param escape the escape character. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StrSubstitutor(final Map valueMap, final String prefix, final String suffix, final char escape) { @@ -295,13 +295,13 @@ public StrSubstitutor(final Map valueMap, final String prefix, fi /** * Constructs a new instance and initializes it. * - * @param the type of the values in the map - * @param valueMap the map with the variables' values, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @param escape the escape character - * @param valueDelimiter the variable default value delimiter, may be null - * @throws IllegalArgumentException if the prefix or suffix is null + * @param the type of the values in the map. + * @param valueMap the map with the variables' values, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @param escape the escape character. + * @param valueDelimiter the variable default value delimiter, may be null. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StrSubstitutor(final Map valueMap, final String prefix, final String suffix, final char escape, final String valueDelimiter) { @@ -311,7 +311,7 @@ public StrSubstitutor(final Map valueMap, final String prefix, fi /** * Constructs a new instance and initializes it. * - * @param variableResolver the variable resolver, may be null + * @param variableResolver the variable resolver, may be null. */ public StrSubstitutor(final StrLookup variableResolver) { this(variableResolver, DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_ESCAPE); @@ -320,11 +320,11 @@ public StrSubstitutor(final StrLookup variableResolver) { /** * Constructs a new instance and initializes it. * - * @param variableResolver the variable resolver, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @param escape the escape character - * @throws IllegalArgumentException if the prefix or suffix is null + * @param variableResolver the variable resolver, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @param escape the escape character. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StrSubstitutor(final StrLookup variableResolver, final String prefix, final String suffix, final char escape) { @@ -338,12 +338,12 @@ public StrSubstitutor(final StrLookup variableResolver, final String prefix, /** * Constructs a new instance and initializes it. * - * @param variableResolver the variable resolver, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @param escape the escape character - * @param valueDelimiter the variable default value delimiter string, may be null - * @throws IllegalArgumentException if the prefix or suffix is null + * @param variableResolver the variable resolver, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @param escape the escape character. + * @param valueDelimiter the variable default value delimiter string, may be null. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StrSubstitutor(final StrLookup variableResolver, final String prefix, final String suffix, final char escape, final String valueDelimiter) { @@ -357,11 +357,11 @@ public StrSubstitutor(final StrLookup variableResolver, final String prefix, /** * Constructs a new instance and initializes it. * - * @param variableResolver the variable resolver, may be null - * @param prefixMatcher the prefix for variables, not null - * @param suffixMatcher the suffix for variables, not null - * @param escape the escape character - * @throws IllegalArgumentException if the prefix or suffix is null + * @param variableResolver the variable resolver, may be null. + * @param prefixMatcher the prefix for variables, not null. + * @param suffixMatcher the suffix for variables, not null. + * @param escape the escape character. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StrSubstitutor( final StrLookup variableResolver, final StrMatcher prefixMatcher, final StrMatcher suffixMatcher, @@ -372,12 +372,12 @@ public StrSubstitutor( /** * Constructs a new instance and initializes it. * - * @param variableResolver the variable resolver, may be null - * @param prefixMatcher the prefix for variables, not null - * @param suffixMatcher the suffix for variables, not null - * @param escape the escape character - * @param valueDelimiterMatcher the variable default value delimiter matcher, may be null - * @throws IllegalArgumentException if the prefix or suffix is null + * @param variableResolver the variable resolver, may be null. + * @param prefixMatcher the prefix for variables, not null. + * @param suffixMatcher the suffix for variables, not null. + * @param escape the escape character. + * @param valueDelimiterMatcher the variable default value delimiter matcher, may be null. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StrSubstitutor( final StrLookup variableResolver, final StrMatcher prefixMatcher, final StrMatcher suffixMatcher, @@ -392,8 +392,8 @@ public StrSubstitutor( /** * Checks if the specified variable is already in the stack (list) of variables. * - * @param varName the variable name to check - * @param priorVariables the list of prior variables + * @param varName the variable name to check. + * @param priorVariables the list of prior variables. */ private void checkCyclicSubstitution(final String varName, final List priorVariables) { if (!priorVariables.contains(varName)) { @@ -410,7 +410,7 @@ private void checkCyclicSubstitution(final String varName, final List pr /** * Returns the escape character. * - * @return The character used for escaping variable references + * @return The character used for escaping variable references. */ public char getEscapeChar() { return this.escapeChar; @@ -419,15 +419,14 @@ public char getEscapeChar() { /** * Gets the variable default value delimiter matcher currently in use. *

    - * The variable default value delimiter is the character or characters that delimit the - * variable name and the variable default value. This delimiter is expressed in terms of a matcher - * allowing advanced variable default value delimiter matches. + * The variable default value delimiter is the character or characters that delimit the variable name and the variable default value. This delimiter is + * expressed in terms of a matcher allowing advanced variable default value delimiter matches. *

    *

    * If it returns null, then the variable default value resolution is disabled. *

    * - * @return The variable default value delimiter matcher in use, may be null + * @return The variable default value delimiter matcher in use, may be null. */ public StrMatcher getValueDelimiterMatcher() { return valueDelimiterMatcher; @@ -436,12 +435,11 @@ public StrMatcher getValueDelimiterMatcher() { /** * Gets the variable prefix matcher currently in use. *

    - * The variable prefix is the character or characters that identify the - * start of a variable. This prefix is expressed in terms of a matcher - * allowing advanced prefix matches. + * The variable prefix is the character or characters that identify the start of a variable. This prefix is expressed in terms of a matcher allowing + * advanced prefix matches. *

    * - * @return The prefix matcher in use + * @return The prefix matcher in use. */ public StrMatcher getVariablePrefixMatcher() { return prefixMatcher; @@ -450,7 +448,7 @@ public StrMatcher getVariablePrefixMatcher() { /** * Gets the VariableResolver that is used to lookup variables. * - * @return The VariableResolver + * @return The VariableResolver. */ public StrLookup getVariableResolver() { return this.variableResolver; @@ -459,12 +457,11 @@ public StrLookup getVariableResolver() { /** * Gets the variable suffix matcher currently in use. *

    - * The variable suffix is the character or characters that identify the - * end of a variable. This suffix is expressed in terms of a matcher - * allowing advanced suffix matches. + * The variable suffix is the character or characters that identify the end of a variable. This suffix is expressed in terms of a matcher allowing advanced + * suffix matches. *

    * - * @return The suffix matcher in use + * @return The suffix matcher in use. */ public StrMatcher getVariableSuffixMatcher() { return suffixMatcher; @@ -482,12 +479,14 @@ public StrMatcher getVariableSuffixMatcher() { * StrSubstitutor sub = new StrSubstitutor(valuesMap); * String resolvedString = sub.replace(templateString); *
    + *

    * yielding: + *

    *
          *      Hi Douglas ${surname}
          * 
    * - * @return The substitution in variable values flag + * @return The substitution in variable values flag. * @since 1.2 */ public boolean isDisableSubstitutionInValues() { @@ -497,29 +496,27 @@ public boolean isDisableSubstitutionInValues() { /** * Returns a flag whether substitution is done in variable names. * - * @return The substitution in variable names flag + * @return The substitution in variable names flag. */ public boolean isEnableSubstitutionInVariables() { return enableSubstitutionInVariables; } /** - * Returns the flag controlling whether escapes are preserved during - * substitution. + * Returns the flag controlling whether escapes are preserved during substitution. * - * @return The preserve escape flag + * @return The preserve escape flag. */ public boolean isPreserveEscapes() { return preserveEscapes; } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source array as a template. - * The array is not altered by this method. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source array as a template. The array is not + * altered by this method. * - * @param source the character array to replace in, not altered, null returns null - * @return The result of the replace operation + * @param source the character array to replace in, not altered, null returns null. + * @return The result of the replace operation. */ public String replace(final char[] source) { if (source == null) { @@ -531,18 +528,16 @@ public String replace(final char[] source) { } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source array as a template. - * The array is not altered by this method. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source array as a template. The array is not + * altered by this method. *

    - * Only the specified portion of the array will be processed. - * The rest of the array is not processed, and is not returned. + * Only the specified portion of the array will be processed. The rest of the array is not processed, and is not returned. *

    * - * @param source the character array to replace in, not altered, null returns null - * @param offset the start offset within the array, must be valid - * @param length the length within the array to be processed, must be valid - * @return The result of the replace operation + * @param source the character array to replace in, not altered, null returns null. + * @param offset the start offset within the array, must be valid. + * @param length the length within the array to be processed, must be valid. + * @return The result of the replace operation. */ public String replace(final char[] source, final int offset, final int length) { if (source == null) { @@ -554,12 +549,11 @@ public String replace(final char[] source, final int offset, final int length) { } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source as a template. - * The source is not altered by this method. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source as a template. The source is not altered by + * this method. * - * @param source the buffer to use as a template, not changed, null returns null - * @return The result of the replace operation + * @param source the buffer to use as a template, not changed, null returns null. + * @return The result of the replace operation. */ public String replace(final CharSequence source) { if (source == null) { @@ -569,18 +563,16 @@ public String replace(final CharSequence source) { } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source as a template. - * The source is not altered by this method. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source as a template. The source is not altered by + * this method. *

    - * Only the specified portion of the buffer will be processed. - * The rest of the buffer is not processed, and is not returned. + * Only the specified portion of the buffer will be processed. The rest of the buffer is not processed, and is not returned. *

    * - * @param source the buffer to use as a template, not changed, null returns null - * @param offset the start offset within the array, must be valid - * @param length the length within the array to be processed, must be valid - * @return The result of the replace operation + * @param source the buffer to use as a template, not changed, null returns null. + * @param offset the start offset within the array, must be valid. + * @param length the length within the array to be processed, must be valid. + * @return The result of the replace operation. */ public String replace(final CharSequence source, final int offset, final int length) { if (source == null) { @@ -592,12 +584,11 @@ public String replace(final CharSequence source, final int offset, final int len } /** - * Replaces all the occurrences of variables in the given source object with - * their matching values from the resolver. The input source object is - * converted to a string using {@code toString} and is not altered. + * Replaces all the occurrences of variables in the given source object with their matching values from the resolver. The input source object is converted + * to a string using {@code toString} and is not altered. * - * @param source the source to replace in, null returns null - * @return The result of the replace operation + * @param source the source to replace in, null returns null. + * @return The result of the replace operation. */ public String replace(final Object source) { if (source == null) { @@ -609,12 +600,11 @@ public String replace(final Object source) { } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source builder as a template. - * The builder is not altered by this method. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source builder as a template. The builder is not + * altered by this method. * - * @param source the builder to use as a template, not changed, null returns null - * @return The result of the replace operation + * @param source the builder to use as a template, not changed, null returns null. + * @return The result of the replace operation. */ public String replace(final StrBuilder source) { if (source == null) { @@ -626,18 +616,16 @@ public String replace(final StrBuilder source) { } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source builder as a template. - * The builder is not altered by this method. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source builder as a template. The builder is not + * altered by this method. *

    - * Only the specified portion of the builder will be processed. - * The rest of the builder is not processed, and is not returned. + * Only the specified portion of the builder will be processed. The rest of the builder is not processed, and is not returned. *

    * - * @param source the builder to use as a template, not changed, null returns null - * @param offset the start offset within the array, must be valid - * @param length the length within the array to be processed, must be valid - * @return The result of the replace operation + * @param source the builder to use as a template, not changed, null returns null. + * @param offset the start offset within the array, must be valid. + * @param length the length within the array to be processed, must be valid. + * @return The result of the replace operation. */ public String replace(final StrBuilder source, final int offset, final int length) { if (source == null) { @@ -649,11 +637,10 @@ public String replace(final StrBuilder source, final int offset, final int lengt } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source string as a template. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source string as a template. * - * @param source the string to replace in, null returns null - * @return The result of the replace operation + * @param source the string to replace in, null returns null. + * @return The result of the replace operation. */ public String replace(final String source) { if (source == null) { @@ -667,17 +654,15 @@ public String replace(final String source) { } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source string as a template. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source string as a template. *

    - * Only the specified portion of the string will be processed. - * The rest of the string is not processed, and is not returned. + * Only the specified portion of the string will be processed. The rest of the string is not processed, and is not returned. *

    * - * @param source the string to replace in, null returns null - * @param offset the start offset within the array, must be valid - * @param length the length within the array to be processed, must be valid - * @return The result of the replace operation + * @param source the string to replace in, null returns null. + * @param offset the start offset within the array, must be valid. + * @param length the length within the array to be processed, must be valid. + * @return The result of the replace operation. */ public String replace(final String source, final int offset, final int length) { if (source == null) { @@ -691,12 +676,11 @@ public String replace(final String source, final int offset, final int length) { } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source buffer as a template. - * The buffer is not altered by this method. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source buffer as a template. The buffer is not + * altered by this method. * - * @param source the buffer to use as a template, not changed, null returns null - * @return The result of the replace operation + * @param source the buffer to use as a template, not changed, null returns null. + * @return The result of the replace operation. */ public String replace(final StringBuffer source) { if (source == null) { @@ -708,18 +692,16 @@ public String replace(final StringBuffer source) { } /** - * Replaces all the occurrences of variables with their matching values - * from the resolver using the given source buffer as a template. - * The buffer is not altered by this method. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source buffer as a template. The buffer is not + * altered by this method. *

    - * Only the specified portion of the buffer will be processed. - * The rest of the buffer is not processed, and is not returned. + * Only the specified portion of the buffer will be processed. The rest of the buffer is not processed, and is not returned. *

    * - * @param source the buffer to use as a template, not changed, null returns null - * @param offset the start offset within the array, must be valid - * @param length the length within the array to be processed, must be valid - * @return The result of the replace operation + * @param source the buffer to use as a template, not changed, null returns null. + * @param offset the start offset within the array, must be valid. + * @param length the length within the array to be processed, must be valid. + * @return The result of the replace operation. */ public String replace(final StringBuffer source, final int offset, final int length) { if (source == null) { @@ -731,11 +713,10 @@ public String replace(final StringBuffer source, final int offset, final int len } /** - * Replaces all the occurrences of variables within the given source - * builder with their matching values from the resolver. + * Replaces all the occurrences of variables within the given source builder with their matching values from the resolver. * - * @param source the builder to replace in, updated, null returns zero - * @return true if altered + * @param source the builder to replace in, updated, null returns zero. + * @return true if altered. */ public boolean replaceIn(final StrBuilder source) { if (source == null) { @@ -745,17 +726,15 @@ public boolean replaceIn(final StrBuilder source) { } /** - * Replaces all the occurrences of variables within the given source - * builder with their matching values from the resolver. + * Replaces all the occurrences of variables within the given source builder with their matching values from the resolver. *

    - * Only the specified portion of the builder will be processed. - * The rest of the builder is not processed, but it is not deleted. + * Only the specified portion of the builder will be processed. The rest of the builder is not processed, but it is not deleted. *

    * - * @param source the builder to replace in, null returns zero - * @param offset the start offset within the array, must be valid - * @param length the length within the builder to be processed, must be valid - * @return true if altered + * @param source the builder to replace in, null returns zero. + * @param offset the start offset within the array, must be valid. + * @param length the length within the builder to be processed, must be valid. + * @return true if altered. */ public boolean replaceIn(final StrBuilder source, final int offset, final int length) { if (source == null) { @@ -765,12 +744,11 @@ public boolean replaceIn(final StrBuilder source, final int offset, final int le } /** - * Replaces all the occurrences of variables within the given source buffer - * with their matching values from the resolver. - * The buffer is updated with the result. + * Replaces all the occurrences of variables within the given source buffer with their matching values from the resolver. The buffer is updated with the + * result. * - * @param source the buffer to replace in, updated, null returns zero - * @return true if altered + * @param source the buffer to replace in, updated, null returns zero. + * @return true if altered. */ public boolean replaceIn(final StringBuffer source) { if (source == null) { @@ -780,18 +758,16 @@ public boolean replaceIn(final StringBuffer source) { } /** - * Replaces all the occurrences of variables within the given source buffer - * with their matching values from the resolver. - * The buffer is updated with the result. + * Replaces all the occurrences of variables within the given source buffer with their matching values from the resolver. The buffer is updated with the + * result. *

    - * Only the specified portion of the buffer will be processed. - * The rest of the buffer is not processed, but it is not deleted. + * Only the specified portion of the buffer will be processed. The rest of the buffer is not processed, but it is not deleted. *

    * - * @param source the buffer to replace in, updated, null returns zero - * @param offset the start offset within the array, must be valid - * @param length the length within the buffer to be processed, must be valid - * @return true if altered + * @param source the buffer to replace in, updated, null returns zero. + * @param offset the start offset within the array, must be valid. + * @param length the length within the buffer to be processed, must be valid. + * @return true if altered. */ public boolean replaceIn(final StringBuffer source, final int offset, final int length) { if (source == null) { @@ -806,12 +782,11 @@ public boolean replaceIn(final StringBuffer source, final int offset, final int } /** - * Replaces all the occurrences of variables within the given source buffer - * with their matching values from the resolver. - * The buffer is updated with the result. + * Replaces all the occurrences of variables within the given source buffer with their matching values from the resolver. The buffer is updated with the + * result. * - * @param source the buffer to replace in, updated, null returns zero - * @return true if altered + * @param source the buffer to replace in, updated, null returns zero. + * @return true if altered. */ public boolean replaceIn(final StringBuilder source) { if (source == null) { @@ -821,18 +796,16 @@ public boolean replaceIn(final StringBuilder source) { } /** - * Replaces all the occurrences of variables within the given source builder - * with their matching values from the resolver. - * The builder is updated with the result. + * Replaces all the occurrences of variables within the given source builder with their matching values from the resolver. The builder is updated with the + * result. *

    - * Only the specified portion of the buffer will be processed. - * The rest of the buffer is not processed, but it is not deleted. + * Only the specified portion of the buffer will be processed. The rest of the buffer is not processed, but it is not deleted. *

    * - * @param source the buffer to replace in, updated, null returns zero - * @param offset the start offset within the array, must be valid - * @param length the length within the buffer to be processed, must be valid - * @return true if altered + * @param source the buffer to replace in, updated, null returns zero. + * @param offset the start offset within the array, must be valid. + * @param length the length within the buffer to be processed, must be valid. + * @return true if altered. */ public boolean replaceIn(final StringBuilder source, final int offset, final int length) { if (source == null) { @@ -849,21 +822,18 @@ public boolean replaceIn(final StringBuilder source, final int offset, final int /** * Internal method that resolves the value of a variable. *

    - * Most users of this class do not need to call this method. This method is - * called automatically by the substitution process. + * Most users of this class do not need to call this method. This method is called automatically by the substitution process. *

    *

    - * Writers of subclasses can override this method if they need to alter - * how each substitution occurs. The method is passed the variable's name - * and must return the corresponding value. This implementation uses the - * {@link #getVariableResolver()} with the variable's name as the key. + * Writers of subclasses can override this method if they need to alter how each substitution occurs. The method is passed the variable's name and must + * return the corresponding value. This implementation uses the {@link #getVariableResolver()} with the variable's name as the key. *

    * - * @param variableName the name of the variable, not null - * @param buf the buffer where the substitution is occurring, not null - * @param startPos the start position of the variable including the prefix, valid - * @param endPos the end position of the variable including the suffix, valid - * @return The variable's value or null if the variable is unknown + * @param variableName the name of the variable, not null. + * @param buf the buffer where the substitution is occurring, not null. + * @param startPos the start position of the variable including the prefix, valid. + * @param endPos the end position of the variable including the suffix, valid. + * @return The variable's value or null if the variable is unknown. */ protected String resolveVariable(final String variableName, final StrBuilder buf, @@ -879,7 +849,7 @@ protected String resolveVariable(final String variableName, /** * Sets a flag whether substitution is done in variable values (recursive). * - * @param disableSubstitutionInValues true if substitution in variable value are disabled + * @param disableSubstitutionInValues true if substitution in variable value are disabled. * @since 1.2 */ public void setDisableSubstitutionInValues(final boolean disableSubstitutionInValues) { @@ -887,37 +857,28 @@ public void setDisableSubstitutionInValues(final boolean disableSubstitutionInVa } /** - * Sets a flag whether substitution is done in variable names. If set to - * true, the names of variables can contain other variables which are - * processed first before the original variable is evaluated, e.g. - * {@code ${jre-${java.version}}}. The default value is false. + * Sets a flag whether substitution is done in variable names. If set to true, the names of variables can contain other variables which are + * processed first before the original variable is evaluated, e.g. {@code ${jre-${java.version}}}. The default value is false. * - * @param enableSubstitutionInVariables the new value of the flag + * @param enableSubstitutionInVariables the new value of the flag. */ - public void setEnableSubstitutionInVariables( - final boolean enableSubstitutionInVariables) { + public void setEnableSubstitutionInVariables(final boolean enableSubstitutionInVariables) { this.enableSubstitutionInVariables = enableSubstitutionInVariables; } /** - * Sets the escape character. - * If this character is placed before a variable reference in the source - * text, this variable will be ignored. + * Sets the escape character. If this character is placed before a variable reference in the source text, this variable will be ignored. * - * @param escapeCharacter the escape character (0 for disabling escaping) + * @param escapeCharacter the escape character (0 for disabling escaping) */ public void setEscapeChar(final char escapeCharacter) { this.escapeChar = escapeCharacter; } /** - * Sets a flag controlling whether escapes are preserved during - * substitution. If set to true, the escape character is retained - * during substitution (e.g. {@code $${this-is-escaped}} remains - * {@code $${this-is-escaped}}). If set to false, the escape - * character is removed during substitution (e.g. - * {@code $${this-is-escaped}} becomes - * {@code ${this-is-escaped}}). The default value is false + * Sets a flag controlling whether escapes are preserved during substitution. If set to true, the escape character is retained during + * substitution (e.g. {@code $${this-is-escaped}} remains {@code $${this-is-escaped}}). If set to false, the escape character is removed + * during substitution (e.g. {@code $${this-is-escaped}} becomes {@code ${this-is-escaped}}). The default value is false * * @param preserveEscapes true if escapes are to be preserved */ @@ -928,13 +889,12 @@ public void setPreserveEscapes(final boolean preserveEscapes) { /** * Sets the variable default value delimiter to use. *

    - * The variable default value delimiter is the character or characters that delimit the - * variable name and the variable default value. This method allows a single character - * variable default value delimiter to be easily set. + * The variable default value delimiter is the character or characters that delimit the variable name and the variable default value. This method allows a + * single character variable default value delimiter to be easily set. *

    * - * @param valueDelimiter the variable default value delimiter character to use - * @return this, to enable chaining + * @param valueDelimiter the variable default value delimiter character to use. + * @return {@code this} instance. */ public StrSubstitutor setValueDelimiter(final char valueDelimiter) { return setValueDelimiterMatcher(StrMatcher.charMatcher(valueDelimiter)); @@ -943,17 +903,15 @@ public StrSubstitutor setValueDelimiter(final char valueDelimiter) { /** * Sets the variable default value delimiter to use. *

    - * The variable default value delimiter is the character or characters that delimit the - * variable name and the variable default value. This method allows a string - * variable default value delimiter to be easily set. + * The variable default value delimiter is the character or characters that delimit the variable name and the variable default value. This method allows a + * string variable default value delimiter to be easily set. *

    *

    - * If the {@code valueDelimiter} is null or empty string, then the variable default - * value resolution becomes disabled. + * If the {@code valueDelimiter} is null or empty string, then the variable default value resolution becomes disabled. *

    * - * @param valueDelimiter the variable default value delimiter string to use, may be null or empty - * @return this, to enable chaining + * @param valueDelimiter the variable default value delimiter string to use, may be null or empty + * @return {@code this} instance. */ public StrSubstitutor setValueDelimiter(final String valueDelimiter) { if (valueDelimiter == null || valueDelimiter.isEmpty()) { @@ -966,17 +924,15 @@ public StrSubstitutor setValueDelimiter(final String valueDelimiter) { /** * Sets the variable default value delimiter matcher to use. *

    - * The variable default value delimiter is the character or characters that delimit the - * variable name and the variable default value. This delimiter is expressed in terms of a matcher - * allowing advanced variable default value delimiter matches. + * The variable default value delimiter is the character or characters that delimit the variable name and the variable default value. This delimiter is + * expressed in terms of a matcher allowing advanced variable default value delimiter matches. *

    *

    - * If the {@code valueDelimiterMatcher} is null, then the variable default value resolution - * becomes disabled. + * If the {@code valueDelimiterMatcher} is null, then the variable default value resolution becomes disabled. *

    * - * @param valueDelimiterMatcher variable default value delimiter matcher to use, may be null - * @return this, to enable chaining + * @param valueDelimiterMatcher variable default value delimiter matcher to use, may be null + * @return {@code this} instance. */ public StrSubstitutor setValueDelimiterMatcher(final StrMatcher valueDelimiterMatcher) { this.valueDelimiterMatcher = valueDelimiterMatcher; @@ -986,13 +942,11 @@ public StrSubstitutor setValueDelimiterMatcher(final StrMatcher valueDelimiterMa /** * Sets the variable prefix to use. *

    - * The variable prefix is the character or characters that identify the - * start of a variable. This method allows a single character prefix to - * be easily set. + * The variable prefix is the character or characters that identify the start of a variable. This method allows a single character prefix to be easily set. *

    * - * @param prefix the prefix character to use - * @return this, to enable chaining + * @param prefix the prefix character to use. + * @return {@code this} instance. */ public StrSubstitutor setVariablePrefix(final char prefix) { return setVariablePrefixMatcher(StrMatcher.charMatcher(prefix)); @@ -1001,13 +955,12 @@ public StrSubstitutor setVariablePrefix(final char prefix) { /** * Sets the variable prefix to use. *

    - * The variable prefix is the character or characters that identify the - * start of a variable. This method allows a string prefix to be easily set. + * The variable prefix is the character or characters that identify the start of a variable. This method allows a string prefix to be easily set. *

    * - * @param prefix the prefix for variables, not null - * @return this, to enable chaining - * @throws IllegalArgumentException if the prefix is null + * @param prefix the prefix for variables, not null. + * @return {@code this} instance. + * @throws IllegalArgumentException if the prefix is null. */ public StrSubstitutor setVariablePrefix(final String prefix) { Validate.isTrue(prefix != null, "Variable prefix must not be null!"); @@ -1017,14 +970,13 @@ public StrSubstitutor setVariablePrefix(final String prefix) { /** * Sets the variable prefix matcher currently in use. *

    - * The variable prefix is the character or characters that identify the - * start of a variable. This prefix is expressed in terms of a matcher - * allowing advanced prefix matches. + * The variable prefix is the character or characters that identify the start of a variable. This prefix is expressed in terms of a matcher allowing + * advanced prefix matches. *

    * - * @param prefixMatcher the prefix matcher to use, null ignored - * @return this, to enable chaining - * @throws IllegalArgumentException if the prefix matcher is null + * @param prefixMatcher the prefix matcher to use, null ignored. + * @return {@code this} instance. + * @throws IllegalArgumentException if the prefix matcher is null. */ public StrSubstitutor setVariablePrefixMatcher(final StrMatcher prefixMatcher) { Validate.isTrue(prefixMatcher != null, "Variable prefix matcher must not be null!"); @@ -1035,7 +987,7 @@ public StrSubstitutor setVariablePrefixMatcher(final StrMatcher prefixMatcher) { /** * Sets the VariableResolver that is used to lookup variables. * - * @param variableResolver the VariableResolver + * @param variableResolver the VariableResolver. */ public void setVariableResolver(final StrLookup variableResolver) { this.variableResolver = variableResolver; @@ -1044,13 +996,11 @@ public void setVariableResolver(final StrLookup variableResolver) { /** * Sets the variable suffix to use. *

    - * The variable suffix is the character or characters that identify the - * end of a variable. This method allows a single character suffix to - * be easily set. + * The variable suffix is the character or characters that identify the end of a variable. This method allows a single character suffix to be easily set. *

    * - * @param suffix the suffix character to use - * @return this, to enable chaining + * @param suffix the suffix character to use. + * @return {@code this} instance. */ public StrSubstitutor setVariableSuffix(final char suffix) { return setVariableSuffixMatcher(StrMatcher.charMatcher(suffix)); @@ -1059,13 +1009,12 @@ public StrSubstitutor setVariableSuffix(final char suffix) { /** * Sets the variable suffix to use. *

    - * The variable suffix is the character or characters that identify the - * end of a variable. This method allows a string suffix to be easily set. + * The variable suffix is the character or characters that identify the end of a variable. This method allows a string suffix to be easily set. *

    * - * @param suffix the suffix for variables, not null - * @return this, to enable chaining - * @throws IllegalArgumentException if the suffix is null + * @param suffix the suffix for variables, not null. + * @return {@code this} instance. + * @throws IllegalArgumentException if the suffix is null. */ public StrSubstitutor setVariableSuffix(final String suffix) { Validate.isTrue(suffix != null, "Variable suffix must not be null!"); @@ -1075,14 +1024,13 @@ public StrSubstitutor setVariableSuffix(final String suffix) { /** * Sets the variable suffix matcher currently in use. *

    - * The variable suffix is the character or characters that identify the - * end of a variable. This suffix is expressed in terms of a matcher - * allowing advanced suffix matches. + * The variable suffix is the character or characters that identify the end of a variable. This suffix is expressed in terms of a matcher allowing advanced + * suffix matches. *

    * - * @param suffixMatcher the suffix matcher to use, null ignored - * @return this, to enable chaining - * @throws IllegalArgumentException if the suffix matcher is null + * @param suffixMatcher the suffix matcher to use, null ignored. + * @return {@code this} instance. + * @throws IllegalArgumentException if the suffix matcher is null. */ public StrSubstitutor setVariableSuffixMatcher(final StrMatcher suffixMatcher) { Validate.isTrue(suffixMatcher != null, "Variable suffix matcher must not be null!"); @@ -1093,34 +1041,30 @@ public StrSubstitutor setVariableSuffixMatcher(final StrMatcher suffixMatcher) { /** * Internal method that substitutes the variables. *

    - * Most users of this class do not need to call this method. This method will - * be called automatically by another (public) method. + * Most users of this class do not need to call this method. This method will be called automatically by another (public) method. *

    *

    - * Writers of subclasses can override this method if they need access to - * the substitution process at the start or end. + * Writers of subclasses can override this method if they need access to the substitution process at the start or end. *

    * - * @param buf the string builder to substitute into, not null - * @param offset the start offset within the builder, must be valid - * @param length the length within the builder to be processed, must be valid - * @return true if altered + * @param buf the string builder to substitute into, not null. + * @param offset the start offset within the builder, must be valid. + * @param length the length within the builder to be processed, must be valid. + * @return true if altered. */ protected boolean substitute(final StrBuilder buf, final int offset, final int length) { return substitute(buf, offset, length, null) > 0; } /** - * Recursive handler for multiple levels of interpolation. This is the main - * interpolation method, which resolves the values of all variable references + * Recursive handler for multiple levels of interpolation. This is the main interpolation method, which resolves the values of all variable references * contained in the passed in text. * - * @param buf the string builder to substitute into, not null - * @param offset the start offset within the builder, must be valid - * @param length the length within the builder to be processed, must be valid - * @param priorVariables the stack keeping track of the replaced variables, may be null - * @return The length change that occurs, unless priorVariables is null when the int - * represents a boolean flag as to whether any change occurred. + * @param buf the string builder to substitute into, not null. + * @param offset the start offset within the builder, must be valid. + * @param length the length within the builder to be processed, must be valid. + * @param priorVariables the stack keeping track of the replaced variables, may be null. + * @return The length change that occurs, unless priorVariables is null when the int represents a boolean flag as to whether any change occurred. */ private int substitute(final StrBuilder buf, final int offset, final int length, List priorVariables) { final StrMatcher pfxMatcher = getVariablePrefixMatcher(); diff --git a/src/main/java/org/apache/commons/text/StrTokenizer.java b/src/main/java/org/apache/commons/text/StrTokenizer.java index abfd1b0736..66ede10fd3 100644 --- a/src/main/java/org/apache/commons/text/StrTokenizer.java +++ b/src/main/java/org/apache/commons/text/StrTokenizer.java @@ -118,27 +118,24 @@ private static StrTokenizer getCSVClone() { } /** - * Gets a new tokenizer instance which parses Comma Separated Value strings - * initializing it with the given input. The default for CSV processing - * will be trim whitespace from both ends (which can be overridden with - * the setTrimmer method). + * Gets a new tokenizer instance which parses Comma Separated Value strings initializing it with the given input. The default for CSV processing will be + * trim whitespace from both ends (which can be overridden with the setTrimmer method). *

    * You must call a "reset" method to set the string which you want to parse. *

    - * @return a new tokenizer instance which parses Comma Separated Value strings + * + * @return a new tokenizer instance which parses Comma Separated Value strings. */ public static StrTokenizer getCSVInstance() { return getCSVClone(); } /** - * Gets a new tokenizer instance which parses Comma Separated Value strings - * initializing it with the given input. The default for CSV processing - * will be trim whitespace from both ends (which can be overridden with - * the setTrimmer method). + * Gets a new tokenizer instance which parses Comma Separated Value strings initializing it with the given input. The default for CSV processing will be + * trim whitespace from both ends (which can be overridden with the setTrimmer method). * - * @param input the text to parse - * @return a new tokenizer instance which parses Comma Separated Value strings + * @param input the text to parse. + * @return a new tokenizer instance which parses Comma Separated Value strings. */ public static StrTokenizer getCSVInstance(final char[] input) { final StrTokenizer tok = getCSVClone(); @@ -147,19 +144,18 @@ public static StrTokenizer getCSVInstance(final char[] input) { } /** - * Gets a new tokenizer instance which parses Comma Separated Value strings - * initializing it with the given input. The default for CSV processing - * will be trim whitespace from both ends (which can be overridden with - * the setTrimmer method). + * Gets a new tokenizer instance which parses Comma Separated Value strings initializing it with the given input. The default for CSV processing will be + * trim whitespace from both ends (which can be overridden with the setTrimmer method). * - * @param input the text to parse - * @return a new tokenizer instance which parses Comma Separated Value strings + * @param input the text to parse. + * @return a new tokenizer instance which parses Comma Separated Value strings. */ public static StrTokenizer getCSVInstance(final String input) { final StrTokenizer tok = getCSVClone(); tok.reset(input); return tok; } + /** * Returns a clone of {@code TSV_TOKENIZER_PROTOTYPE}. * @@ -170,12 +166,12 @@ private static StrTokenizer getTSVClone() { } /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. - * The default for CSV processing will be trim whitespace from both ends - * (which can be overridden with the setTrimmer method). + * Gets a new tokenizer instance which parses Tab Separated Value strings. The default for CSV processing will be trim whitespace from both ends (which can + * be overridden with the setTrimmer method). *

    * You must call a "reset" method to set the string which you want to parse. *

    + * * @return a new tokenizer instance which parses Tab Separated Value strings. */ public static StrTokenizer getTSVInstance() { @@ -183,10 +179,10 @@ public static StrTokenizer getTSVInstance() { } /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. - * The default for CSV processing will be trim whitespace from both ends - * (which can be overridden with the setTrimmer method). - * @param input the string to parse + * Gets a new tokenizer instance which parses Tab Separated Value strings. The default for CSV processing will be trim whitespace from both ends (which can + * be overridden with the setTrimmer method). + * + * @param input the string to parse. * @return a new tokenizer instance which parses Tab Separated Value strings. */ public static StrTokenizer getTSVInstance(final char[] input) { @@ -196,10 +192,10 @@ public static StrTokenizer getTSVInstance(final char[] input) { } /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. - * The default for CSV processing will be trim whitespace from both ends - * (which can be overridden with the setTrimmer method). - * @param input the string to parse + * Gets a new tokenizer instance which parses Tab Separated Value strings. The default for CSV processing will be trim whitespace from both ends (which can + * be overridden with the setTrimmer method). + * + * @param input the string to parse. * @return a new tokenizer instance which parses Tab Separated Value strings. */ public static StrTokenizer getTSVInstance(final String input) { @@ -236,8 +232,7 @@ public static StrTokenizer getTSVInstance(final String input) { private boolean ignoreEmptyTokens = true; /** - * Constructs a tokenizer splitting on space, tab, newline and form feed - * as per StringTokenizer, but with no text to tokenize. + * Constructs a tokenizer splitting on space, tab, newline and form feed as per StringTokenizer, but with no text to tokenize. *

    * This constructor is normally used with {@link #reset(String)}. *

    @@ -250,7 +245,7 @@ public StrTokenizer() { * Constructs a tokenizer splitting on space, tab, newline and form feed * as per StringTokenizer. * - * @param input the string which is to be parsed, not cloned + * @param input the string which is to be parsed, not cloned. */ public StrTokenizer(final char[] input) { if (input == null) { @@ -263,8 +258,8 @@ public StrTokenizer(final char[] input) { /** * Constructs a tokenizer splitting on the specified character. * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter character + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter character. */ public StrTokenizer(final char[] input, final char delim) { this(input); @@ -275,9 +270,9 @@ public StrTokenizer(final char[] input, final char delim) { * Constructs a tokenizer splitting on the specified delimiter character * and handling quotes using the specified quote character. * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter character - * @param quote the field quoted string character + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter character. + * @param quote the field quoted string character. */ public StrTokenizer(final char[] input, final char delim, final char quote) { this(input, delim); @@ -287,8 +282,8 @@ public StrTokenizer(final char[] input, final char delim, final char quote) { /** * Constructs a tokenizer splitting on the specified string. * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter string + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter string. */ public StrTokenizer(final char[] input, final String delim) { this(input); @@ -298,8 +293,8 @@ public StrTokenizer(final char[] input, final String delim) { /** * Constructs a tokenizer splitting using the specified delimiter matcher. * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter matcher + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter matcher. */ public StrTokenizer(final char[] input, final StrMatcher delim) { this(input); @@ -310,9 +305,9 @@ public StrTokenizer(final char[] input, final StrMatcher delim) { * Constructs a tokenizer splitting using the specified delimiter matcher * and handling quotes using the specified quote matcher. * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter character - * @param quote the field quoted string character + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter character. + * @param quote the field quoted string character. */ public StrTokenizer(final char[] input, final StrMatcher delim, final StrMatcher quote) { this(input, delim); @@ -323,7 +318,7 @@ public StrTokenizer(final char[] input, final StrMatcher delim, final StrMatcher * Constructs a tokenizer splitting on space, tab, newline and form feed * as per StringTokenizer. * - * @param input the string which is to be parsed + * @param input the string which is to be parsed. */ public StrTokenizer(final String input) { if (input != null) { @@ -336,8 +331,8 @@ public StrTokenizer(final String input) { /** * Constructs a tokenizer splitting on the specified delimiter character. * - * @param input the string which is to be parsed - * @param delim the field delimiter character + * @param input the string which is to be parsed. + * @param delim the field delimiter character. */ public StrTokenizer(final String input, final char delim) { this(input); @@ -348,9 +343,9 @@ public StrTokenizer(final String input, final char delim) { * Constructs a tokenizer splitting on the specified delimiter character * and handling quotes using the specified quote character. * - * @param input the string which is to be parsed - * @param delim the field delimiter character - * @param quote the field quoted string character + * @param input the string which is to be parsed. + * @param delim the field delimiter character. + * @param quote the field quoted string character. */ public StrTokenizer(final String input, final char delim, final char quote) { this(input, delim); @@ -360,8 +355,8 @@ public StrTokenizer(final String input, final char delim, final char quote) { /** * Constructs a tokenizer splitting on the specified delimiter string. * - * @param input the string which is to be parsed - * @param delim the field delimiter string + * @param input the string which is to be parsed. + * @param delim the field delimiter string. */ public StrTokenizer(final String input, final String delim) { this(input); @@ -371,8 +366,8 @@ public StrTokenizer(final String input, final String delim) { /** * Constructs a tokenizer splitting using the specified delimiter matcher. * - * @param input the string which is to be parsed - * @param delim the field delimiter matcher + * @param input the string which is to be parsed. + * @param delim the field delimiter matcher. */ public StrTokenizer(final String input, final StrMatcher delim) { this(input); @@ -383,9 +378,9 @@ public StrTokenizer(final String input, final StrMatcher delim) { * Constructs a tokenizer splitting using the specified delimiter matcher * and handling quotes using the specified quote matcher. * - * @param input the string which is to be parsed - * @param delim the field delimiter matcher - * @param quote the field quoted string matcher + * @param input the string which is to be parsed. + * @param delim the field delimiter matcher. + * @param quote the field quoted string matcher. */ public StrTokenizer(final String input, final StrMatcher delim, final StrMatcher quote) { this(input, delim); @@ -395,7 +390,7 @@ public StrTokenizer(final String input, final StrMatcher delim, final StrMatcher /** * Unsupported ListIterator operation. * @param obj this parameter ignored. - * @throws UnsupportedOperationException always + * @throws UnsupportedOperationException always. */ @Override public void add(final String obj) { @@ -405,8 +400,8 @@ public void add(final String obj) { /** * Adds a token to a list, paying attention to the parameters we've set. * - * @param list the list to add to - * @param tok the token to add + * @param list the list to add to. + * @param tok the token to add. */ private void addToken(final List list, String tok) { if (tok == null || tok.isEmpty()) { @@ -437,9 +432,8 @@ private void checkTokenized() { } /** - * Creates a new instance of this Tokenizer. The new instance is reset so - * that it will be at the start of the token list. - * If a {@link CloneNotSupportedException} is caught, return {@code null}. + * Creates a new instance of this Tokenizer. The new instance is reset so that it will be at the start of the token list. If a + * {@link CloneNotSupportedException} is caught, return {@code null}. * * @return a new instance of this Tokenizer which has been reset. */ @@ -453,11 +447,10 @@ public Object clone() { } /** - * Creates a new instance of this Tokenizer. The new instance is reset so that - * it will be at the start of the token list. + * Creates a new instance of this Tokenizer. The new instance is reset so that it will be at the start of the token list. * * @return a new instance of this Tokenizer which has been reset. - * @throws CloneNotSupportedException if there is a problem cloning + * @throws CloneNotSupportedException if there is a problem cloning. */ Object cloneReset() throws CloneNotSupportedException { // this method exists to enable 100% test coverage @@ -472,7 +465,7 @@ Object cloneReset() throws CloneNotSupportedException { /** * Gets the String content that the tokenizer is parsing. * - * @return The string content being parsed + * @return The string content being parsed. */ public String getContent() { if (chars == null) { @@ -484,7 +477,7 @@ public String getContent() { /** * Gets the field delimiter matcher. * - * @return The delimiter matcher in use + * @return The delimiter matcher in use. */ public StrMatcher getDelimiterMatcher() { return this.delimMatcher; @@ -493,12 +486,10 @@ public StrMatcher getDelimiterMatcher() { /** * Gets the ignored character matcher. *

    - * These characters are ignored when parsing the String, unless they are - * within a quoted region. - * The default value is not to ignore anything. + * These characters are ignored when parsing the String, unless they are within a quoted region. The default value is not to ignore anything. *

    * - * @return The ignored matcher in use + * @return The ignored matcher in use. */ public StrMatcher getIgnoredMatcher() { return ignoredMatcher; @@ -507,12 +498,10 @@ public StrMatcher getIgnoredMatcher() { /** * Gets the quote matcher currently in use. *

    - * The quote character is used to wrap data between the tokens. - * This enables delimiters to be entered as data. - * The default value is '"' (double quote). + * The quote character is used to wrap data between the tokens. This enables delimiters to be entered as data. The default value is '"' (double quote). *

    * - * @return The quote matcher in use + * @return The quote matcher in use. */ public StrMatcher getQuoteMatcher() { return quoteMatcher; @@ -521,7 +510,7 @@ public StrMatcher getQuoteMatcher() { /** * Gets a copy of the full token list as an independent modifiable array. * - * @return The tokens as a String array + * @return The tokens as a String array. */ public String[] getTokenArray() { checkTokenized(); @@ -531,7 +520,7 @@ public String[] getTokenArray() { /** * Gets a copy of the full token list as an independent modifiable list. * - * @return The tokens as a String array + * @return The tokens as a String array. */ public List getTokenList() { checkTokenized(); @@ -544,12 +533,10 @@ public List getTokenList() { /** * Gets the trimmer character matcher. *

    - * These characters are trimmed off on each side of the delimiter - * until the token or quote is found. - * The default value is not to trim anything. + * These characters are trimmed off on each side of the delimiter until the token or quote is found. The default value is not to trim anything. *

    * - * @return The trimmer matcher in use + * @return The trimmer matcher in use. */ public StrMatcher getTrimmerMatcher() { return trimmerMatcher; @@ -558,7 +545,7 @@ public StrMatcher getTrimmerMatcher() { /** * Checks whether there are any more tokens. * - * @return true if there are more tokens + * @return true if there are more tokens. */ @Override public boolean hasNext() { @@ -569,7 +556,7 @@ public boolean hasNext() { /** * Checks whether there are any previous tokens that can be iterated to. * - * @return true if there are previous tokens + * @return true if there are previous tokens. */ @Override public boolean hasPrevious() { @@ -581,7 +568,7 @@ public boolean hasPrevious() { * Gets whether the tokenizer currently returns empty tokens as null. * The default for this property is false. * - * @return true if empty tokens are returned as null + * @return true if empty tokens are returned as null. */ public boolean isEmptyTokenAsNull() { return this.emptyAsNull; @@ -591,7 +578,7 @@ public boolean isEmptyTokenAsNull() { * Gets whether the tokenizer currently ignores empty tokens. * The default for this property is true. * - * @return true if empty tokens are not returned + * @return true if empty tokens are not returned. */ public boolean isIgnoreEmptyTokens() { return ignoreEmptyTokens; @@ -601,12 +588,12 @@ public boolean isIgnoreEmptyTokens() { * Checks if the characters at the index specified match the quote * already matched in readNextToken(). * - * @param srcChars the character array being tokenized - * @param pos the position to check for a quote - * @param len the length of the character array being tokenized - * @param quoteStart the start position of the matched quote, 0 if no quoting - * @param quoteLen the length of the matched quote, 0 if no quoting - * @return true if a quote is matched + * @param srcChars the character array being tokenized. + * @param pos the position to check for a quote. + * @param len the length of the character array being tokenized. + * @param quoteStart the start position of the matched quote, 0 if no quoting. + * @param quoteLen the length of the matched quote, 0 if no quoting. + * @return true if a quote is matched. */ private boolean isQuote(final char[] srcChars, final int pos, @@ -624,8 +611,8 @@ private boolean isQuote(final char[] srcChars, /** * Gets the next token. * - * @return The next String token - * @throws NoSuchElementException if there are no more elements + * @return The next String token. + * @throws NoSuchElementException if there are no more elements. */ @Override public String next() { @@ -638,7 +625,7 @@ public String next() { /** * Gets the index of the next token to return. * - * @return The next token index + * @return The next token index. */ @Override public int nextIndex() { @@ -646,11 +633,10 @@ public int nextIndex() { } /** - * Gets the next token from the String. - * Equivalent to {@link #next()} except it returns null rather than - * throwing {@link NoSuchElementException} when no tokens remain. + * Gets the next token from the String. Equivalent to {@link #next()} except it returns null rather than throwing {@link NoSuchElementException} when no + * tokens remain. * - * @return The next sequential token, or null when no more tokens are found + * @return The next sequential token, or null when no more tokens are found. */ public String nextToken() { if (hasNext()) { @@ -662,7 +648,7 @@ public String nextToken() { /** * Gets the token previous to the last returned token. * - * @return The previous token + * @return The previous token. */ @Override public String previous() { @@ -675,7 +661,7 @@ public String previous() { /** * Gets the index of the previous token. * - * @return The previous token index + * @return The previous token index. */ @Override public int previousIndex() { @@ -685,7 +671,7 @@ public int previousIndex() { /** * Gets the previous token from the String. * - * @return The previous sequential token, or null when no more tokens are found + * @return The previous sequential token, or null when no more tokens are found. */ public String previousToken() { if (hasPrevious()) { @@ -697,13 +683,12 @@ public String previousToken() { /** * Reads character by character through the String to get the next token. * - * @param srcChars the character array being tokenized - * @param start the first character of field - * @param len the length of the character array being tokenized - * @param workArea a temporary work area - * @param tokenList the list of parsed tokens - * @return The starting position of the next field (the character - * immediately after the delimiter), or -1 if end of string found + * @param srcChars the character array being tokenized. + * @param start the first character of field. + * @param len the length of the character array being tokenized. + * @param workArea a temporary work area. + * @param tokenList the list of parsed tokens. + * @return The starting position of the next field (the character immediately after the delimiter), or -1 if end of string found. */ private int readNextToken(final char[] srcChars, int start, @@ -748,16 +733,14 @@ private int readNextToken(final char[] srcChars, /** * Reads a possibly quoted string token. * - * @param srcChars the character array being tokenized - * @param start the first character of field - * @param len the length of the character array being tokenized - * @param workArea a temporary work area - * @param tokenList the list of parsed tokens - * @param quoteStart the start position of the matched quote, 0 if no quoting - * @param quoteLen the length of the matched quote, 0 if no quoting - * @return The starting position of the next field (the character - * immediately after the delimiter, or if end of string found, - * then the length of string + * @param srcChars the character array being tokenized. + * @param start the first character of field. + * @param len the length of the character array being tokenized. + * @param workArea a temporary work area. + * @param tokenList the list of parsed tokens. + * @param quoteStart the start position of the matched quote, 0 if no quoting. + * @param quoteLen the length of the matched quote, 0 if no quoting. + * @return The starting position of the next field (the character immediately after the delimiter, or if end of string found, then the length of string. */ private int readWithQuotes(final char[] srcChars, final int start, final int len, final StrBuilder workArea, final List tokenList, final int quoteStart, final int quoteLen) { @@ -843,7 +826,7 @@ private int readWithQuotes(final char[] srcChars, final int start, final int len /** * Unsupported ListIterator operation. * - * @throws UnsupportedOperationException always + * @throws UnsupportedOperationException always. */ @Override public void remove() { @@ -854,8 +837,9 @@ public void remove() { * Resets this tokenizer, forgetting all parsing and iteration already completed. *

    * This method allows the same tokenizer to be reused for the same String. + *

    * - * @return this, to enable chaining + * @return {@code this} instance. */ public StrTokenizer reset() { tokenPos = 0; @@ -864,12 +848,10 @@ public StrTokenizer reset() { } /** - * Reset this tokenizer, giving it a new input string to parse. - * In this manner you can re-use a tokenizer with the same settings - * on multiple input lines. + * Reset this tokenizer, giving it a new input string to parse. In this manner you can re-use a tokenizer with the same settings on multiple input lines. * - * @param input the new character array to tokenize, not cloned, null sets no text to parse - * @return this, to enable chaining + * @param input the new character array to tokenize, not cloned, null sets no text to parse. + * @return {@code this} instance. */ public StrTokenizer reset(final char[] input) { reset(); @@ -882,12 +864,10 @@ public StrTokenizer reset(final char[] input) { } /** - * Reset this tokenizer, giving it a new input string to parse. - * In this manner you can re-use a tokenizer with the same settings - * on multiple input lines. + * Reset this tokenizer, giving it a new input string to parse. In this manner you can re-use a tokenizer with the same settings on multiple input lines. * - * @param input the new string to tokenize, null sets no text to parse - * @return this, to enable chaining + * @param input the new string to tokenize, null sets no text to parse. + * @return {@code this} instance. */ public StrTokenizer reset(final String input) { reset(); @@ -901,8 +881,9 @@ public StrTokenizer reset(final String input) { /** * Unsupported ListIterator operation. + * * @param obj this parameter ignored. - * @throws UnsupportedOperationException always + * @throws UnsupportedOperationException Always thrown. */ @Override public void set(final String obj) { @@ -912,8 +893,8 @@ public void set(final String obj) { /** * Sets the field delimiter character. * - * @param delim the delimiter character to use - * @return this, to enable chaining + * @param delim the delimiter character to use. + * @return {@code this} instance. */ public StrTokenizer setDelimiterChar(final char delim) { return setDelimiterMatcher(StrMatcher.charMatcher(delim)); @@ -925,8 +906,8 @@ public StrTokenizer setDelimiterChar(final char delim) { * The delimiter is used to separate one token from another. *

    * - * @param delim the delimiter matcher to use - * @return this, to enable chaining + * @param delim the delimiter matcher to use. + * @return {@code this} instance. */ public StrTokenizer setDelimiterMatcher(final StrMatcher delim) { if (delim == null) { @@ -940,19 +921,18 @@ public StrTokenizer setDelimiterMatcher(final StrMatcher delim) { /** * Sets the field delimiter string. * - * @param delim the delimiter string to use - * @return this, to enable chaining + * @param delim the delimiter string to use. + * @return {@code this} instance. */ public StrTokenizer setDelimiterString(final String delim) { return setDelimiterMatcher(StrMatcher.stringMatcher(delim)); } /** - * Sets whether the tokenizer should return empty tokens as null. - * The default for this property is false. + * Sets whether the tokenizer should return empty tokens as null. The default for this property is false. * - * @param emptyAsNull whether empty tokens are returned as null - * @return this, to enable chaining + * @param emptyAsNull whether empty tokens are returned as null. + * @return {@code this} instance. */ public StrTokenizer setEmptyTokenAsNull(final boolean emptyAsNull) { this.emptyAsNull = emptyAsNull; @@ -962,12 +942,11 @@ public StrTokenizer setEmptyTokenAsNull(final boolean emptyAsNull) { /** * Sets the character to ignore. *

    - * This character is ignored when parsing the String, unless it is - * within a quoted region. + * This character is ignored when parsing the String, unless it is within a quoted region. *

    * - * @param ignored the ignored character to use - * @return this, to enable chaining + * @param ignored the ignored character to use. + * @return {@code this} instance. */ public StrTokenizer setIgnoredChar(final char ignored) { return setIgnoredMatcher(StrMatcher.charMatcher(ignored)); @@ -976,12 +955,11 @@ public StrTokenizer setIgnoredChar(final char ignored) { /** * Sets the matcher for characters to ignore. *

    - * These characters are ignored when parsing the String, unless they are - * within a quoted region. + * These characters are ignored when parsing the String, unless they are within a quoted region. *

    * - * @param ignored the ignored matcher to use, null ignored - * @return this, to enable chaining + * @param ignored the ignored matcher to use, null ignored. + * @return {@code this} instance. */ public StrTokenizer setIgnoredMatcher(final StrMatcher ignored) { if (ignored != null) { @@ -991,11 +969,10 @@ public StrTokenizer setIgnoredMatcher(final StrMatcher ignored) { } /** - * Sets whether the tokenizer should ignore and not return empty tokens. - * The default for this property is true. + * Sets whether the tokenizer should ignore and not return empty tokens. The default for this property is true. * - * @param ignoreEmptyTokens whether empty tokens are not returned - * @return this, to enable chaining + * @param ignoreEmptyTokens whether empty tokens are not returned. + * @return {@code this} instance. */ public StrTokenizer setIgnoreEmptyTokens(final boolean ignoreEmptyTokens) { this.ignoreEmptyTokens = ignoreEmptyTokens; @@ -1005,12 +982,11 @@ public StrTokenizer setIgnoreEmptyTokens(final boolean ignoreEmptyTokens) { /** * Sets the quote character to use. *

    - * The quote character is used to wrap data between the tokens. - * This enables delimiters to be entered as data. + * The quote character is used to wrap data between the tokens. This enables delimiters to be entered as data. *

    * - * @param quote the quote character to use - * @return this, to enable chaining + * @param quote the quote character to use. + * @return {@code this} instance. */ public StrTokenizer setQuoteChar(final char quote) { return setQuoteMatcher(StrMatcher.charMatcher(quote)); @@ -1019,12 +995,11 @@ public StrTokenizer setQuoteChar(final char quote) { /** * Sets the quote matcher to use. *

    - * The quote character is used to wrap data between the tokens. - * This enables delimiters to be entered as data. + * The quote character is used to wrap data between the tokens. This enables delimiters to be entered as data. *

    * - * @param quote the quote matcher to use, null ignored - * @return this, to enable chaining + * @param quote the quote matcher to use, null ignored. + * @return {@code this} instance. */ public StrTokenizer setQuoteMatcher(final StrMatcher quote) { if (quote != null) { @@ -1036,12 +1011,11 @@ public StrTokenizer setQuoteMatcher(final StrMatcher quote) { /** * Sets the matcher for characters to trim. *

    - * These characters are trimmed off on each side of the delimiter - * until the token or quote is found. + * These characters are trimmed off on each side of the delimiter until the token or quote is found. *

    * - * @param trimmer the trimmer matcher to use, null ignored - * @return this, to enable chaining + * @param trimmer the trimmer matcher to use, null ignored + * @return {@code this} instance. */ public StrTokenizer setTrimmerMatcher(final StrMatcher trimmer) { if (trimmer != null) { @@ -1053,7 +1027,7 @@ public StrTokenizer setTrimmerMatcher(final StrMatcher trimmer) { /** * Gets the number of tokens found in the String. * - * @return The number of matched tokens + * @return The number of matched tokens. */ public int size() { checkTokenized(); @@ -1063,25 +1037,21 @@ public int size() { /** * Internal method to performs the tokenization. *

    - * Most users of this class do not need to call this method. This method - * will be called automatically by other (public) methods when required. + * Most users of this class do not need to call this method. This method will be called automatically by other (public) methods when required. *

    *

    - * This method exists to allow subclasses to add code before or after the - * tokenization. For example, a subclass could alter the character array, - * offset or count to be parsed, or call the tokenizer multiple times on - * multiple strings. It is also be possible to filter the results. + * This method exists to allow subclasses to add code before or after the tokenization. For example, a subclass could alter the character array, offset or + * count to be parsed, or call the tokenizer multiple times on multiple strings. It is also be possible to filter the results. *

    *

    - * {@code StrTokenizer} will always pass a zero offset and a count - * equal to the length of the array to this method, however a subclass - * may pass other values, or even an entirely different array. + * {@code StrTokenizer} will always pass a zero offset and a count equal to the length of the array to this method, however a subclass may pass other + * values, or even an entirely different array. *

    * - * @param srcChars the character array being tokenized, may be null - * @param offset the start position within the character array, must be valid - * @param count the number of characters to tokenize, must be valid - * @return The modifiable list of String tokens, unmodifiable if null array or zero count + * @param srcChars the character array being tokenized, may be null. + * @param offset the start position within the character array, must be valid. + * @param count the number of characters to tokenize, must be valid. + * @return The modifiable list of String tokens, unmodifiable if null array or zero count. */ protected List tokenize(final char[] srcChars, final int offset, final int count) { if (srcChars == null || count == 0) { @@ -1107,7 +1077,7 @@ protected List tokenize(final char[] srcChars, final int offset, final i /** * Gets the String content that the tokenizer is parsing. * - * @return The string content being parsed + * @return The string content being parsed. */ @Override public String toString() { diff --git a/src/main/java/org/apache/commons/text/StringEscapeUtils.java b/src/main/java/org/apache/commons/text/StringEscapeUtils.java index 6fc8f27532..b9ee6e0e75 100644 --- a/src/main/java/org/apache/commons/text/StringEscapeUtils.java +++ b/src/main/java/org/apache/commons/text/StringEscapeUtils.java @@ -165,9 +165,8 @@ public int translate(final CharSequence input, final int index, final Writer wri /** * Translator object for escaping Java. * - * While {@link #escapeJava(String)} is the expected method of use, this - * object allows the Java escaping functionality to be used - * as the foundation for a custom translator. + * While {@link #escapeJava(String)} is the expected method of use, this object allows the Java escaping functionality to be used as the foundation for a + * custom translator. */ public static final CharSequenceTranslator ESCAPE_JAVA; static { @@ -184,9 +183,8 @@ public int translate(final CharSequence input, final int index, final Writer wri /** * Translator object for escaping EcmaScript/JavaScript. * - * While {@link #escapeEcmaScript(String)} is the expected method of use, this - * object allows the EcmaScript escaping functionality to be used - * as the foundation for a custom translator. + * While {@link #escapeEcmaScript(String)} is the expected method of use, this object allows the EcmaScript escaping functionality to be used as the + * foundation for a custom translator. */ public static final CharSequenceTranslator ESCAPE_ECMASCRIPT; static { @@ -205,9 +203,8 @@ public int translate(final CharSequence input, final int index, final Writer wri /** * Translator object for escaping Json. * - * While {@link #escapeJson(String)} is the expected method of use, this - * object allows the Json escaping functionality to be used - * as the foundation for a custom translator. + * While {@link #escapeJson(String)} is the expected method of use, this object allows the Json escaping functionality to be used as the foundation for a + * custom translator. */ public static final CharSequenceTranslator ESCAPE_JSON; static { @@ -225,9 +222,8 @@ public int translate(final CharSequence input, final int index, final Writer wri /** * Translator object for escaping XML 1.0. * - * While {@link #escapeXml10(String)} is the expected method of use, this - * object allows the XML escaping functionality to be used - * as the foundation for a custom translator. + * While {@link #escapeXml10(String)} is the expected method of use, this object allows the XML escaping functionality to be used as the foundation for a + * custom translator. */ public static final CharSequenceTranslator ESCAPE_XML10; static { @@ -480,7 +476,8 @@ public int translate(final CharSequence input, final int index, final Writer wri /** * Gets a {@link Builder}. - * @param translator the text translator + * + * @param translator the text translator. * @return {@link Builder} */ public static StringEscapeUtils.Builder builder(final CharSequenceTranslator translator) { @@ -488,23 +485,25 @@ public static StringEscapeUtils.Builder builder(final CharSequenceTranslator tra } /** - * Returns a {@code String} value for a CSV column enclosed in double quotes, - * if required. - * - *

    If the value contains a comma, newline or double quote, then the - * String value is returned enclosed in double quotes.

    + * Returns a {@code String} value for a CSV column enclosed in double quotes, if required. * - *

    Any double quote characters in the value are escaped with another double quote.

    + *

    + * If the value contains a comma, newline or double quote, then the String value is returned enclosed in double quotes. + *

    * - *

    If the value does not contain a comma, newline or double quote, then the - * String value is returned unchanged.

    + *

    + * Any double quote characters in the value are escaped with another double quote. + *

    * - * see Wikipedia and - * RFC 4180. + *

    + * If the value does not contain a comma, newline or double quote, then the String value is returned unchanged. + *

    + *

    + * See Wikipedia and RFC 4180. + *

    * - * @param input the input CSV column String, may be null - * @return The input String, enclosed in double quotes if the value contains a comma, - * newline or double quote, {@code null} if null string input + * @param input the input CSV column String, may be null. + * @return The input String, enclosed in double quotes if the value contains a comma, newline or double quote, {@code null} if null string input. */ public static String escapeCsv(final String input) { return ESCAPE_CSV.translate(input); @@ -513,32 +512,39 @@ public static String escapeCsv(final String input) { /** * Escapes the characters in a {@code String} using EcmaScript String rules. * - *

    Escapes any values it finds into their EcmaScript String form. - * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)

    + *

    + * Escapes any values it finds into their EcmaScript String form. Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) + *

    * - *

    So a tab becomes the characters {@code '\\'} and - * {@code 't'}.

    + *

    + * So a tab becomes the characters {@code '\\'} and {@code 't'}. + *

    * - *

    The only difference between Java strings and EcmaScript strings - * is that in EcmaScript, a single quote and forward-slash (/) are escaped.

    + *

    + * The only difference between Java strings and EcmaScript strings is that in EcmaScript, a single quote and forward-slash (/) are escaped. + *

    * - *

    Note that EcmaScript is best known by the JavaScript and ActionScript dialects.

    + *

    + * Note that EcmaScript is best known by the JavaScript and ActionScript dialects. + *

    + * + *

    + * Example: + *

    * - *

    Example:

    *
          * input string: He didn't say, "Stop!"
          * output string: He didn\'t say, \"Stop!\"
          * 
    + *

    + * Security Note. We only provide backslash escaping in this method. For example, {@code '\"'} has the output {@code '\\\"'} which could + * result in potential issues in the case where the string being escaped is being used in an HTML tag like {@code }. If you wish to have more rigorous string escaping, you - * may consider the - * ESAPI Libraries. - * Further, you can view the ESAPI GitHub Org. - * - * @param input String to escape values in, may be null - * @return String with escaped values, {@code null} if null string input + * @param input String to escape values in, may be null. + * @return String with escaped values, {@code null} if null string input. */ public static String escapeEcmaScript(final String input) { return ESCAPE_ECMASCRIPT.translate(input); @@ -549,8 +555,8 @@ public static String escapeEcmaScript(final String input) { * *

    Supports only the HTML 3.0 entities.

    * - * @param input the {@code String} to escape, may be null - * @return a new escaped {@code String}, {@code null} if null string input + * @param input the {@code String} to escape, may be null. + * @return a new escaped {@code String}, {@code null} if null string input. */ public static String escapeHtml3(final String input) { return ESCAPE_HTML3.translate(input); @@ -573,8 +579,8 @@ public static String escapeHtml3(final String input) { * Note that the commonly used apostrophe escape character (&apos;) * is not a legal entity and so is not supported).

    * - * @param input the {@code String} to escape, may be null - * @return a new escaped {@code String}, {@code null} if null string input + * @param input the {@code String} to escape, may be null. + * @return a new escaped {@code String}, {@code null} if null string input. * @see ISO Entities * @see HTML 3.2 Character Entities for ISO Latin-1 * @see HTML 4.0 Character entity references @@ -589,22 +595,29 @@ public static String escapeHtml4(final String input) { /** * Escapes the characters in a {@code String} using Java String rules. * - *

    Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)

    + *

    + * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) + *

    * - *

    So a tab becomes the characters {@code '\\'} and - * {@code 't'}.

    + *

    + * So a tab becomes the characters {@code '\\'} and {@code 't'}. + *

    * - *

    The only difference between Java strings and JavaScript strings - * is that in JavaScript, a single quote and forward-slash (/) are escaped.

    + *

    + * The only difference between Java strings and JavaScript strings is that in JavaScript, a single quote and forward-slash (/) are escaped. + *

    + * + *

    + * Example: + *

    * - *

    Example:

    *
          * input string: He didn't say, "Stop!"
          * output string: He didn't say, \"Stop!\"
          * 
    * - * @param input String to escape values in, may be null - * @return String with escaped values, {@code null} if null string input + * @param input String to escape values in, may be null. + * @return String with escaped values, {@code null} if null string input. */ public static String escapeJava(final String input) { return ESCAPE_JAVA.translate(input); @@ -613,25 +626,33 @@ public static String escapeJava(final String input) { /** * Escapes the characters in a {@code String} using Json String rules. * - *

    Escapes any values it finds into their Json String form. - * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)

    + *

    + * Escapes any values it finds into their Json String form. Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) + *

    * - *

    So a tab becomes the characters {@code '\\'} and - * {@code 't'}.

    + *

    + * So a tab becomes the characters {@code '\\'} and {@code 't'}. + *

    * - *

    The only difference between Java strings and Json strings - * is that in Json, forward-slash (/) is escaped.

    + *

    + * The only difference between Java strings and Json strings is that in Json, forward-slash (/) is escaped. + *

    * - *

    See http://www.ietf.org/rfc/rfc4627.txt for further details.

    + *

    + * See http://www.ietf.org/rfc/rfc4627.txt for further details. + *

    + * + *

    + * Example: + *

    * - *

    Example:

    *
          * input string: He didn't say, "Stop!"
          * output string: He didn't say, \"Stop!\"
          * 
    * - * @param input String to escape values in, may be null - * @return String with escaped values, {@code null} if null string input + * @param input String to escape values in, may be null. + * @return String with escaped values, {@code null} if null string input. */ public static String escapeJson(final String input) { return ESCAPE_JSON.translate(input); @@ -640,28 +661,34 @@ public static String escapeJson(final String input) { /** * Escapes the characters in a {@code String} using XML entities. * - *

    For example: {@code "bread" & "butter"} => - * {@code "bread" & "butter"}. + *

    + * For example: {@code "bread" & "butter"} => {@code "bread" & "butter"}. *

    * - *

    Note that XML 1.0 is a text-only format: it cannot represent control - * characters or unpaired Unicode surrogate code points, even after escaping. - * {@code escapeXml10} will remove characters that do not fit in the - * following ranges:

    + *

    + * Note that XML 1.0 is a text-only format: it cannot represent control characters or unpaired Unicode surrogate code points, even after escaping. + * {@code escapeXml10} will remove characters that do not fit in the following ranges: + *

    * - *

    {@code #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]}

    + *

    + * {@code #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]} + *

    * - *

    Though not strictly necessary, {@code escapeXml10} will escape - * characters in the following ranges:

    + *

    + * Though not strictly necessary, {@code escapeXml10} will escape characters in the following ranges: + *

    * - *

    {@code [#x7F-#x84] | [#x86-#x9F]}

    + *

    + * {@code [#x7F-#x84] | [#x86-#x9F]} + *

    * - *

    The returned string can be inserted into a valid XML 1.0 or XML 1.1 - * document. If you want to allow more non-text characters in an XML 1.1 - * document, use {@link #escapeXml11(String)}.

    + *

    + * The returned string can be inserted into a valid XML 1.0 or XML 1.1 document. If you want to allow more non-text characters in an XML 1.1 document, use + * {@link #escapeXml11(String)}. + *

    * - * @param input the {@code String} to escape, may be null - * @return a new escaped {@code String}, {@code null} if null string input + * @param input the {@code String} to escape, may be null. + * @return a new escaped {@code String}, {@code null} if null string input. * @see #unescapeXml(String) */ public static String escapeXml10(final String input) { @@ -671,26 +698,33 @@ public static String escapeXml10(final String input) { /** * Escapes the characters in a {@code String} using XML entities. * - *

    For example: {@code "bread" & "butter"} => - * {@code "bread" & "butter"}. + *

    + * For example: {@code "bread" & "butter"} => {@code "bread" & "butter"}. *

    * - *

    XML 1.1 can represent certain control characters, but it cannot represent - * the null byte or unpaired Unicode surrogate code points, even after escaping. - * {@code escapeXml11} will remove characters that do not fit in the following - * ranges:

    + *

    + * XML 1.1 can represent certain control characters, but it cannot represent the null byte or unpaired Unicode surrogate code points, even after escaping. + * {@code escapeXml11} will remove characters that do not fit in the following ranges: + *

    * - *

    {@code [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]}

    + *

    + * {@code [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]} + *

    * - *

    {@code escapeXml11} will escape characters in the following ranges:

    + *

    + * {@code escapeXml11} will escape characters in the following ranges: + *

    * - *

    {@code [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]}

    + *

    + * {@code [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]} + *

    * - *

    The returned string can be inserted into a valid XML 1.1 document. Do not - * use it for XML 1.0 documents.

    + *

    + * The returned string can be inserted into a valid XML 1.1 document. Do not use it for XML 1.0 documents. + *

    * - * @param input the {@code String} to escape, may be null - * @return a new escaped {@code String}, {@code null} if null string input + * @param input the {@code String} to escape, may be null. + * @return a new escaped {@code String}, {@code null} if null string input. * @see #unescapeXml(String) */ public static String escapeXml11(final String input) { @@ -700,19 +734,23 @@ public static String escapeXml11(final String input) { /** * Escapes the characters in a {@code String} using XSI rules. * - *

    Beware! In most cases you don't want to escape shell commands but use multi-argument - * methods provided by {@link ProcessBuilder} or {@link Runtime#exec(String[])} - * instead.

    + *

    + * Beware! In most cases you don't want to escape shell commands but use multi-argument methods provided by {@link ProcessBuilder} or + * {@link Runtime#exec(String[])} instead. + *

    + * + *

    + * Example: + *

    * - *

    Example:

    *
          * input string: He didn't say, "Stop!"
          * output string: He\ didn\'t\ say,\ \"Stop!\"
          * 
    * + * @param input String to escape values in, may be null. + * @return String with escaped values, {@code null} if null string input. * @see Shell Command Language - * @param input String to escape values in, may be null - * @return String with escaped values, {@code null} if null string input */ public static String escapeXSI(final String input) { return ESCAPE_XSI.translate(input); @@ -721,22 +759,22 @@ public static String escapeXSI(final String input) { /** * Returns a {@code String} value for an unescaped CSV column. * - *

    If the value is enclosed in double quotes, and contains a comma, newline - * or double quote, then quotes are removed. + *

    + * If the value is enclosed in double quotes, and contains a comma, newline or double quote, then quotes are removed. *

    * - *

    Any double quote escaped characters (a pair of double quotes) are unescaped - * to just one double quote.

    + *

    + * Any double quote escaped characters (a pair of double quotes) are unescaped to just one double quote. + *

    * - *

    If the value is not enclosed in double quotes, or is and does not contain a - * comma, newline or double quote, then the String value is returned unchanged.

    + *

    + * If the value is not enclosed in double quotes, or is and does not contain a comma, newline or double quote, then the String value is returned unchanged. + *

    * - * see Wikipedia and - * RFC 4180. + * see Wikipedia and RFC 4180. * - * @param input the input CSV column String, may be null - * @return The input String, with enclosing double quotes removed and embedded double - * quotes unescaped, {@code null} if null string input + * @param input the input CSV column String, may be null. + * @return The input String, with enclosing double quotes removed and embedded double quotes unescaped, {@code null} if null string input. */ public static String unescapeCsv(final String input) { return UNESCAPE_CSV.translate(input); @@ -745,57 +783,54 @@ public static String unescapeCsv(final String input) { /** * Unescapes any EcmaScript literals found in the {@code String}. * - *

    For example, it will turn a sequence of {@code '\'} and {@code 'n'} - * into a newline character, unless the {@code '\'} is preceded by another - * {@code '\'}.

    + *

    + * For example, it will turn a sequence of {@code '\'} and {@code 'n'} into a newline character, unless the {@code '\'} is preceded by another {@code '\'}. + *

    * + * @param input the {@code String} to unescape, may be null. + * @return A new unescaped {@code String}, {@code null} if null string input. * @see #unescapeJava(String) - * @param input the {@code String} to unescape, may be null - * @return A new unescaped {@code String}, {@code null} if null string input */ public static String unescapeEcmaScript(final String input) { return UNESCAPE_ECMASCRIPT.translate(input); } /** - * Unescapes a string containing entity escapes to a string - * containing the actual Unicode characters corresponding to the - * escapes. Supports only HTML 3.0 entities. + * Unescapes a string containing entity escapes to a string containing the actual Unicode characters corresponding to the escapes. Supports only HTML 3.0 + * entities. * - * @param input the {@code String} to unescape, may be null - * @return a new unescaped {@code String}, {@code null} if null string input + * @param input the {@code String} to unescape, may be null. + * @return a new unescaped {@code String}, {@code null} if null string input. */ public static String unescapeHtml3(final String input) { return UNESCAPE_HTML3.translate(input); } /** - * Unescapes a string containing entity escapes to a string - * containing the actual Unicode characters corresponding to the - * escapes. Supports HTML 4.0 entities. + * Unescapes a string containing entity escapes to a string containing the actual Unicode characters corresponding to the escapes. Supports HTML 4.0 + * entities. * - *

    For example, the string {@code "<Français>"} - * will become {@code ""}

    + *

    + * For example, the string {@code "<Français>"} will become {@code ""} + *

    * - *

    If an entity is unrecognized, it is left alone, and inserted - * verbatim into the result string. e.g. {@code ">&zzzz;x"} will - * become {@code ">&zzzz;x"}.

    + *

    + * If an entity is unrecognized, it is left alone, and inserted verbatim into the result string. e.g. {@code ">&zzzz;x"} will become {@code ">&zzzz;x"}. + *

    * - * @param input the {@code String} to unescape, may be null - * @return a new unescaped {@code String}, {@code null} if null string input + * @param input the {@code String} to unescape, may be null. + * @return a new unescaped {@code String}, {@code null} if null string input. */ public static String unescapeHtml4(final String input) { return UNESCAPE_HTML4.translate(input); } /** - * Unescapes any Java literals found in the {@code String}. - * For example, it will turn a sequence of {@code '\'} and - * {@code 'n'} into a newline character, unless the {@code '\'} - * is preceded by another {@code '\'}. + * Unescapes any Java literals found in the {@code String}. For example, it will turn a sequence of {@code '\'} and {@code 'n'} into a newline character, + * unless the {@code '\'} is preceded by another {@code '\'}. * - * @param input the {@code String} to unescape, may be null - * @return a new unescaped {@code String}, {@code null} if null string input + * @param input the {@code String} to unescape, may be null. + * @return a new unescaped {@code String}, {@code null} if null string input. */ public static String unescapeJava(final String input) { return UNESCAPE_JAVA.translate(input); @@ -804,31 +839,31 @@ public static String unescapeJava(final String input) { /** * Unescapes any Json literals found in the {@code String}. * - *

    For example, it will turn a sequence of {@code '\'} and {@code 'n'} - * into a newline character, unless the {@code '\'} is preceded by another - * {@code '\'}.

    + *

    + * For example, it will turn a sequence of {@code '\'} and {@code 'n'} into a newline character, unless the {@code '\'} is preceded by another {@code '\'}. + *

    * + * @param input the {@code String} to unescape, may be null. + * @return A new unescaped {@code String}, {@code null} if null string input. * @see #unescapeJava(String) - * @param input the {@code String} to unescape, may be null - * @return A new unescaped {@code String}, {@code null} if null string input */ public static String unescapeJson(final String input) { return UNESCAPE_JSON.translate(input); } /** - * Unescapes a string containing XML entity escapes to a string - * containing the actual Unicode characters corresponding to the - * escapes. + * Unescapes a string containing XML entity escapes to a string containing the actual Unicode characters corresponding to the escapes. * - *

    Supports only the five basic XML entities (gt, lt, quot, amp, apos). - * Does not support DTDs or external entities.

    + *

    + * Supports only the five basic XML entities (gt, lt, quot, amp, apos). Does not support DTDs or external entities. + *

    * - *

    Note that numerical \\u Unicode codes are unescaped to their respective - * Unicode characters. This may change in future releases.

    + *

    + * Note that numerical \\u Unicode codes are unescaped to their respective Unicode characters. This may change in future releases. + *

    * - * @param input the {@code String} to unescape, may be null - * @return a new unescaped {@code String}, {@code null} if null string input + * @param input the {@code String} to unescape, may be null. + * @return a new unescaped {@code String}, {@code null} if null string input. * @see #escapeXml10(String) * @see #escapeXml11(String) */ @@ -839,23 +874,28 @@ public static String unescapeXml(final String input) { /** * Unescapes the characters in a {@code String} using XSI rules. * + * @param input the {@code String} to unescape, may be null. + * @return a new unescaped {@code String}, {@code null} if null string input. * @see StringEscapeUtils#escapeXSI(String) - * @param input the {@code String} to unescape, may be null - * @return a new unescaped {@code String}, {@code null} if null string input */ public static String unescapeXSI(final String input) { return UNESCAPE_XSI.translate(input); } /** - * {@code StringEscapeUtils} instances should NOT be constructed in - * standard programming. + * {@code StringEscapeUtils} instances should NOT be constructed in standard programming. * - *

    Instead, the class should be used as:

    - *
    StringEscapeUtils.escapeJava("foo");
    + *

    + * Instead, the class should be used as: + *

    + * + *
    +     * StringEscapeUtils.escapeJava("foo");
    +     * 
    * - *

    This constructor is public to permit tools that require a JavaBean - * instance to operate.

    + *

    + * This constructor is public to permit tools that require a JavaBean instance to operate. + *

    */ public StringEscapeUtils() { } diff --git a/src/main/java/org/apache/commons/text/StringSubstitutor.java b/src/main/java/org/apache/commons/text/StringSubstitutor.java index 1cffd67d72..d794c2999c 100644 --- a/src/main/java/org/apache/commons/text/StringSubstitutor.java +++ b/src/main/java/org/apache/commons/text/StringSubstitutor.java @@ -505,8 +505,8 @@ public StringSubstitutor() { * Constructs a new initialized instance. Uses defaults for variable prefix and suffix and the escaping * character. * - * @param the type of the values in the map - * @param valueMap the map with the variables' values, may be null + * @param the type of the values in the map. + * @param valueMap the map with the variables' values, may be null. */ public StringSubstitutor(final Map valueMap) { this(StringLookupFactory.INSTANCE.mapStringLookup(valueMap), DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_ESCAPE); @@ -515,11 +515,11 @@ public StringSubstitutor(final Map valueMap) { /** * Constructs a new initialized instance. Uses a default escaping character. * - * @param the type of the values in the map - * @param valueMap the map with the variables' values, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @throws IllegalArgumentException if the prefix or suffix is null + * @param the type of the values in the map. + * @param valueMap the map with the variables' values, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StringSubstitutor(final Map valueMap, final String prefix, final String suffix) { this(StringLookupFactory.INSTANCE.mapStringLookup(valueMap), prefix, suffix, DEFAULT_ESCAPE); @@ -528,12 +528,12 @@ public StringSubstitutor(final Map valueMap, final String prefix, /** * Constructs a new initialized instance. * - * @param the type of the values in the map - * @param valueMap the map with the variables' values, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @param escape the escape character - * @throws IllegalArgumentException if the prefix or suffix is null + * @param the type of the values in the map. + * @param valueMap the map with the variables' values, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @param escape the escape character. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StringSubstitutor(final Map valueMap, final String prefix, final String suffix, final char escape) { @@ -543,13 +543,13 @@ public StringSubstitutor(final Map valueMap, final String prefix, /** * Constructs a new initialized instance. * - * @param the type of the values in the map - * @param valueMap the map with the variables' values, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @param escape the escape character - * @param valueDelimiter the variable default value delimiter, may be null - * @throws IllegalArgumentException if the prefix or suffix is null + * @param the type of the values in the map. + * @param valueMap the map with the variables' values, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @param escape the escape character. + * @param valueDelimiter the variable default value delimiter, may be null. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StringSubstitutor(final Map valueMap, final String prefix, final String suffix, final char escape, final String valueDelimiter) { @@ -568,11 +568,11 @@ public StringSubstitutor(final StringLookup variableResolver) { /** * Constructs a new initialized instance. * - * @param variableResolver the variable resolver, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @param escape the escape character - * @throws IllegalArgumentException if the prefix or suffix is null + * @param variableResolver the variable resolver, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @param escape the escape character. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StringSubstitutor(final StringLookup variableResolver, final String prefix, final String suffix, final char escape) { @@ -586,12 +586,12 @@ public StringSubstitutor(final StringLookup variableResolver, final String prefi /** * Constructs a new initialized instance. * - * @param variableResolver the variable resolver, may be null - * @param prefix the prefix for variables, not null - * @param suffix the suffix for variables, not null - * @param escape the escape character - * @param valueDelimiter the variable default value delimiter string, may be null - * @throws IllegalArgumentException if the prefix or suffix is null + * @param variableResolver the variable resolver, may be null. + * @param prefix the prefix for variables, not null. + * @param suffix the suffix for variables, not null. + * @param escape the escape character. + * @param valueDelimiter the variable default value delimiter string, may be null. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StringSubstitutor(final StringLookup variableResolver, final String prefix, final String suffix, final char escape, final String valueDelimiter) { @@ -606,10 +606,10 @@ public StringSubstitutor(final StringLookup variableResolver, final String prefi * Constructs a new initialized instance. * * @param variableResolver the variable resolver, may be null - * @param prefixMatcher the prefix for variables, not null - * @param suffixMatcher the suffix for variables, not null - * @param escape the escape character - * @throws IllegalArgumentException if the prefix or suffix is null + * @param prefixMatcher the prefix for variables, not null. + * @param suffixMatcher the suffix for variables, not null. + * @param escape the escape character. + * @throws IllegalArgumentException if the prefix or suffix is null. */ public StringSubstitutor(final StringLookup variableResolver, final StringMatcher prefixMatcher, final StringMatcher suffixMatcher, final char escape) { @@ -675,7 +675,7 @@ private void checkCyclicSubstitution(final String varName, final List pr /** * Returns the escape character. * - * @return The character used for escaping variable references + * @return The character used for escaping variable references. */ public char getEscapeChar() { return escapeChar; @@ -684,7 +684,7 @@ public char getEscapeChar() { /** * Gets the StringLookup that is used to lookup variables. * - * @return The StringLookup + * @return The StringLookup. */ public StringLookup getStringLookup() { return variableResolver; @@ -700,7 +700,7 @@ public StringLookup getStringLookup() { *

    * If it returns null, then the variable default value resolution is disabled. * - * @return The variable default value delimiter matcher in use, may be null + * @return The variable default value delimiter matcher in use, may be null. */ public StringMatcher getValueDelimiterMatcher() { return valueDelimiterMatcher; @@ -751,7 +751,7 @@ public StringMatcher getVariableSuffixMatcher() { * Hi Douglas ${surname} *

    * - * @return The substitution in variable values flag + * @return The substitution in variable values flag. */ public boolean isDisableSubstitutionInValues() { return disableSubstitutionInValues; @@ -760,7 +760,7 @@ public boolean isDisableSubstitutionInValues() { /** * Returns a flag whether substitution is done in variable names. * - * @return The substitution in variable names flag + * @return The substitution in variable names flag. */ public boolean isEnableSubstitutionInVariables() { return enableSubstitutionInVariables; @@ -769,7 +769,7 @@ public boolean isEnableSubstitutionInVariables() { /** * Returns a flag whether exception can be thrown upon undefined variable. * - * @return The fail on undefined variable flag + * @return The fail on undefined variable flag. */ public boolean isEnableUndefinedVariableException() { return failOnUndefinedVariable; @@ -778,7 +778,7 @@ public boolean isEnableUndefinedVariableException() { /** * Returns the flag controlling whether escapes are preserved during substitution. * - * @return The preserve escape flag + * @return The preserve escape flag. */ public boolean isPreserveEscapes() { return preserveEscapes; @@ -788,9 +788,9 @@ public boolean isPreserveEscapes() { * Replaces all the occurrences of variables with their matching values from the resolver using the given source * array as a template. The array is not altered by this method. * - * @param source the character array to replace in, not altered, null returns null - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the character array to replace in, not altered, null returns null. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public String replace(final char[] source) { if (source == null) { @@ -802,22 +802,20 @@ public String replace(final char[] source) { } /** - * Replaces all the occurrences of variables with their matching values from the resolver using the given source - * array as a template. The array is not altered by this method. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source array as a template. The array is not + * altered by this method. *

    - * Only the specified portion of the array will be processed. The rest of the array is not processed, and is not - * returned. + * Only the specified portion of the array will be processed. The rest of the array is not processed, and is not returned. *

    * - * @param source the character array to replace in, not altered, null returns null - * @param offset the start offset within the array, must be valid - * @param length the length within the array to be processed, must be valid - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception - * @throws StringIndexOutOfBoundsException if {@code offset} is not in the - * range {@code 0 <= offset <= chars.length} - * @throws StringIndexOutOfBoundsException if {@code length < 0} - * @throws StringIndexOutOfBoundsException if {@code offset + length > chars.length} + * @param source the character array to replace in, not altered, null returns null. + * @param offset the start offset within the array, must be valid. + * @param length the length within the array to be processed, must be valid. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. + * @throws StringIndexOutOfBoundsException if {@code offset} is not in the range {@code 0 <= offset <= chars.length}. + * @throws StringIndexOutOfBoundsException if {@code length < 0}. + * @throws StringIndexOutOfBoundsException if {@code offset + length > chars.length}. */ public String replace(final char[] source, final int offset, final int length) { if (source == null) { @@ -832,9 +830,9 @@ public String replace(final char[] source, final int offset, final int length) { * Replaces all the occurrences of variables with their matching values from the resolver using the given source as * a template. The source is not altered by this method. * - * @param source the buffer to use as a template, not changed, null returns null - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the buffer to use as a template, not changed, null returns null. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public String replace(final CharSequence source) { if (source == null) { @@ -851,11 +849,11 @@ public String replace(final CharSequence source) { * returned. *

    * - * @param source the buffer to use as a template, not changed, null returns null - * @param offset the start offset within the array, must be valid - * @param length the length within the array to be processed, must be valid - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the buffer to use as a template, not changed, null returns null. + * @param offset the start offset within the array, must be valid. + * @param length the length within the array to be processed, must be valid. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public String replace(final CharSequence source, final int offset, final int length) { if (source == null) { @@ -870,9 +868,9 @@ public String replace(final CharSequence source, final int offset, final int len * Replaces all the occurrences of variables in the given source object with their matching values from the * resolver. The input source object is converted to a string using {@code toString} and is not altered. * - * @param source the source to replace in, null returns null - * @return The result of the replace operation - * @throws IllegalArgumentException if a variable is not found and enableUndefinedVariableException is true + * @param source the source to replace in, null returns null. + * @return The result of the replace operation. + * @throws IllegalArgumentException if a variable is not found and enableUndefinedVariableException is true. */ public String replace(final Object source) { if (source == null) { @@ -887,9 +885,9 @@ public String replace(final Object source) { * Replaces all the occurrences of variables with their matching values from the resolver using the given source * string as a template. * - * @param source the string to replace in, null returns null - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the string to replace in, null returns null. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public String replace(final String source) { if (source == null) { @@ -903,22 +901,19 @@ public String replace(final String source) { } /** - * Replaces all the occurrences of variables with their matching values from the resolver using the given source - * string as a template. + * Replaces all the occurrences of variables with their matching values from the resolver using the given source string as a template. *

    - * Only the specified portion of the string will be processed. The rest of the string is not processed, and is not - * returned. + * Only the specified portion of the string will be processed. The rest of the string is not processed, and is not returned. *

    * - * @param source the string to replace in, null returns null - * @param offset the start offset within the source, must be valid - * @param length the length within the source to be processed, must be valid - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception - * @throws StringIndexOutOfBoundsException if {@code offset} is not in the - * range {@code 0 <= offset <= source.length()} - * @throws StringIndexOutOfBoundsException if {@code length < 0} - * @throws StringIndexOutOfBoundsException if {@code offset + length > source.length()} + * @param source the string to replace in, null returns null. + * @param offset the start offset within the source, must be valid. + * @param length the length within the source to be processed, must be valid. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. + * @throws StringIndexOutOfBoundsException if {@code offset} is not in the range {@code 0 <= offset <= source.length()}. + * @throws StringIndexOutOfBoundsException if {@code length < 0}. + * @throws StringIndexOutOfBoundsException if {@code offset + length > source.length()}. */ public String replace(final String source, final int offset, final int length) { if (source == null) { @@ -935,9 +930,9 @@ public String replace(final String source, final int offset, final int length) { * Replaces all the occurrences of variables with their matching values from the resolver using the given source * buffer as a template. The buffer is not altered by this method. * - * @param source the buffer to use as a template, not changed, null returns null - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the buffer to use as a template, not changed, null returns null. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public String replace(final StringBuffer source) { if (source == null) { @@ -956,11 +951,11 @@ public String replace(final StringBuffer source) { * returned. *

    * - * @param source the buffer to use as a template, not changed, null returns null - * @param offset the start offset within the source, must be valid - * @param length the length within the source to be processed, must be valid - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the buffer to use as a template, not changed, null returns null. + * @param offset the start offset within the source, must be valid. + * @param length the length within the source to be processed, must be valid. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public String replace(final StringBuffer source, final int offset, final int length) { if (source == null) { @@ -975,9 +970,9 @@ public String replace(final StringBuffer source, final int offset, final int len * Replaces all the occurrences of variables with their matching values from the resolver using the given source * builder as a template. The builder is not altered by this method. * - * @param source the builder to use as a template, not changed, null returns null - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the builder to use as a template, not changed, null returns null. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public String replace(final TextStringBuilder source) { if (source == null) { @@ -996,11 +991,11 @@ public String replace(final TextStringBuilder source) { * returned. *

    * - * @param source the builder to use as a template, not changed, null returns null - * @param offset the start offset within the source, must be valid - * @param length the length within the source to be processed, must be valid - * @return The result of the replace operation - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the builder to use as a template, not changed, null returns null. + * @param offset the start offset within the source, must be valid. + * @param length the length within the source to be processed, must be valid. + * @return The result of the replace operation. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public String replace(final TextStringBuilder source, final int offset, final int length) { if (source == null) { @@ -1015,7 +1010,7 @@ public String replace(final TextStringBuilder source, final int offset, final in * Replaces all the occurrences of variables within the given source buffer with their matching values from the * resolver. The buffer is updated with the result. * - * @param source the buffer to replace in, updated, null returns zero + * @param source the buffer to replace in, updated, null returns zero. * @return true if altered */ public boolean replaceIn(final StringBuffer source) { @@ -1033,11 +1028,11 @@ public boolean replaceIn(final StringBuffer source) { * not deleted. *

    * - * @param source the buffer to replace in, updated, null returns zero - * @param offset the start offset within the source, must be valid - * @param length the length within the source to be processed, must be valid - * @return true if altered - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the buffer to replace in, updated, null returns zero. + * @param offset the start offset within the source, must be valid. + * @param length the length within the source to be processed, must be valid. + * @return true if altered. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public boolean replaceIn(final StringBuffer source, final int offset, final int length) { if (source == null) { @@ -1055,8 +1050,8 @@ public boolean replaceIn(final StringBuffer source, final int offset, final int * Replaces all the occurrences of variables within the given source buffer with their matching values from the * resolver. The buffer is updated with the result. * - * @param source the buffer to replace in, updated, null returns zero - * @return true if altered + * @param source the buffer to replace in, updated, null returns zero. + * @return true if altered. */ public boolean replaceIn(final StringBuilder source) { if (source == null) { @@ -1073,11 +1068,11 @@ public boolean replaceIn(final StringBuilder source) { * not deleted. *

    * - * @param source the buffer to replace in, updated, null returns zero - * @param offset the start offset within the source, must be valid - * @param length the length within the source to be processed, must be valid - * @return true if altered - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the buffer to replace in, updated, null returns zero. + * @param offset the start offset within the source, must be valid. + * @param length the length within the source to be processed, must be valid. + * @return true if altered. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public boolean replaceIn(final StringBuilder source, final int offset, final int length) { if (source == null) { @@ -1095,9 +1090,9 @@ public boolean replaceIn(final StringBuilder source, final int offset, final int * Replaces all the occurrences of variables within the given source builder with their matching values from the * resolver. * - * @param source the builder to replace in, updated, null returns zero - * @return true if altered - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the builder to replace in, updated, null returns zero. + * @return true if altered. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public boolean replaceIn(final TextStringBuilder source) { if (source == null) { @@ -1114,11 +1109,11 @@ public boolean replaceIn(final TextStringBuilder source) { * not deleted. *

    * - * @param source the builder to replace in, null returns zero - * @param offset the start offset within the source, must be valid - * @param length the length within the source to be processed, must be valid - * @return true if altered - * @throws IllegalArgumentException if variable is not found when its allowed to throw exception + * @param source the builder to replace in, null returns zero. + * @param offset the start offset within the source, must be valid. + * @param length the length within the source to be processed, must be valid. + * @return true if altered. + * @throws IllegalArgumentException if variable is not found when its allowed to throw exception. */ public boolean replaceIn(final TextStringBuilder source, final int offset, final int length) { if (source == null) { @@ -1139,11 +1134,11 @@ public boolean replaceIn(final TextStringBuilder source, final int offset, final * {@link #getStringLookup()} with the variable's name as the key. *

    * - * @param variableName the name of the variable, not null - * @param buf the buffer where the substitution is occurring, not null - * @param startPos the start position of the variable including the prefix, valid - * @param endPos the end position of the variable including the suffix, valid - * @return The variable's value or null if the variable is unknown + * @param variableName the name of the variable, not null. + * @param buf the buffer where the substitution is occurring, not null. + * @param startPos the start position of the variable including the prefix, valid. + * @param endPos the end position of the variable including the suffix, valid. + * @return The variable's value or null if the variable is unknown. */ protected String resolveVariable(final String variableName, final TextStringBuilder buf, final int startPos, final int endPos) { @@ -1157,8 +1152,8 @@ protected String resolveVariable(final String variableName, final TextStringBuil /** * Sets a flag whether substitution is done in variable values (recursive). * - * @param disableSubstitutionInValues true if substitution in variable value are disabled - * @return this, to enable chaining + * @param disableSubstitutionInValues true if substitution in variable value are disabled. + * @return {@code this} instance. */ public StringSubstitutor setDisableSubstitutionInValues(final boolean disableSubstitutionInValues) { this.disableSubstitutionInValues = disableSubstitutionInValues; @@ -1170,8 +1165,8 @@ public StringSubstitutor setDisableSubstitutionInValues(final boolean disableSub * contain other variables which are processed first before the original variable is evaluated, e.g. * {@code ${jre-${java.version}}}. The default value is false. * - * @param enableSubstitutionInVariables the new value of the flag - * @return this, to enable chaining + * @param enableSubstitutionInVariables the new value of the flag. + * @return {@code this} instance. */ public StringSubstitutor setEnableSubstitutionInVariables(final boolean enableSubstitutionInVariables) { this.enableSubstitutionInVariables = enableSubstitutionInVariables; @@ -1181,8 +1176,8 @@ public StringSubstitutor setEnableSubstitutionInVariables(final boolean enableSu /** * Sets a flag whether exception should be thrown if any variable is undefined. * - * @param failOnUndefinedVariable true if exception should be thrown on undefined variable - * @return this, to enable chaining + * @param failOnUndefinedVariable true if exception should be thrown on undefined variable. + * @return {@code this} instance. */ public StringSubstitutor setEnableUndefinedVariableException(final boolean failOnUndefinedVariable) { this.failOnUndefinedVariable = failOnUndefinedVariable; @@ -1193,8 +1188,8 @@ public StringSubstitutor setEnableUndefinedVariableException(final boolean failO * Sets the escape character. If this character is placed before a variable reference in the source text, this * variable will be ignored. * - * @param escapeChar the escape character (0 for disabling escaping) - * @return this, to enable chaining + * @param escapeChar the escape character (0 for disabling escaping). + * @return {@code this} instance. */ public StringSubstitutor setEscapeChar(final char escapeChar) { this.escapeChar = escapeChar; @@ -1207,8 +1202,8 @@ public StringSubstitutor setEscapeChar(final char escapeChar) { * If set to false, the escape character is removed during substitution (e.g. {@code $${this-is-escaped}} * becomes {@code ${this-is-escaped}}). The default value is false * - * @param preserveEscapes true if escapes are to be preserved - * @return this, to enable chaining + * @param preserveEscapes true if escapes are to be preserved. + * @return {@code this} instance. */ public StringSubstitutor setPreserveEscapes(final boolean preserveEscapes) { this.preserveEscapes = preserveEscapes; @@ -1222,8 +1217,8 @@ public StringSubstitutor setPreserveEscapes(final boolean preserveEscapes) { * variable default value. This method allows a single character variable default value delimiter to be easily set. *

    * - * @param valueDelimiter the variable default value delimiter character to use - * @return this, to enable chaining + * @param valueDelimiter the variable default value delimiter character to use. + * @return {@code this} instance. */ public StringSubstitutor setValueDelimiter(final char valueDelimiter) { return setValueDelimiterMatcher(StringMatcherFactory.INSTANCE.charMatcher(valueDelimiter)); @@ -1240,8 +1235,8 @@ public StringSubstitutor setValueDelimiter(final char valueDelimiter) { * disabled. *

    * - * @param valueDelimiter the variable default value delimiter string to use, may be null or empty - * @return this, to enable chaining + * @param valueDelimiter the variable default value delimiter string to use, may be null or empty. + * @return {@code this} instance. */ public StringSubstitutor setValueDelimiter(final String valueDelimiter) { if (valueDelimiter == null || valueDelimiter.isEmpty()) { @@ -1262,8 +1257,8 @@ public StringSubstitutor setValueDelimiter(final String valueDelimiter) { * If the {@code valueDelimiterMatcher} is null, then the variable default value resolution becomes disabled. *

    * - * @param valueDelimiterMatcher variable default value delimiter matcher to use, may be null - * @return this, to enable chaining + * @param valueDelimiterMatcher variable default value delimiter matcher to use, may be null. + * @return {@code this} instance. */ public StringSubstitutor setValueDelimiterMatcher(final StringMatcher valueDelimiterMatcher) { this.valueDelimiterMatcher = valueDelimiterMatcher; @@ -1277,8 +1272,8 @@ public StringSubstitutor setValueDelimiterMatcher(final StringMatcher valueDelim * single character prefix to be easily set. *

    * - * @param prefix the prefix character to use - * @return this, to enable chaining + * @param prefix the prefix character to use. + * @return {@code this} instance. */ public StringSubstitutor setVariablePrefix(final char prefix) { return setVariablePrefixMatcher(StringMatcherFactory.INSTANCE.charMatcher(prefix)); @@ -1291,9 +1286,9 @@ public StringSubstitutor setVariablePrefix(final char prefix) { * string prefix to be easily set. *

    * - * @param prefix the prefix for variables, not null - * @return this, to enable chaining - * @throws IllegalArgumentException if the prefix is null + * @param prefix the prefix for variables, not null. + * @return {@code this} instance. + * @throws IllegalArgumentException if the prefix is null. */ public StringSubstitutor setVariablePrefix(final String prefix) { Validate.isTrue(prefix != null, "Variable prefix must not be null!"); @@ -1307,9 +1302,9 @@ public StringSubstitutor setVariablePrefix(final String prefix) { * expressed in terms of a matcher allowing advanced prefix matches. *

    * - * @param prefixMatcher the prefix matcher to use, null ignored - * @return this, to enable chaining - * @throws IllegalArgumentException if the prefix matcher is null + * @param prefixMatcher the prefix matcher to use, null ignored. + * @return {@code this} instance. + * @throws IllegalArgumentException if the prefix matcher is null. */ public StringSubstitutor setVariablePrefixMatcher(final StringMatcher prefixMatcher) { Validate.isTrue(prefixMatcher != null, "Variable prefix matcher must not be null!"); @@ -1320,8 +1315,8 @@ public StringSubstitutor setVariablePrefixMatcher(final StringMatcher prefixMatc /** * Sets the VariableResolver that is used to lookup variables. * - * @param variableResolver the VariableResolver - * @return this, to enable chaining + * @param variableResolver the VariableResolver. + * @return {@code this} instance. */ public StringSubstitutor setVariableResolver(final StringLookup variableResolver) { this.variableResolver = variableResolver; @@ -1335,8 +1330,8 @@ public StringSubstitutor setVariableResolver(final StringLookup variableResolver * single character suffix to be easily set. *

    * - * @param suffix the suffix character to use - * @return this, to enable chaining + * @param suffix the suffix character to use. + * @return {@code this} instance. */ public StringSubstitutor setVariableSuffix(final char suffix) { return setVariableSuffixMatcher(StringMatcherFactory.INSTANCE.charMatcher(suffix)); @@ -1349,9 +1344,9 @@ public StringSubstitutor setVariableSuffix(final char suffix) { * string suffix to be easily set. *

    * - * @param suffix the suffix for variables, not null - * @return this, to enable chaining - * @throws IllegalArgumentException if the suffix is null + * @param suffix the suffix for variables, not null. + * @return {@code this} instance. + * @throws IllegalArgumentException if the suffix is null. */ public StringSubstitutor setVariableSuffix(final String suffix) { Validate.isTrue(suffix != null, "Variable suffix must not be null!"); @@ -1365,9 +1360,9 @@ public StringSubstitutor setVariableSuffix(final String suffix) { * in terms of a matcher allowing advanced suffix matches. *

    * - * @param suffixMatcher the suffix matcher to use, null ignored - * @return this, to enable chaining - * @throws IllegalArgumentException if the suffix matcher is null + * @param suffixMatcher the suffix matcher to use, null ignored. + * @return {@code this} instance. + * @throws IllegalArgumentException if the suffix matcher is null. */ public StringSubstitutor setVariableSuffixMatcher(final StringMatcher suffixMatcher) { Validate.isTrue(suffixMatcher != null, "Variable suffix matcher must not be null!"); @@ -1386,10 +1381,10 @@ public StringSubstitutor setVariableSuffixMatcher(final StringMatcher suffixMatc * end. *

    * - * @param builder the string builder to substitute into, not null - * @param offset the start offset within the builder, must be valid - * @param length the length within the builder to be processed, must be valid - * @return true if altered + * @param builder the string builder to substitute into, not null. + * @param offset the start offset within the builder, must be valid. + * @param length the length within the builder to be processed, must be valid. + * @return true if altered. */ protected boolean substitute(final TextStringBuilder builder, final int offset, final int length) { return substitute(builder, offset, length, null).altered; @@ -1399,12 +1394,12 @@ protected boolean substitute(final TextStringBuilder builder, final int offset, * Recursive handler for multiple levels of interpolation. This is the main interpolation method, which resolves the * values of all variable references contained in the passed in text. * - * @param builder the string builder to substitute into, not null - * @param offset the start offset within the builder, must be valid - * @param length the length within the builder to be processed, must be valid - * @param priorVariables the stack keeping track of the replaced variables, may be null + * @param builder the string builder to substitute into, not null. + * @param offset the start offset within the builder, must be valid. + * @param length the length within the builder to be processed, must be valid. + * @param priorVariables the stack keeping track of the replaced variables, may be null. * @return The result. - * @throws IllegalArgumentException if variable is not found and
    isEnableUndefinedVariableException()==true
    + * @throws IllegalArgumentException if variable is not found and isEnableUndefinedVariableException() == true. * @since 1.9 */ private Result substitute(final TextStringBuilder builder, final int offset, final int length, diff --git a/src/main/java/org/apache/commons/text/StringTokenizer.java b/src/main/java/org/apache/commons/text/StringTokenizer.java index d2369af235..83b1c12fbb 100644 --- a/src/main/java/org/apache/commons/text/StringTokenizer.java +++ b/src/main/java/org/apache/commons/text/StringTokenizer.java @@ -132,33 +132,29 @@ private static StringTokenizer getCSVClone() { * You must call a "reset" method to set the string which you want to parse. *

    * - * @return a new tokenizer instance which parses Comma Separated Value strings + * @return a new tokenizer instance which parses Comma Separated Value strings. */ public static StringTokenizer getCSVInstance() { return getCSVClone(); } /** - * Gets a new tokenizer instance which parses Comma Separated Value strings initializing it with the given input. - * The default for CSV processing will be trim whitespace from both ends (which can be overridden with the - * setTrimmer method). + * Gets a new tokenizer instance which parses Comma Separated Value strings initializing it with the given input. The default for CSV processing will be + * trim whitespace from both ends (which can be overridden with the setTrimmer method). * - * @param input - * the text to parse - * @return a new tokenizer instance which parses Comma Separated Value strings + * @param input the text to parse. + * @return a new tokenizer instance which parses Comma Separated Value strings. */ public static StringTokenizer getCSVInstance(final char[] input) { return getCSVClone().reset(input); } /** - * Gets a new tokenizer instance which parses Comma Separated Value strings initializing it with the given input. - * The default for CSV processing will be trim whitespace from both ends (which can be overridden with the - * setTrimmer method). + * Gets a new tokenizer instance which parses Comma Separated Value strings initializing it with the given input. The default for CSV processing will be + * trim whitespace from both ends (which can be overridden with the setTrimmer method). * - * @param input - * the text to parse - * @return a new tokenizer instance which parses Comma Separated Value strings + * @param input the text to parse. + * @return a new tokenizer instance which parses Comma Separated Value strings. */ public static StringTokenizer getCSVInstance(final String input) { return getCSVClone().reset(input); @@ -187,11 +183,10 @@ public static StringTokenizer getTSVInstance() { } /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. The default for CSV processing will be - * trim whitespace from both ends (which can be overridden with the setTrimmer method). + * Gets a new tokenizer instance which parses Tab Separated Value strings. The default for CSV processing will be trim whitespace from both ends (which can + * be overridden with the setTrimmer method). * - * @param input - * the string to parse + * @param input the string to parse. * @return a new tokenizer instance which parses Tab Separated Value strings. */ public static StringTokenizer getTSVInstance(final char[] input) { @@ -199,11 +194,10 @@ public static StringTokenizer getTSVInstance(final char[] input) { } /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. The default for CSV processing will be - * trim whitespace from both ends (which can be overridden with the setTrimmer method). + * Gets a new tokenizer instance which parses Tab Separated Value strings. The default for CSV processing will be trim whitespace from both ends (which can + * be overridden with the setTrimmer method). * - * @param input - * the string to parse + * @param input the string to parse. * @return a new tokenizer instance which parses Tab Separated Value strings. */ public static StringTokenizer getTSVInstance(final String input) { @@ -238,8 +232,7 @@ public static StringTokenizer getTSVInstance(final String input) { private boolean ignoreEmptyTokens = true; /** - * Constructs a tokenizer splitting on space, tab, newline and form feed as per StringTokenizer, but with no text to - * tokenize. + * Constructs a tokenizer splitting on space, tab, newline and form feed as per StringTokenizer, but with no text to tokenize. *

    * This constructor is normally used with {@link #reset(String)}. *

    @@ -251,8 +244,7 @@ public StringTokenizer() { /** * Constructs a tokenizer splitting on space, tab, newline and form feed as per StringTokenizer. * - * @param input - * the string which is to be parsed, not cloned + * @param input the string which is to be parsed, not cloned. */ public StringTokenizer(final char[] input) { this.chars = input != null ? input.clone() : null; @@ -261,10 +253,8 @@ public StringTokenizer(final char[] input) { /** * Constructs a tokenizer splitting on the specified character. * - * @param input - * the string which is to be parsed, not cloned - * @param delim - * the field delimiter character + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter character. */ public StringTokenizer(final char[] input, final char delim) { this(input); @@ -272,15 +262,11 @@ public StringTokenizer(final char[] input, final char delim) { } /** - * Constructs a tokenizer splitting on the specified delimiter character and handling quotes using the specified - * quote character. + * Constructs a tokenizer splitting on the specified delimiter character and handling quotes using the specified quote character. * - * @param input - * the string which is to be parsed, not cloned - * @param delim - * the field delimiter character - * @param quote - * the field quoted string character + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter character. + * @param quote the field quoted string character. */ public StringTokenizer(final char[] input, final char delim, final char quote) { this(input, delim); @@ -290,10 +276,8 @@ public StringTokenizer(final char[] input, final char delim, final char quote) { /** * Constructs a tokenizer splitting on the specified string. * - * @param input - * the string which is to be parsed, not cloned - * @param delim - * the field delimiter string + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter string. */ public StringTokenizer(final char[] input, final String delim) { this(input); @@ -303,10 +287,8 @@ public StringTokenizer(final char[] input, final String delim) { /** * Constructs a tokenizer splitting using the specified delimiter matcher. * - * @param input - * the string which is to be parsed, not cloned - * @param delim - * the field delimiter matcher + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter matcher. */ public StringTokenizer(final char[] input, final StringMatcher delim) { this(input); @@ -314,15 +296,11 @@ public StringTokenizer(final char[] input, final StringMatcher delim) { } /** - * Constructs a tokenizer splitting using the specified delimiter matcher and handling quotes using the specified - * quote matcher. + * Constructs a tokenizer splitting using the specified delimiter matcher and handling quotes using the specified quote matcher. * - * @param input - * the string which is to be parsed, not cloned - * @param delim - * the field delimiter character - * @param quote - * the field quoted string character + * @param input the string which is to be parsed, not cloned. + * @param delim the field delimiter character. + * @param quote the field quoted string character. */ public StringTokenizer(final char[] input, final StringMatcher delim, final StringMatcher quote) { this(input, delim); @@ -332,8 +310,7 @@ public StringTokenizer(final char[] input, final StringMatcher delim, final Stri /** * Constructs a tokenizer splitting on space, tab, newline and form feed as per StringTokenizer. * - * @param input - * the string which is to be parsed + * @param input the string which is to be parsed. */ public StringTokenizer(final String input) { this.chars = input != null ? input.toCharArray() : null; @@ -342,10 +319,8 @@ public StringTokenizer(final String input) { /** * Constructs a tokenizer splitting on the specified delimiter character. * - * @param input - * the string which is to be parsed - * @param delim - * the field delimiter character + * @param input the string which is to be parsed. + * @param delim the field delimiter character. */ public StringTokenizer(final String input, final char delim) { this(input); @@ -353,15 +328,11 @@ public StringTokenizer(final String input, final char delim) { } /** - * Constructs a tokenizer splitting on the specified delimiter character and handling quotes using the specified - * quote character. + * Constructs a tokenizer splitting on the specified delimiter character and handling quotes using the specified quote character. * - * @param input - * the string which is to be parsed - * @param delim - * the field delimiter character - * @param quote - * the field quoted string character + * @param input the string which is to be parsed. + * @param delim the field delimiter character. + * @param quote the field quoted string character. */ public StringTokenizer(final String input, final char delim, final char quote) { this(input, delim); @@ -371,10 +342,8 @@ public StringTokenizer(final String input, final char delim, final char quote) { /** * Constructs a tokenizer splitting on the specified delimiter string. * - * @param input - * the string which is to be parsed - * @param delim - * the field delimiter string + * @param input the string which is to be parsed. + * @param delim the field delimiter string. */ public StringTokenizer(final String input, final String delim) { this(input); @@ -384,10 +353,8 @@ public StringTokenizer(final String input, final String delim) { /** * Constructs a tokenizer splitting using the specified delimiter matcher. * - * @param input - * the string which is to be parsed - * @param delim - * the field delimiter matcher + * @param input the string which is to be parsed. + * @param delim the field delimiter matcher. */ public StringTokenizer(final String input, final StringMatcher delim) { this(input); @@ -395,15 +362,11 @@ public StringTokenizer(final String input, final StringMatcher delim) { } /** - * Constructs a tokenizer splitting using the specified delimiter matcher and handling quotes using the specified - * quote matcher. + * Constructs a tokenizer splitting using the specified delimiter matcher and handling quotes using the specified quote matcher. * - * @param input - * the string which is to be parsed - * @param delim - * the field delimiter matcher - * @param quote - * the field quoted string matcher + * @param input the string which is to be parsed. + * @param delim the field delimiter matcher. + * @param quote the field quoted string matcher. */ public StringTokenizer(final String input, final StringMatcher delim, final StringMatcher quote) { this(input, delim); @@ -413,10 +376,8 @@ public StringTokenizer(final String input, final StringMatcher delim, final Stri /** * Unsupported ListIterator operation. * - * @param obj - * this parameter ignored. - * @throws UnsupportedOperationException - * always + * @param obj this parameter ignored. + * @throws UnsupportedOperationException always. */ @Override public void add(final String obj) { @@ -426,10 +387,8 @@ public void add(final String obj) { /** * Adds a token to a list, paying attention to the parameters we've set. * - * @param list - * the list to add to - * @param tok - * the token to add + * @param list the list to add to. + * @param tok the token to add. */ private void addToken(final List list, String tok) { if (tok == null || tok.isEmpty()) { @@ -450,7 +409,7 @@ private void checkTokenized() { if (tokens == null) { final List split; if (chars == null) { - // still call tokenize as subclass may do some work + // still call tokenize as subclass may do some work. split = tokenize(null, 0, 0); } else { split = tokenize(chars, 0, chars.length); @@ -460,8 +419,8 @@ private void checkTokenized() { } /** - * Creates a new instance of this Tokenizer. The new instance is reset so that it will be at the start of the token - * list. If a {@link CloneNotSupportedException} is caught, return {@code null}. + * Creates a new instance of this Tokenizer. The new instance is reset so that it will be at the start of the token list. If a + * {@link CloneNotSupportedException} is caught, return {@code null}. * * @return a new instance of this Tokenizer which has been reset. */ @@ -475,12 +434,10 @@ public Object clone() { } /** - * Creates a new instance of this Tokenizer. The new instance is reset so that it will be at the start of the token - * list. + * Creates a new instance of this Tokenizer. The new instance is reset so that it will be at the start of the token list. * * @return a new instance of this Tokenizer which has been reset. - * @throws CloneNotSupportedException - * if there is a problem cloning + * @throws CloneNotSupportedException if there is a problem cloning. */ Object cloneReset() throws CloneNotSupportedException { // this method exists to enable 100% test coverage @@ -495,7 +452,7 @@ Object cloneReset() throws CloneNotSupportedException { /** * Gets the String content that the tokenizer is parsing. * - * @return The string content being parsed + * @return The string content being parsed. */ public String getContent() { if (chars == null) { @@ -507,7 +464,7 @@ public String getContent() { /** * Gets the field delimiter matcher. * - * @return The delimiter matcher in use + * @return The delimiter matcher in use. */ public StringMatcher getDelimiterMatcher() { return this.delimMatcher; @@ -516,11 +473,10 @@ public StringMatcher getDelimiterMatcher() { /** * Gets the ignored character matcher. *

    - * These characters are ignored when parsing the String, unless they are within a quoted region. The default value - * is not to ignore anything. + * These characters are ignored when parsing the String, unless they are within a quoted region. The default value is not to ignore anything. *

    * - * @return The ignored matcher in use + * @return The ignored matcher in use. */ public StringMatcher getIgnoredMatcher() { return ignoredMatcher; @@ -529,11 +485,10 @@ public StringMatcher getIgnoredMatcher() { /** * Gets the quote matcher currently in use. *

    - * The quote character is used to wrap data between the tokens. This enables delimiters to be entered as data. The - * default value is '"' (double quote). + * The quote character is used to wrap data between the tokens. This enables delimiters to be entered as data. The default value is '"' (double quote). *

    * - * @return The quote matcher in use + * @return The quote matcher in use. */ public StringMatcher getQuoteMatcher() { return quoteMatcher; @@ -542,7 +497,7 @@ public StringMatcher getQuoteMatcher() { /** * Gets a copy of the full token list as an independent modifiable array. * - * @return The tokens as a String array + * @return The tokens as a String array. */ public String[] getTokenArray() { checkTokenized(); @@ -552,7 +507,7 @@ public String[] getTokenArray() { /** * Gets a copy of the full token list as an independent modifiable list. * - * @return The tokens as a String list + * @return The tokens as a String list. */ public List getTokenList() { checkTokenized(); @@ -562,11 +517,10 @@ public List getTokenList() { /** * Gets the trimmer character matcher. *

    - * These characters are trimmed off on each side of the delimiter until the token or quote is found. The default - * value is not to trim anything. + * These characters are trimmed off on each side of the delimiter until the token or quote is found. The default value is not to trim anything. *

    * - * @return The trimmer matcher in use + * @return The trimmer matcher in use. */ public StringMatcher getTrimmerMatcher() { return trimmerMatcher; @@ -575,7 +529,7 @@ public StringMatcher getTrimmerMatcher() { /** * Tests whether there are any more tokens. * - * @return true if there are more tokens + * @return true if there are more tokens. */ @Override public boolean hasNext() { @@ -586,7 +540,7 @@ public boolean hasNext() { /** * Tests whether there are any previous tokens that can be iterated to. * - * @return true if there are previous tokens + * @return true if there are previous tokens. */ @Override public boolean hasPrevious() { @@ -597,7 +551,7 @@ public boolean hasPrevious() { /** * Tests whether the tokenizer currently returns empty tokens as null. The default for this property is false. * - * @return true if empty tokens are returned as null + * @return true if empty tokens are returned as null. */ public boolean isEmptyTokenAsNull() { return this.emptyAsNull; @@ -606,7 +560,7 @@ public boolean isEmptyTokenAsNull() { /** * Tests whether the tokenizer currently ignores empty tokens. The default for this property is true. * - * @return true if empty tokens are not returned + * @return true if empty tokens are not returned. */ public boolean isIgnoreEmptyTokens() { return ignoreEmptyTokens; @@ -615,20 +569,14 @@ public boolean isIgnoreEmptyTokens() { /** * Tests if the characters at the index specified match the quote already matched in readNextToken(). * - * @param srcChars - * the character array being tokenized - * @param pos - * the position to check for a quote - * @param len - * the length of the character array being tokenized - * @param quoteStart - * the start position of the matched quote, 0 if no quoting - * @param quoteLen - * the length of the matched quote, 0 if no quoting - * @return true if a quote is matched - */ - private boolean isQuote(final char[] srcChars, final int pos, final int len, final int quoteStart, - final int quoteLen) { + * @param srcChars the character array being tokenized. + * @param pos the position to check for a quote. + * @param len the length of the character array being tokenized. + * @param quoteStart the start position of the matched quote, 0 if no quoting. + * @param quoteLen the length of the matched quote, 0 if no quoting. + * @return true if a quote is matched. + */ + private boolean isQuote(final char[] srcChars, final int pos, final int len, final int quoteStart, final int quoteLen) { for (int i = 0; i < quoteLen; i++) { if (pos + i >= len || srcChars[pos + i] != srcChars[quoteStart + i]) { return false; @@ -640,9 +588,8 @@ private boolean isQuote(final char[] srcChars, final int pos, final int len, fin /** * Gets the next token. * - * @return The next String token - * @throws NoSuchElementException - * if there are no more elements + * @return The next String token. + * @throws NoSuchElementException if there are no more elements. */ @Override public String next() { @@ -655,7 +602,7 @@ public String next() { /** * Gets the index of the next token to return. * - * @return The next token index + * @return The next token index. */ @Override public int nextIndex() { @@ -663,10 +610,10 @@ public int nextIndex() { } /** - * Gets the next token from the String. Equivalent to {@link #next()} except it returns null rather than throwing - * {@link NoSuchElementException} when no tokens remain. + * Gets the next token from the String. Equivalent to {@link #next()} except it returns null rather than throwing {@link NoSuchElementException} when no + * tokens remain. * - * @return The next sequential token, or null when no more tokens are found + * @return The next sequential token, or null when no more tokens are found. */ public String nextToken() { if (hasNext()) { @@ -678,7 +625,7 @@ public String nextToken() { /** * Gets the token previous to the last returned token. * - * @return The previous token + * @return The previous token. */ @Override public String previous() { @@ -691,7 +638,7 @@ public String previous() { /** * Gets the index of the previous token. * - * @return The previous token index + * @return The previous token index. */ @Override public int previousIndex() { @@ -701,7 +648,7 @@ public int previousIndex() { /** * Gets the previous token from the String. * - * @return The previous sequential token, or null when no more tokens are found + * @return The previous sequential token, or null when no more tokens are found. */ public String previousToken() { if (hasPrevious()) { @@ -713,18 +660,12 @@ public String previousToken() { /** * Reads character by character through the String to get the next token. * - * @param srcChars - * the character array being tokenized - * @param start - * the first character of field - * @param len - * the length of the character array being tokenized - * @param workArea - * a temporary work area - * @param tokenList - * the list of parsed tokens - * @return The starting position of the next field (the character immediately after the delimiter), or -1 if end of - * string found + * @param srcChars the character array being tokenized. + * @param start the first character of field. + * @param len the length of the character array being tokenized. + * @param workArea a temporary work area. + * @param tokenList the list of parsed tokens. + * @return The starting position of the next field (the character immediately after the delimiter), or -1 if end of string found. */ private int readNextToken(final char[] srcChars, int start, final int len, final TextStringBuilder workArea, final List tokenList) { @@ -764,22 +705,14 @@ private int readNextToken(final char[] srcChars, int start, final int len, final /** * Reads a possibly quoted string token. * - * @param srcChars - * the character array being tokenized - * @param start - * the first character of field - * @param len - * the length of the character array being tokenized - * @param workArea - * a temporary work area - * @param tokenList - * the list of parsed tokens - * @param quoteStart - * the start position of the matched quote, 0 if no quoting - * @param quoteLen - * the length of the matched quote, 0 if no quoting - * @return The starting position of the next field (the character immediately after the delimiter, or if end of - * string found, then the length of string + * @param srcChars the character array being tokenized. + * @param start the first character of field. + * @param len the length of the character array being tokenized. + * @param workArea a temporary work area. + * @param tokenList the list of parsed tokens. + * @param quoteStart the start position of the matched quote, 0 if no quoting. + * @param quoteLen the length of the matched quote, 0 if no quoting. + * @return The starting position of the next field (the character immediately after the delimiter, or if end of string found, then the length of string. */ private int readWithQuotes(final char[] srcChars, final int start, final int len, final TextStringBuilder workArea, final List tokenList, final int quoteStart, final int quoteLen) { @@ -864,8 +797,7 @@ private int readWithQuotes(final char[] srcChars, final int start, final int len /** * Throws {@link UnsupportedOperationException} for this unsupported ListIterator operation. * - * @throws UnsupportedOperationException - * always + * @throws UnsupportedOperationException Always thrown. */ @Override public void remove() { @@ -878,7 +810,7 @@ public void remove() { * This method allows the same tokenizer to be reused for the same String. *

    * - * @return this, to enable chaining + * @return {@code this} instance. */ public StringTokenizer reset() { tokenPos = 0; @@ -887,12 +819,10 @@ public StringTokenizer reset() { } /** - * Resets this tokenizer, giving it a new input string to parse. In this manner you can re-use a tokenizer with the - * same settings on multiple input lines. + * Resets this tokenizer, giving it a new input string to parse. In this manner you can re-use a tokenizer with the same settings on multiple input lines. * - * @param input - * the new character array to tokenize, not cloned, null sets no text to parse - * @return this, to enable chaining + * @param input the new character array to tokenize, not cloned, null sets no text to parse. + * @return {@code this} instance. */ public StringTokenizer reset(final char[] input) { reset(); @@ -901,12 +831,10 @@ public StringTokenizer reset(final char[] input) { } /** - * Resets this tokenizer, giving it a new input string to parse. In this manner you can re-use a tokenizer with the - * same settings on multiple input lines. + * Resets this tokenizer, giving it a new input string to parse. In this manner you can re-use a tokenizer with the same settings on multiple input lines. * - * @param input - * the new string to tokenize, null sets no text to parse - * @return this, to enable chaining + * @param input the new string to tokenize, null sets no text to parse. + * @return {@code this} instance. */ public StringTokenizer reset(final String input) { reset(); @@ -917,10 +845,8 @@ public StringTokenizer reset(final String input) { /** * Throws {@link UnsupportedOperationException} for this unsupported ListIterator operation. * - * @param obj - * this parameter ignored. - * @throws UnsupportedOperationException - * always + * @param obj this parameter ignored. + * @throws UnsupportedOperationException always. */ @Override public void set(final String obj) { @@ -930,9 +856,8 @@ public void set(final String obj) { /** * Sets the field delimiter character. * - * @param delim - * the delimiter character to use - * @return this, to enable chaining + * @param delim the delimiter character to use. + * @return {@code this} instance. */ public StringTokenizer setDelimiterChar(final char delim) { return setDelimiterMatcher(StringMatcherFactory.INSTANCE.charMatcher(delim)); @@ -944,9 +869,8 @@ public StringTokenizer setDelimiterChar(final char delim) { * The delimiter is used to separate one token from another. *

    * - * @param delim - * the delimiter matcher to use - * @return this, to enable chaining + * @param delim the delimiter matcher to use. + * @return {@code this} instance. */ public StringTokenizer setDelimiterMatcher(final StringMatcher delim) { this.delimMatcher = delim == null ? StringMatcherFactory.INSTANCE.noneMatcher() : delim; @@ -956,9 +880,8 @@ public StringTokenizer setDelimiterMatcher(final StringMatcher delim) { /** * Sets the field delimiter string. * - * @param delim - * the delimiter string to use - * @return this, to enable chaining + * @param delim the delimiter string to use. + * @return {@code this} instance. */ public StringTokenizer setDelimiterString(final String delim) { return setDelimiterMatcher(StringMatcherFactory.INSTANCE.stringMatcher(delim)); @@ -967,9 +890,8 @@ public StringTokenizer setDelimiterString(final String delim) { /** * Sets whether the tokenizer should return empty tokens as null. The default for this property is false. * - * @param emptyAsNull - * whether empty tokens are returned as null - * @return this, to enable chaining + * @param emptyAsNull whether empty tokens are returned as null. + * @return {@code this} instance. */ public StringTokenizer setEmptyTokenAsNull(final boolean emptyAsNull) { this.emptyAsNull = emptyAsNull; @@ -982,9 +904,8 @@ public StringTokenizer setEmptyTokenAsNull(final boolean emptyAsNull) { * This character is ignored when parsing the String, unless it is within a quoted region. *

    * - * @param ignored - * the ignored character to use - * @return this, to enable chaining + * @param ignored the ignored character to use. + * @return {@code this} instance. */ public StringTokenizer setIgnoredChar(final char ignored) { return setIgnoredMatcher(StringMatcherFactory.INSTANCE.charMatcher(ignored)); @@ -996,9 +917,8 @@ public StringTokenizer setIgnoredChar(final char ignored) { * These characters are ignored when parsing the String, unless they are within a quoted region. *

    * - * @param ignored - * the ignored matcher to use, null ignored - * @return this, to enable chaining + * @param ignored the ignored matcher to use, null ignored. + * @return {@code this} instance. */ public StringTokenizer setIgnoredMatcher(final StringMatcher ignored) { if (ignored != null) { @@ -1010,9 +930,8 @@ public StringTokenizer setIgnoredMatcher(final StringMatcher ignored) { /** * Sets whether the tokenizer should ignore and not return empty tokens. The default for this property is true. * - * @param ignoreEmptyTokens - * whether empty tokens are not returned - * @return this, to enable chaining + * @param ignoreEmptyTokens whether empty tokens are not returned. + * @return {@code this} instance. */ public StringTokenizer setIgnoreEmptyTokens(final boolean ignoreEmptyTokens) { this.ignoreEmptyTokens = ignoreEmptyTokens; @@ -1025,9 +944,8 @@ public StringTokenizer setIgnoreEmptyTokens(final boolean ignoreEmptyTokens) { * The quote character is used to wrap data between the tokens. This enables delimiters to be entered as data. *

    * - * @param quote - * the quote character to use - * @return this, to enable chaining + * @param quote the quote character to use. + * @return {@code this} instance. */ public StringTokenizer setQuoteChar(final char quote) { return setQuoteMatcher(StringMatcherFactory.INSTANCE.charMatcher(quote)); @@ -1039,9 +957,8 @@ public StringTokenizer setQuoteChar(final char quote) { * The quote character is used to wrap data between the tokens. This enables delimiters to be entered as data. *

    * - * @param quote - * the quote matcher to use, null ignored - * @return this, to enable chaining + * @param quote the quote matcher to use, null ignored. + * @return {@code this} instance. */ public StringTokenizer setQuoteMatcher(final StringMatcher quote) { if (quote != null) { @@ -1055,9 +972,8 @@ public StringTokenizer setQuoteMatcher(final StringMatcher quote) { *

    * These characters are trimmed off on each side of the delimiter until the token or quote is found. * - * @param trimmer - * the trimmer matcher to use, null ignored - * @return this, to enable chaining + * @param trimmer the trimmer matcher to use, null ignored. + * @return {@code this} instance. */ public StringTokenizer setTrimmerMatcher(final StringMatcher trimmer) { if (trimmer != null) { @@ -1069,7 +985,7 @@ public StringTokenizer setTrimmerMatcher(final StringMatcher trimmer) { /** * Gets the number of tokens found in the String. * - * @return The number of matched tokens + * @return The number of matched tokens. */ public int size() { checkTokenized(); @@ -1079,26 +995,21 @@ public int size() { /** * Internal method to performs the tokenization. *

    - * Most users of this class do not need to call this method. This method will be called automatically by other - * (public) methods when required. + * Most users of this class do not need to call this method. This method will be called automatically by other (public) methods when required. *

    *

    - * This method exists to allow subclasses to add code before or after the tokenization. For example, a subclass - * could alter the character array, offset or count to be parsed, or call the tokenizer multiple times on multiple - * strings. It is also be possible to filter the results. + * This method exists to allow subclasses to add code before or after the tokenization. For example, a subclass could alter the character array, offset or + * count to be parsed, or call the tokenizer multiple times on multiple strings. It is also be possible to filter the results. *

    *

    - * {@code StrTokenizer} will always pass a zero offset and a count equal to the length of the array to this - * method, however a subclass may pass other values, or even an entirely different array. + * {@code StrTokenizer} will always pass a zero offset and a count equal to the length of the array to this method, however a subclass may pass other + * values, or even an entirely different array. *

    * - * @param srcChars - * the character array being tokenized, may be null - * @param offset - * the start position within the character array, must be valid - * @param count - * the number of characters to tokenize, must be valid - * @return The modifiable list of String tokens, unmodifiable if null array or zero count + * @param srcChars the character array being tokenized, may be null. + * @param offset the start position within the character array, must be valid. + * @param count the number of characters to tokenize, must be valid. + * @return The modifiable list of String tokens, unmodifiable if null array or zero count. */ protected List tokenize(final char[] srcChars, final int offset, final int count) { if (srcChars == null || count == 0) { @@ -1107,12 +1018,10 @@ protected List tokenize(final char[] srcChars, final int offset, final i final TextStringBuilder buf = new TextStringBuilder(); final List tokenList = new ArrayList<>(); int pos = offset; - // loop around the entire buffer while (pos >= 0 && pos < count) { // find next token pos = readNextToken(srcChars, pos, count, buf, tokenList); - // handle case where end of string is a delimiter if (pos >= count) { addToken(tokenList, StringUtils.EMPTY); @@ -1124,7 +1033,7 @@ protected List tokenize(final char[] srcChars, final int offset, final i /** * Gets the String content that the tokenizer is parsing. * - * @return The string content being parsed + * @return The string content being parsed. */ @Override public String toString() { @@ -1133,5 +1042,4 @@ public String toString() { } return "StringTokenizer" + getTokenList(); } - } diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java index 40d53b1bf4..b3ea8585f7 100644 --- a/src/main/java/org/apache/commons/text/TextStringBuilder.java +++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java @@ -369,9 +369,9 @@ public TextStringBuilder() { * Constructs an instance from a reference to a character array. * * @param initialBuffer a reference to a character array, must not be null. - * @param length The length of the subarray to be used; must be non-negative and no larger than - * {@code initialBuffer.length}. The new builder's size will be set to {@code length}. - * @throws NullPointerException If {@code initialBuffer} is null. + * @param length The length of the subarray to be used; must be non-negative and no larger than {@code initialBuffer.length}. The new builder's size + * will be set to {@code length}. + * @throws NullPointerException If {@code initialBuffer} is null. * @throws IllegalArgumentException if {@code length} is bad. */ private TextStringBuilder(final char[] initialBuffer, final int length) { @@ -385,7 +385,7 @@ private TextStringBuilder(final char[] initialBuffer, final int length) { /** * Constructs an instance from a character sequence, allocating 32 extra characters for growth. * - * @param seq the string to copy, null treated as blank string + * @param seq the string to copy, null treated as blank string. * @since 1.9 */ public TextStringBuilder(final CharSequence seq) { @@ -398,7 +398,7 @@ public TextStringBuilder(final CharSequence seq) { /** * Constructs an instance with the specified initial capacity. * - * @param initialCapacity the initial capacity, zero or less will be converted to 32 + * @param initialCapacity the initial capacity, zero or less will be converted to 32. */ public TextStringBuilder(final int initialCapacity) { buffer = new char[initialCapacity <= 0 ? CAPACITY : initialCapacity]; @@ -407,7 +407,7 @@ public TextStringBuilder(final int initialCapacity) { /** * Constructs an instance from a string, allocating 32 extra characters for growth. * - * @param str the string to copy, null treated as blank string + * @param str the string to copy, null treated as blank string. */ public TextStringBuilder(final String str) { this(StringUtils.length(str) + CAPACITY); @@ -419,8 +419,8 @@ public TextStringBuilder(final String str) { /** * Appends a boolean value to the string builder. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder append(final boolean value) { if (value) { @@ -436,8 +436,8 @@ public TextStringBuilder append(final boolean value) { /** * Appends a char value to the string builder. * - * @param ch the value to append - * @return this, to enable chaining + * @param ch the value to append. + * @return {@code this} instance. */ @Override public TextStringBuilder append(final char ch) { @@ -450,8 +450,8 @@ public TextStringBuilder append(final char ch) { /** * Appends a char array to the string builder. Appending null will call {@link #appendNull()}. * - * @param chars the char array to append - * @return this, to enable chaining + * @param chars the char array to append. + * @return {@code this} instance. */ public TextStringBuilder append(final char[] chars) { if (chars == null) { @@ -470,14 +470,13 @@ public TextStringBuilder append(final char[] chars) { /** * Appends a char array to the string builder. Appending null will call {@link #appendNull()}. * - * @param chars the char array to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @throws StringIndexOutOfBoundsException if {@code startIndex} is not in the - * range {@code 0 <= startIndex <= chars.length} - * @throws StringIndexOutOfBoundsException if {@code length < 0} - * @throws StringIndexOutOfBoundsException if {@code startIndex + length > chars.length} + * @param chars the char array to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. + * @throws StringIndexOutOfBoundsException if {@code startIndex} is not in the range {@code 0 <= startIndex <= chars.length}. + * @throws StringIndexOutOfBoundsException if {@code length < 0}. + * @throws StringIndexOutOfBoundsException if {@code startIndex + length > chars.length}. */ public TextStringBuilder append(final char[] chars, final int startIndex, final int length) { if (chars == null) { @@ -501,8 +500,8 @@ public TextStringBuilder append(final char[] chars, final int startIndex, final /** * Appends the contents of a char buffer to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the char buffer to append - * @return this, to enable chaining + * @param str the char buffer to append. + * @return {@code this} instance. */ public TextStringBuilder append(final CharBuffer str) { return append(str, 0, StringUtils.length(str)); @@ -511,10 +510,10 @@ public TextStringBuilder append(final CharBuffer str) { /** * Appends the contents of a char buffer to this string builder. Appending null will call {@link #appendNull()}. * - * @param buf the char buffer to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining + * @param buf the char buffer to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. */ public TextStringBuilder append(final CharBuffer buf, final int startIndex, final int length) { if (buf == null) { @@ -541,8 +540,8 @@ public TextStringBuilder append(final CharBuffer buf, final int startIndex, fina /** * Appends a CharSequence to this string builder. Appending null will call {@link #appendNull()}. * - * @param seq the CharSequence to append - * @return this, to enable chaining + * @param seq the CharSequence to append. + * @return {@code this} instance. */ @Override public TextStringBuilder append(final CharSequence seq) { @@ -567,10 +566,10 @@ public TextStringBuilder append(final CharSequence seq) { /** * Appends part of a CharSequence to this string builder. Appending null will call {@link #appendNull()}. * - * @param seq the CharSequence to append - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid - * @return this, to enable chaining + * @param seq the CharSequence to append. + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid. + * @return {@code this} instance. */ @Override public TextStringBuilder append(final CharSequence seq, final int startIndex, final int endIndex) { @@ -589,8 +588,8 @@ public TextStringBuilder append(final CharSequence seq, final int startIndex, fi /** * Appends a double value to the string builder using {@code String.valueOf}. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder append(final double value) { return append(String.valueOf(value)); @@ -599,8 +598,8 @@ public TextStringBuilder append(final double value) { /** * Appends a float value to the string builder using {@code String.valueOf}. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder append(final float value) { return append(String.valueOf(value)); @@ -609,8 +608,8 @@ public TextStringBuilder append(final float value) { /** * Appends an int value to the string builder using {@code String.valueOf}. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder append(final int value) { return append(String.valueOf(value)); @@ -619,8 +618,8 @@ public TextStringBuilder append(final int value) { /** * Appends a long value to the string builder using {@code String.valueOf}. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder append(final long value) { return append(String.valueOf(value)); @@ -630,7 +629,7 @@ public TextStringBuilder append(final long value) { * Appends an object to this string builder. Appending null will call {@link #appendNull()}. * * @param obj the object to append. - * @return this, to enable chaining. + * @return {@code this} instance. */ public TextStringBuilder append(final Object obj) { if (obj == null) { @@ -645,8 +644,8 @@ public TextStringBuilder append(final Object obj) { /** * Appends a string to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the string to append - * @return this, to enable chaining + * @param str the string to append. + * @return {@code this} instance. */ public TextStringBuilder append(final String str) { return append(str, 0, StringUtils.length(str)); @@ -655,14 +654,13 @@ public TextStringBuilder append(final String str) { /** * Appends part of a string to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @throws StringIndexOutOfBoundsException if {@code startIndex} is not in the - * range {@code 0 <= startIndex <= str.length()} - * @throws StringIndexOutOfBoundsException if {@code length < 0} - * @throws StringIndexOutOfBoundsException if {@code startIndex + length > str.length()} + * @param str the string to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. + * @throws StringIndexOutOfBoundsException if {@code startIndex} is not in the range {@code 0 <= startIndex <= str.length()}. + * @throws StringIndexOutOfBoundsException if {@code length < 0}. + * @throws StringIndexOutOfBoundsException if {@code startIndex + length > str.length()}. */ public TextStringBuilder append(final String str, final int startIndex, final int length) { if (str == null) { @@ -686,9 +684,9 @@ public TextStringBuilder append(final String str, final int startIndex, final in /** * Calls {@link String#format(String, Object...)} and appends the result. * - * @param format the format string - * @param objs the objects to use in the format string - * @return {@code this} to enable chaining + * @param format the format string. + * @param objs the objects to use in the format string. + * @return {@code this} to enable chaining. * @see String#format(String, Object...) */ public TextStringBuilder append(final String format, final Object... objs) { @@ -698,8 +696,8 @@ public TextStringBuilder append(final String format, final Object... objs) { /** * Appends a string buffer to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the string buffer to append - * @return this, to enable chaining + * @param str the string buffer to append. + * @return {@code this} instance. */ public TextStringBuilder append(final StringBuffer str) { return append(str, 0, StringUtils.length(str)); @@ -708,10 +706,10 @@ public TextStringBuilder append(final StringBuffer str) { /** * Appends part of a string buffer to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining + * @param str the string to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. */ public TextStringBuilder append(final StringBuffer str, final int startIndex, final int length) { if (str == null) { @@ -735,8 +733,8 @@ public TextStringBuilder append(final StringBuffer str, final int startIndex, fi /** * Appends a StringBuilder to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the StringBuilder to append - * @return this, to enable chaining + * @param str the StringBuilder to append. + * @return {@code this} instance. */ public TextStringBuilder append(final StringBuilder str) { return append(str, 0, StringUtils.length(str)); @@ -745,10 +743,10 @@ public TextStringBuilder append(final StringBuilder str) { /** * Appends part of a StringBuilder to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the StringBuilder to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining + * @param str the StringBuilder to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. */ public TextStringBuilder append(final StringBuilder str, final int startIndex, final int length) { if (str == null) { @@ -772,8 +770,8 @@ public TextStringBuilder append(final StringBuilder str, final int startIndex, f /** * Appends another string builder to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the string builder to append - * @return this, to enable chaining + * @param str the string builder to append. + * @return {@code this} instance. */ public TextStringBuilder append(final TextStringBuilder str) { return append(str, 0, StringUtils.length(str)); @@ -782,10 +780,10 @@ public TextStringBuilder append(final TextStringBuilder str) { /** * Appends part of a string builder to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining + * @param str the string to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. */ public TextStringBuilder append(final TextStringBuilder str, final int startIndex, final int length) { if (str == null) { @@ -807,11 +805,11 @@ public TextStringBuilder append(final TextStringBuilder str, final int startInde } /** - * Appends each item in an iterable to the builder without any separators. Appending a null iterable will have no - * effect. Each object is appended using {@link #append(Object)}. + * Appends each item in an iterable to the builder without any separators. Appending a null iterable will have no effect. Each object is appended using + * {@link #append(Object)}. * - * @param iterable the iterable to append - * @return this, to enable chaining + * @param iterable the iterable to append. + * @return {@code this} instance. */ public TextStringBuilder appendAll(final Iterable iterable) { if (iterable != null) { @@ -821,11 +819,11 @@ public TextStringBuilder appendAll(final Iterable iterable) { } /** - * Appends each item in an iterator to the builder without any separators. Appending a null iterator will have no - * effect. Each object is appended using {@link #append(Object)}. + * Appends each item in an iterator to the builder without any separators. Appending a null iterator will have no effect. Each object is appended using + * {@link #append(Object)}. * - * @param it the iterator to append - * @return this, to enable chaining + * @param it the iterator to append. + * @return {@code this} instance. */ public TextStringBuilder appendAll(final Iterator it) { if (it != null) { @@ -835,12 +833,12 @@ public TextStringBuilder appendAll(final Iterator it) { } /** - * Appends each item in an array to the builder without any separators. Appending a null array will have no effect. - * Each object is appended using {@link #append(Object)}. + * Appends each item in an array to the builder without any separators. Appending a null array will have no effect. Each object is appended using + * {@link #append(Object)}. * - * @param the element type - * @param array the array to append - * @return this, to enable chaining + * @param the element type. + * @param array the array to append. + * @return {@code this} instance. */ public TextStringBuilder appendAll(@SuppressWarnings("unchecked") final T... array) { /* @@ -867,27 +865,26 @@ private void appendFalse(int index) { } /** - * Appends an object to the builder padding on the left to a fixed width. The {@code String.valueOf} of the - * {@code int} value is used. If the formatted value is larger than the length, the left hand side is lost. + * Appends an object to the builder padding on the left to a fixed width. The {@code String.valueOf} of the {@code int} value is used. If the formatted + * value is larger than the length, the left hand side is lost. * - * @param value the value to append - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining + * @param value the value to append. + * @param width the fixed field width, zero or negative has no effect. + * @param padChar the pad character to use. + * @return {@code this} instance. */ public TextStringBuilder appendFixedWidthPadLeft(final int value, final int width, final char padChar) { return appendFixedWidthPadLeft(String.valueOf(value), width, padChar); } /** - * Appends an object to the builder padding on the left to a fixed width. The {@code toString} of the object is - * used. If the object is larger than the length, the left hand side is lost. If the object is null, the null text - * value is used. + * Appends an object to the builder padding on the left to a fixed width. The {@code toString} of the object is used. If the object is larger than the + * length, the left hand side is lost. If the object is null, the null text value is used. * - * @param obj the object to append, null uses null text - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining + * @param obj the object to append, null uses null text. + * @param width the fixed field width, zero or negative has no effect. + * @param padChar the pad character to use. + * @return {@code this} instance. */ public TextStringBuilder appendFixedWidthPadLeft(final Object obj, final int width, final char padChar) { if (width > 0) { @@ -911,27 +908,26 @@ public TextStringBuilder appendFixedWidthPadLeft(final Object obj, final int wid } /** - * Appends an object to the builder padding on the right to a fixed length. The {@code String.valueOf} of the - * {@code int} value is used. If the object is larger than the length, the right hand side is lost. + * Appends an object to the builder padding on the right to a fixed length. The {@code String.valueOf} of the {@code int} value is used. If the object is + * larger than the length, the right hand side is lost. * - * @param value the value to append - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining + * @param value the value to append. + * @param width the fixed field width, zero or negative has no effect. + * @param padChar the pad character to use. + * @return {@code this} instance. */ public TextStringBuilder appendFixedWidthPadRight(final int value, final int width, final char padChar) { return appendFixedWidthPadRight(String.valueOf(value), width, padChar); } /** - * Appends an object to the builder padding on the right to a fixed length. The {@code toString} of the object is - * used. If the object is larger than the length, the right hand side is lost. If the object is null, null text - * value is used. + * Appends an object to the builder padding on the right to a fixed length. The {@code toString} of the object is used. If the object is larger than the + * length, the right hand side is lost. If the object is null, null text value is used. * - * @param obj the object to append, null uses null text - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining + * @param obj the object to append, null uses null text. + * @param width the fixed field width, zero or negative has no effect. + * @param padChar the pad character to use. + * @return {@code this} instance. */ public TextStringBuilder appendFixedWidthPadRight(final Object obj, final int width, final char padChar) { if (width > 0) { @@ -956,8 +952,8 @@ public TextStringBuilder appendFixedWidthPadRight(final Object obj, final int wi /** * Appends a boolean value followed by a new line to the string builder. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final boolean value) { return append(value).appendNewLine(); @@ -966,8 +962,8 @@ public TextStringBuilder appendln(final boolean value) { /** * Appends a char value followed by a new line to the string builder. * - * @param ch the value to append - * @return this, to enable chaining + * @param ch the value to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final char ch) { return append(ch).appendNewLine(); @@ -977,8 +973,8 @@ public TextStringBuilder appendln(final char ch) { * Appends a char array followed by a new line to the string builder. Appending null will call * {@link #appendNull()}. * - * @param chars the char array to append - * @return this, to enable chaining + * @param chars the char array to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final char[] chars) { return append(chars).appendNewLine(); @@ -988,10 +984,10 @@ public TextStringBuilder appendln(final char[] chars) { * Appends a char array followed by a new line to the string builder. Appending null will call * {@link #appendNull()}. * - * @param chars the char array to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining + * @param chars the char array to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. */ public TextStringBuilder appendln(final char[] chars, final int startIndex, final int length) { return append(chars, startIndex, length).appendNewLine(); @@ -1000,8 +996,8 @@ public TextStringBuilder appendln(final char[] chars, final int startIndex, fina /** * Appends a double value followed by a new line to the string builder using {@code String.valueOf}. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final double value) { return append(value).appendNewLine(); @@ -1010,8 +1006,8 @@ public TextStringBuilder appendln(final double value) { /** * Appends a float value followed by a new line to the string builder using {@code String.valueOf}. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final float value) { return append(value).appendNewLine(); @@ -1020,8 +1016,8 @@ public TextStringBuilder appendln(final float value) { /** * Appends an int value followed by a new line to the string builder using {@code String.valueOf}. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final int value) { return append(value).appendNewLine(); @@ -1030,8 +1026,8 @@ public TextStringBuilder appendln(final int value) { /** * Appends a long value followed by a new line to the string builder using {@code String.valueOf}. * - * @param value the value to append - * @return this, to enable chaining + * @param value the value to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final long value) { return append(value).appendNewLine(); @@ -1040,8 +1036,8 @@ public TextStringBuilder appendln(final long value) { /** * Appends an object followed by a new line to this string builder. Appending null will call {@link #appendNull()}. * - * @param obj the object to append - * @return this, to enable chaining + * @param obj the object to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final Object obj) { return append(obj).appendNewLine(); @@ -1050,8 +1046,8 @@ public TextStringBuilder appendln(final Object obj) { /** * Appends a string followed by a new line to this string builder. Appending null will call {@link #appendNull()}. * - * @param str the string to append - * @return this, to enable chaining + * @param str the string to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final String str) { return append(str).appendNewLine(); @@ -1061,10 +1057,10 @@ public TextStringBuilder appendln(final String str) { * Appends part of a string followed by a new line to this string builder. Appending null will call * {@link #appendNull()}. * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining + * @param str the string to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. */ public TextStringBuilder appendln(final String str, final int startIndex, final int length) { return append(str, startIndex, length).appendNewLine(); @@ -1073,9 +1069,9 @@ public TextStringBuilder appendln(final String str, final int startIndex, final /** * Calls {@link String#format(String, Object...)} and appends the result. * - * @param format the format string - * @param objs the objects to use in the format string - * @return {@code this} to enable chaining + * @param format the format string. + * @param objs the objects to use in the format string. + * @return {@code this} to enable chaining. * @see String#format(String, Object...) */ public TextStringBuilder appendln(final String format, final Object... objs) { @@ -1086,8 +1082,8 @@ public TextStringBuilder appendln(final String format, final Object... objs) { * Appends a string buffer followed by a new line to this string builder. Appending null will call * {@link #appendNull()}. * - * @param str the string buffer to append - * @return this, to enable chaining + * @param str the string buffer to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final StringBuffer str) { return append(str).appendNewLine(); @@ -1097,10 +1093,10 @@ public TextStringBuilder appendln(final StringBuffer str) { * Appends part of a string buffer followed by a new line to this string builder. Appending null will call * {@link #appendNull()}. * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining + * @param str the string to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. */ public TextStringBuilder appendln(final StringBuffer str, final int startIndex, final int length) { return append(str, startIndex, length).appendNewLine(); @@ -1110,8 +1106,8 @@ public TextStringBuilder appendln(final StringBuffer str, final int startIndex, * Appends a string builder followed by a new line to this string builder. Appending null will call * {@link #appendNull()}. * - * @param str the string builder to append - * @return this, to enable chaining + * @param str the string builder to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final StringBuilder str) { return append(str).appendNewLine(); @@ -1121,10 +1117,10 @@ public TextStringBuilder appendln(final StringBuilder str) { * Appends part of a string builder followed by a new line to this string builder. Appending null will call * {@link #appendNull()}. * - * @param str the string builder to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining + * @param str the string builder to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. */ public TextStringBuilder appendln(final StringBuilder str, final int startIndex, final int length) { return append(str, startIndex, length).appendNewLine(); @@ -1134,8 +1130,8 @@ public TextStringBuilder appendln(final StringBuilder str, final int startIndex, * Appends another string builder followed by a new line to this string builder. Appending null will call * {@link #appendNull()}. * - * @param str the string builder to append - * @return this, to enable chaining + * @param str the string builder to append. + * @return {@code this} instance. */ public TextStringBuilder appendln(final TextStringBuilder str) { return append(str).appendNewLine(); @@ -1145,10 +1141,10 @@ public TextStringBuilder appendln(final TextStringBuilder str) { * Appends part of a string builder followed by a new line to this string builder. Appending null will call * {@link #appendNull()}. * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining + * @param str the string to append. + * @param startIndex the start index, inclusive, must be valid. + * @param length the length to append, must be valid. + * @return {@code this} instance. */ public TextStringBuilder appendln(final TextStringBuilder str, final int startIndex, final int length) { return append(str, startIndex, length).appendNewLine(); @@ -1164,7 +1160,7 @@ public TextStringBuilder appendln(final TextStringBuilder str, final int startIn * endings even when on Windows. *

    * - * @return this + * @return {@code this} instance. * @see #getNewLineText() * @see #setNewLineText(String) */ @@ -1175,7 +1171,7 @@ public TextStringBuilder appendNewLine() { /** * Appends the text representing {@code null} to this string builder. * - * @return this, to enable chaining. + * @return {@code this} instance. */ public TextStringBuilder appendNull() { return nullText != null ? append(nullText) : this; @@ -1184,9 +1180,9 @@ public TextStringBuilder appendNull() { /** * Appends the pad character to the builder the specified number of times. * - * @param length the length to append, negative means no append - * @param padChar the character to append - * @return this, to enable chaining + * @param length the length to append, negative means no append. + * @param padChar the character to append. + * @return {@code this} instance. */ public TextStringBuilder appendPadding(final int length, final char padChar) { if (length >= 0) { @@ -1215,22 +1211,23 @@ public TextStringBuilder appendPadding(final int length, final char padChar) { * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}. *

    * - * @param separator the separator to use - * @return this, to enable chaining + * @param separator the separator to use. + * @return {@code this} instance. */ public TextStringBuilder appendSeparator(final char separator) { return isEmpty() ? this : append(separator); } /** - * Appends one of both separators to the builder If the builder is currently empty it will append the - * defaultIfEmpty-separator Otherwise it will append the standard-separator - * + * Appends one of both separators to the builder If the builder is currently empty it will append the defaultIfEmpty-separator Otherwise it will append the + * standard-separator + *

    * The separator is appended using {@link #append(char)}. + *

    * - * @param standard the separator if builder is not empty - * @param defaultIfEmpty the separator if builder is empty - * @return this, to enable chaining + * @param standard the separator if builder is not empty. + * @param defaultIfEmpty the separator if builder is empty. + * @return {@code this} instance. */ public TextStringBuilder appendSeparator(final char standard, final char defaultIfEmpty) { return append(isEmpty() ? defaultIfEmpty : standard); @@ -1254,9 +1251,9 @@ public TextStringBuilder appendSeparator(final char standard, final char default * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}. *

    * - * @param separator the separator to use - * @param loopIndex the loop index - * @return this, to enable chaining + * @param separator the separator to use. + * @param loopIndex the loop index. + * @return {@code this} instance. */ public TextStringBuilder appendSeparator(final char separator, final int loopIndex) { return loopIndex > 0 ? append(separator) : this; @@ -1280,8 +1277,8 @@ public TextStringBuilder appendSeparator(final char separator, final int loopInd * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}. *

    * - * @param separator the separator to use, null means no separator - * @return this, to enable chaining + * @param separator the separator to use, null means no separator. + * @return {@code this} instance. */ public TextStringBuilder appendSeparator(final String separator) { return appendSeparator(separator, null); @@ -1305,9 +1302,9 @@ public TextStringBuilder appendSeparator(final String separator) { * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}. *

    * - * @param separator the separator to use, null means no separator - * @param loopIndex the loop index - * @return this, to enable chaining + * @param separator the separator to use, null means no separator. + * @param loopIndex the loop index. + * @return {@code this} instance. */ public TextStringBuilder appendSeparator(final String separator, final int loopIndex) { return separator != null && loopIndex > 0 ? append(separator) : this; @@ -1336,9 +1333,9 @@ public TextStringBuilder appendSeparator(final String separator, final int loopI * selectClause.append(whereClause) *
    * - * @param standard the separator if builder is not empty, null means no separator - * @param defaultIfEmpty the separator if builder is empty, null means no separator - * @return this, to enable chaining + * @param standard the separator if builder is not empty, null means no separator. + * @param defaultIfEmpty the separator if builder is empty, null means no separator. + * @return {@code this} instance. */ public TextStringBuilder appendSeparator(final String standard, final String defaultIfEmpty) { final String str = isEmpty() ? defaultIfEmpty : standard; @@ -1351,7 +1348,7 @@ public TextStringBuilder appendSeparator(final String standard, final String def * This method tries to avoid doing any extra copies of contents. *

    * - * @param appendable the appendable to append data to + * @param appendable the appendable to append data to. * @throws IOException if an I/O error occurs. * @see #readFrom(Readable) */ @@ -1382,9 +1379,9 @@ private void appendTrue(int index) { * Appends an iterable placing separators between each value, but not before the first or after the last. Appending * a null iterable will have no effect. Each object is appended using {@link #append(Object)}. * - * @param iterable the iterable to append - * @param separator the separator to use, null means no separator - * @return this, to enable chaining + * @param iterable the iterable to append. + * @param separator the separator to use, null means no separator. + * @return {@code this} instance. */ public TextStringBuilder appendWithSeparators(final Iterable iterable, final String separator) { if (iterable != null) { @@ -1397,9 +1394,9 @@ public TextStringBuilder appendWithSeparators(final Iterable iterable, final * Appends an iterator placing separators between each value, but not before the first or after the last. Appending * a null iterator will have no effect. Each object is appended using {@link #append(Object)}. * - * @param it the iterator to append - * @param separator the separator to use, null means no separator - * @return this, to enable chaining + * @param it the iterator to append. + * @param separator the separator to use, null means no separator. + * @return {@code this} instance. */ public TextStringBuilder appendWithSeparators(final Iterator it, final String separator) { if (it != null) { @@ -1418,9 +1415,9 @@ public TextStringBuilder appendWithSeparators(final Iterator it, final String * Appends an array placing separators between each value, but not before the first or after the last. Appending a * null array will have no effect. Each object is appended using {@link #append(Object)}. * - * @param array the array to append - * @param separator the separator to use, null means no separator - * @return this, to enable chaining + * @param array the array to append. + * @param separator the separator to use, null means no separator. + * @return {@code this} instance. */ public TextStringBuilder appendWithSeparators(final Object[] array, final String separator) { if (array != null && array.length > 0) { @@ -1450,7 +1447,7 @@ public TextStringBuilder appendWithSeparators(final Object[] array, final String * The returned reader supports marking, and ignores the flush method. *

    * - * @return a reader that reads from this builder + * @return a reader that reads from this builder. */ public Reader asReader() { return new TextStringBuilderReader(); @@ -1489,7 +1486,7 @@ public Reader asReader() { * break the link with the builder. *

    * - * @return a tokenizer that is linked to this builder + * @return a tokenizer that is linked to this builder. */ public StringTokenizer asTokenizer() { return new TextStringBuilderTokenizer(); @@ -1513,7 +1510,7 @@ public StringTokenizer asTokenizer() { * The returned writer ignores the close and flush methods. *

    * - * @return a writer that populates this builder + * @return a writer that populates this builder. */ public Writer asWriter() { return new TextStringBuilderWriter(); @@ -1522,7 +1519,7 @@ public Writer asWriter() { /** * Converts this instance to a String. * - * @return This instance as a String + * @return This instance as a String. * @see #toString() * @deprecated Use {@link #get()}. */ @@ -1535,7 +1532,7 @@ public String build() { /** * Gets the current size of the internal character array buffer. * - * @return The capacity + * @return The capacity. */ public int capacity() { return buffer.length; @@ -1544,11 +1541,11 @@ public int capacity() { /** * Gets the character at the specified index. * + * @param index the index to retrieve, must be valid. + * @return The character at the index. + * @throws IndexOutOfBoundsException if the index is invalid. * @see #setCharAt(int, char) * @see #deleteCharAt(int) - * @param index the index to retrieve, must be valid - * @return The character at the index - * @throws IndexOutOfBoundsException if the index is invalid */ @Override public char charAt(final int index) { @@ -1567,7 +1564,7 @@ public char charAt(final int index) { * Collections. *

    * - * @return this, to enable chaining + * @return {@code this} instance. */ public TextStringBuilder clear() { size = 0; @@ -1577,8 +1574,8 @@ public TextStringBuilder clear() { /** * Tests if the string builder contains the specified char. * - * @param ch the character to find - * @return true if the builder contains the character + * @param ch the character to find. + * @return true if the builder contains the character. */ public boolean contains(final char ch) { final char[] thisBuf = buffer; @@ -1593,8 +1590,8 @@ public boolean contains(final char ch) { /** * Tests if the string builder contains the specified string. * - * @param str the string to find - * @return true if the builder contains the string + * @param str the string to find. + * @return true if the builder contains the string. */ public boolean contains(final String str) { return indexOf(str, 0) >= 0; @@ -1607,8 +1604,8 @@ public boolean contains(final String str) { * the character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @return true if the matcher finds a match in the builder + * @param matcher the matcher to use, null returns -1. + * @return true if the matcher finds a match in the builder. */ public boolean contains(final StringMatcher matcher) { return indexOf(matcher, 0) >= 0; @@ -1617,10 +1614,10 @@ public boolean contains(final StringMatcher matcher) { /** * Deletes the characters between the two specified indices. * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder delete(final int startIndex, final int endIndex) { final int actualEndIndex = validateRange(startIndex, endIndex); @@ -1634,8 +1631,8 @@ public TextStringBuilder delete(final int startIndex, final int endIndex) { /** * Deletes the character wherever it occurs in the builder. * - * @param ch the character to delete - * @return this, to enable chaining + * @param ch the character to delete. + * @return {@code this} instance. */ public TextStringBuilder deleteAll(final char ch) { for (int i = 0; i < size; i++) { @@ -1657,8 +1654,8 @@ public TextStringBuilder deleteAll(final char ch) { /** * Deletes the string wherever it occurs in the builder. * - * @param str the string to delete, null causes no action - * @return this, to enable chaining + * @param str the string to delete, null causes no action. + * @return {@code this} instance. */ public TextStringBuilder deleteAll(final String str) { final int len = str == null ? 0 : str.length(); @@ -1679,8 +1676,8 @@ public TextStringBuilder deleteAll(final String str) { * occurrences where the character 'a' is followed by a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @return this, to enable chaining + * @param matcher the matcher to use to find the deletion, null causes no action. + * @return {@code this} instance. */ public TextStringBuilder deleteAll(final StringMatcher matcher) { return replace(matcher, null, 0, size, -1); @@ -1689,11 +1686,11 @@ public TextStringBuilder deleteAll(final StringMatcher matcher) { /** * Deletes the character at the specified index. * + * @param index the index to delete. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. * @see #charAt(int) * @see #setCharAt(int, char) - * @param index the index to delete - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid */ public TextStringBuilder deleteCharAt(final int index) { validateIndex(index); @@ -1704,8 +1701,8 @@ public TextStringBuilder deleteCharAt(final int index) { /** * Deletes the character wherever it occurs in the builder. * - * @param ch the character to delete - * @return this, to enable chaining + * @param ch the character to delete. + * @return {@code this} instance. */ public TextStringBuilder deleteFirst(final char ch) { for (int i = 0; i < size; i++) { @@ -1720,8 +1717,8 @@ public TextStringBuilder deleteFirst(final char ch) { /** * Deletes the string wherever it occurs in the builder. * - * @param str the string to delete, null causes no action - * @return this, to enable chaining + * @param str the string to delete, null causes no action. + * @return {@code this} instance. */ public TextStringBuilder deleteFirst(final String str) { final int len = str == null ? 0 : str.length(); @@ -1741,8 +1738,8 @@ public TextStringBuilder deleteFirst(final String str) { * the character 'a' is followed by a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @return this, to enable chaining + * @param matcher the matcher to use to find the deletion, null causes no action. + * @return {@code this} instance. */ public TextStringBuilder deleteFirst(final StringMatcher matcher) { return replace(matcher, null, 0, size, 1); @@ -1751,10 +1748,10 @@ public TextStringBuilder deleteFirst(final StringMatcher matcher) { /** * Internal method to delete a range without validation. * - * @param startIndex the start index, must be valid - * @param endIndex the end index (exclusive), must be valid - * @param len the length, must be valid - * @throws IndexOutOfBoundsException if any index is invalid + * @param startIndex the start index, must be valid. + * @param endIndex the end index (exclusive), must be valid. + * @param len the length, must be valid. + * @throws IndexOutOfBoundsException if any index is invalid. */ private void deleteImpl(final int startIndex, final int endIndex, final int len) { System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex); @@ -1764,12 +1761,12 @@ private void deleteImpl(final int startIndex, final int endIndex, final int len) /** * Gets the character at the specified index before deleting it. * - * @see #charAt(int) - * @see #deleteCharAt(int) * @param index the index to retrieve, must be valid * @return The character at the index * @throws IndexOutOfBoundsException if the index is invalid * @since 1.9 + * @see #charAt(int) + * @see #deleteCharAt(int) */ public char drainChar(final int index) { validateIndex(index); @@ -1806,8 +1803,8 @@ public int drainChars(final int startIndex, final int endIndex, final char[] tar * Note that this method handles null input quietly, unlike String. *

    * - * @param str the string to search for, null returns false - * @return true if the builder ends with the string + * @param str the string to search for, null returns false. + * @return true if the builder ends with the string. */ public boolean endsWith(final String str) { if (str == null) { @@ -1838,9 +1835,9 @@ public boolean endsWith(final String str) { * The method ignores a negative {@code capacity} argument. *

    * - * @param capacity the capacity to ensure - * @return this, to enable chaining - * @throws OutOfMemoryError if the capacity cannot be allocated + * @param capacity the capacity to ensure. + * @return {@code this} instance. + * @throws OutOfMemoryError if the capacity cannot be allocated. */ public TextStringBuilder ensureCapacity(final int capacity) { if (capacity > 0) { @@ -1858,8 +1855,8 @@ public TextStringBuilder ensureCapacity(final int capacity) { * for an array, or cannot be allocated. *

    * - * @param capacity the capacity to ensure - * @throws OutOfMemoryError if the capacity cannot be allocated + * @param capacity the capacity to ensure. + * @throws OutOfMemoryError if the capacity cannot be allocated. */ private void ensureCapacityInternal(final int capacity) { // Check for overflow of the current buffer. @@ -1873,8 +1870,8 @@ private void ensureCapacityInternal(final int capacity) { /** * Tests the contents of this builder against another to see if they contain the same character content. * - * @param obj the object to check, null returns false - * @return true if the builders contain the same characters in the same order + * @param obj the object to check, null returns false. + * @return true if the builders contain the same characters in the same order. */ @Override public boolean equals(final Object obj) { @@ -1884,8 +1881,8 @@ public boolean equals(final Object obj) { /** * Tests the contents of this builder against another to see if they contain the same character content. * - * @param other the object to check, null returns false - * @return true if the builders contain the same characters in the same order + * @param other the object to check, null returns false. + * @return true if the builders contain the same characters in the same order. */ public boolean equals(final TextStringBuilder other) { if (this == other) { @@ -1913,8 +1910,8 @@ public boolean equals(final TextStringBuilder other) { * Tests the contents of this builder against another to see if they contain the same character content ignoring * case. * - * @param other the object to check, null returns false - * @return true if the builders contain the same characters in the same order + * @param other the object to check, null returns false. + * @return true if the builders contain the same characters in the same order. */ public boolean equalsIgnoreCase(final TextStringBuilder other) { if (this == other) { @@ -1938,7 +1935,7 @@ public boolean equalsIgnoreCase(final TextStringBuilder other) { /** * Converts this instance to a String. * - * @return This instance as a String + * @return This instance as a String. * @see #toString() * @since 1.12.0 */ @@ -1957,8 +1954,8 @@ char[] getBuffer() { /** * Copies this character array into the specified array. * - * @param target the target array, null will cause an array to be created - * @return The input array, unless that was null or too small + * @param target the target array, null will cause an array to be created. + * @return The input array, unless that was null or too small. */ public char[] getChars(char[] target) { final int len = length(); @@ -2004,7 +2001,7 @@ public String getNewLineText() { /** * Gets the text to be appended when null is added. * - * @return The null text, null means no append + * @return The null text, null means no append. */ public String getNullText() { return nullText; @@ -2013,7 +2010,7 @@ public String getNullText() { /** * Gets a suitable hash code for this builder. * - * @return a hash code + * @return a hash code. */ @Override public int hashCode() { @@ -2029,8 +2026,8 @@ public int hashCode() { /** * Searches the string builder to find the first reference to the specified char. * - * @param ch the character to find - * @return The first index of the character, or -1 if not found + * @param ch the character to find. + * @return The first index of the character, or -1 if not found. */ public int indexOf(final char ch) { return indexOf(ch, 0); @@ -2039,9 +2036,9 @@ public int indexOf(final char ch) { /** * Searches the string builder to find the first reference to the specified char. * - * @param ch the character to find - * @param startIndex the index to start at, invalid index rounded to edge - * @return The first index of the character, or -1 if not found + * @param ch the character to find. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The first index of the character, or -1 if not found. */ public int indexOf(final char ch, int startIndex) { startIndex = Math.max(0, startIndex); @@ -2063,8 +2060,8 @@ public int indexOf(final char ch, int startIndex) { * Note that a null input string will return -1, whereas the JDK throws an exception. *

    * - * @param str the string to find, null returns -1 - * @return The first index of the string, or -1 if not found + * @param str the string to find, null returns -1. + * @return The first index of the string, or -1 if not found. */ public int indexOf(final String str) { return indexOf(str, 0); @@ -2077,9 +2074,9 @@ public int indexOf(final String str) { * Note that a null input string will return -1, whereas the JDK throws an exception. *

    * - * @param str the string to find, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return The first index of the string, or -1 if not found + * @param str the string to find, null returns -1. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The first index of the string, or -1 if not found. */ public int indexOf(final String str, int startIndex) { startIndex = Math.max(0, startIndex); @@ -2117,8 +2114,8 @@ public int indexOf(final String str, int startIndex) { * character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @return The first index matched, or -1 if not found + * @param matcher the matcher to use, null returns -1. + * @return The first index matched, or -1 if not found. */ public int indexOf(final StringMatcher matcher) { return indexOf(matcher, 0); @@ -2131,9 +2128,9 @@ public int indexOf(final StringMatcher matcher) { * character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return The first index matched, or -1 if not found + * @param matcher the matcher to use, null returns -1. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The first index matched, or -1 if not found. */ public int indexOf(final StringMatcher matcher, int startIndex) { startIndex = Math.max(0, startIndex); @@ -2153,10 +2150,10 @@ public int indexOf(final StringMatcher matcher, int startIndex) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index to add at, must be valid. + * @param value the value to insert. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, final boolean value) { validateRange(index, size); @@ -2175,10 +2172,10 @@ public TextStringBuilder insert(final int index, final boolean value) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index to add at, must be valid. + * @param value the value to insert. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, final char value) { validateRange(index, size); @@ -2192,10 +2189,10 @@ public TextStringBuilder insert(final int index, final char value) { /** * Inserts the character array into this builder. Inserting null will use the stored null text value. * - * @param index the index to add at, must be valid - * @param chars the char array to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index to add at, must be valid. + * @param chars the char array to insert. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, final char[] chars) { validateRange(index, size); @@ -2215,12 +2212,12 @@ public TextStringBuilder insert(final int index, final char[] chars) { /** * Inserts part of the character array into this builder. Inserting null will use the stored null text value. * - * @param index the index to add at, must be valid - * @param chars the char array to insert - * @param offset the offset into the character array to start at, must be valid - * @param length the length of the character array part to copy, must be positive - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if any index is invalid + * @param index the index to add at, must be valid. + * @param chars the char array to insert. + * @param offset the offset into the character array to start at, must be valid. + * @param length the length of the character array part to copy, must be positive. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if any index is invalid. */ public TextStringBuilder insert(final int index, final char[] chars, final int offset, final int length) { validateRange(index, size); @@ -2245,10 +2242,10 @@ public TextStringBuilder insert(final int index, final char[] chars, final int o /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index to add at, must be valid. + * @param value the value to insert. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, final double value) { return insert(index, String.valueOf(value)); @@ -2257,10 +2254,10 @@ public TextStringBuilder insert(final int index, final double value) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index to add at, must be valid. + * @param value the value to insert. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, final float value) { return insert(index, String.valueOf(value)); @@ -2269,10 +2266,10 @@ public TextStringBuilder insert(final int index, final float value) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index to add at, must be valid. + * @param value the value to insert. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, final int value) { return insert(index, String.valueOf(value)); @@ -2281,10 +2278,10 @@ public TextStringBuilder insert(final int index, final int value) { /** * Inserts the value into this builder. * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index to add at, must be valid. + * @param value the value to insert. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, final long value) { return insert(index, String.valueOf(value)); @@ -2296,7 +2293,7 @@ public TextStringBuilder insert(final int index, final long value) { * * @param index the index to add at, must be valid. * @param obj the object to insert. - * @return this, to enable chaining. + * @return {@code this} instance. * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, final Object obj) { @@ -2306,10 +2303,10 @@ public TextStringBuilder insert(final int index, final Object obj) { /** * Inserts the string into this builder. Inserting null will use the stored null text value. * - * @param index the index to add at, must be valid - * @param str the string to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param index the index to add at, must be valid. + * @param str the string to insert. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder insert(final int index, String str) { validateRange(index, size); @@ -2367,8 +2364,8 @@ public boolean isReallocated() { /** * Searches the string builder to find the last reference to the specified char. * - * @param ch the character to find - * @return The last index of the character, or -1 if not found + * @param ch the character to find. + * @return The last index of the character, or -1 if not found. */ public int lastIndexOf(final char ch) { return lastIndexOf(ch, size - 1); @@ -2377,9 +2374,9 @@ public int lastIndexOf(final char ch) { /** * Searches the string builder to find the last reference to the specified char. * - * @param ch the character to find - * @param startIndex the index to start at, invalid index rounded to edge - * @return The last index of the character, or -1 if not found + * @param ch the character to find. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The last index of the character, or -1 if not found. */ public int lastIndexOf(final char ch, int startIndex) { startIndex = startIndex >= size ? size - 1 : startIndex; @@ -2400,8 +2397,8 @@ public int lastIndexOf(final char ch, int startIndex) { * Note that a null input string will return -1, whereas the JDK throws an exception. *

    * - * @param str the string to find, null returns -1 - * @return The last index of the string, or -1 if not found + * @param str the string to find, null returns -1. + * @return The last index of the string, or -1 if not found. */ public int lastIndexOf(final String str) { return lastIndexOf(str, size - 1); @@ -2414,9 +2411,9 @@ public int lastIndexOf(final String str) { * Note that a null input string will return -1, whereas the JDK throws an exception. *

    * - * @param str the string to find, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return The last index of the string, or -1 if not found + * @param str the string to find, null returns -1. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The last index of the string, or -1 if not found. */ public int lastIndexOf(final String str, int startIndex) { startIndex = startIndex >= size ? size - 1 : startIndex; @@ -2452,8 +2449,8 @@ public int lastIndexOf(final String str, int startIndex) { * character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @return The last index matched, or -1 if not found + * @param matcher the matcher to use, null returns -1. + * @return The last index matched, or -1 if not found. */ public int lastIndexOf(final StringMatcher matcher) { return lastIndexOf(matcher, size); @@ -2466,9 +2463,9 @@ public int lastIndexOf(final StringMatcher matcher) { * character 'a' followed by a number. *

    * - * @param matcher the matcher to use, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return The last index matched, or -1 if not found + * @param matcher the matcher to use, null returns -1. + * @param startIndex the index to start at, invalid index rounded to edge. + * @return The last index matched, or -1 if not found. */ public int lastIndexOf(final StringMatcher matcher, int startIndex) { startIndex = startIndex >= size ? size - 1 : startIndex; @@ -2492,8 +2489,8 @@ public int lastIndexOf(final StringMatcher matcher, int startIndex) { * available, the whole builder is returned. Thus the returned string may be shorter than the length requested. *

    * - * @param length the number of characters to extract, negative returns empty string - * @return The new string + * @param length the number of characters to extract, negative returns empty string. + * @return The new string. */ public String leftString(final int length) { if (length <= 0) { @@ -2524,9 +2521,9 @@ public int length() { * much as possible is returned. Thus the returned string may be shorter than the length requested. *

    * - * @param index the index to start at, negative means zero - * @param length the number of characters to extract, negative returns empty string - * @return The new string + * @param index the index to start at, negative means zero. + * @param length the number of characters to extract, negative returns empty string. + * @return The new string. */ public String midString(int index, final int length) { if (index < 0) { @@ -2544,7 +2541,7 @@ public String midString(int index, final int length) { /** * Minimizes the capacity to the actual length of the string. * - * @return this, to enable chaining + * @return {@code this} instance. */ public TextStringBuilder minimizeCapacity() { if (buffer.length > size) { @@ -2575,8 +2572,8 @@ public int readFrom(final CharBuffer charBuffer) { * If possible, reads all chars from the provided {@link Readable} directly into underlying character buffer without * making extra copies. * - * @param readable object to read from - * @return The number of characters read + * @param readable object to read from. + * @return The number of characters read. * @throws IOException if an I/O error occurs. * @see #appendTo(Appendable) */ @@ -2626,13 +2623,11 @@ public int readFrom(final Reader reader) throws IOException { } /** - * If possible, reads {@code count} chars from the provided {@link Reader} directly into underlying character buffer - * without making extra copies. + * If possible, reads {@code count} chars from the provided {@link Reader} directly into underlying character buffer without making extra copies. * * @param reader Reader to read. - * @param count The maximum characters to read, a value <= 0 returns 0. - * @return The number of characters read. If less than {@code count}, then we've reached the end-of-stream, or -1 if - * we reached the end of stream. + * @param count The maximum characters to read, a value <= 0 returns 0. + * @return The number of characters read. If less than {@code count}, then we've reached the end-of-stream, or -1 if we reached the end of stream. * @throws IOException if an I/O error occurs. * @see #appendTo(Appendable) * @since 1.9 @@ -2659,7 +2654,7 @@ public int readFrom(final Reader reader, final int count) throws IOException { /** * Reallocates the buffer to the new length. * - * @param newLength the length of the copy to be returned + * @param newLength the length of the copy to be returned. */ private void reallocate(final int newLength) { this.buffer = Arrays.copyOf(buffer, newLength); @@ -2667,14 +2662,13 @@ private void reallocate(final int newLength) { } /** - * Replaces a portion of the string builder with another string. The length of the inserted string does not have to - * match the removed length. + * Replaces a portion of the string builder with another string. The length of the inserted string does not have to match the removed length. * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @param replaceStr the string to replace with, null means delete range - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @param replaceStr the string to replace with, null means delete range. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the index is invalid. */ public TextStringBuilder replace(final int startIndex, int endIndex, final String replaceStr) { endIndex = validateRange(startIndex, endIndex); @@ -2686,17 +2680,17 @@ public TextStringBuilder replace(final int startIndex, int endIndex, final Strin /** * Advanced search and replaces within the builder using a matcher. *

    - * Matchers can be used to perform advanced behavior. For example you could write a matcher to delete all - * occurrences where the character 'a' is followed by a number. + * Matchers can be used to perform advanced behavior. For example you could write a matcher to delete all occurrences where the character 'a' is followed by + * a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @param replaceStr the string to replace the match with, null is a delete - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @param replaceCount the number of times to replace, -1 for replace all - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if start index is invalid + * @param matcher the matcher to use to find the deletion, null causes no action. + * @param replaceStr the string to replace the match with, null is a delete. + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @param replaceCount the number of times to replace, -1 for replace all. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if start index is invalid. */ public TextStringBuilder replace(final StringMatcher matcher, final String replaceStr, final int startIndex, int endIndex, final int replaceCount) { @@ -2707,9 +2701,9 @@ public TextStringBuilder replace(final StringMatcher matcher, final String repla /** * Replaces the search character with the replace character throughout the builder. * - * @param search the search character - * @param replace the replace character - * @return this, to enable chaining + * @param search the search character. + * @param replace the replace character. + * @return {@code this} instance. */ public TextStringBuilder replaceAll(final char search, final char replace) { if (search != replace) { @@ -2725,9 +2719,9 @@ public TextStringBuilder replaceAll(final char search, final char replace) { /** * Replaces the search string with the replace string throughout the builder. * - * @param searchStr the search string, null causes no action to occur - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining + * @param searchStr the search string, null causes no action to occur. + * @param replaceStr the replace string, null is equivalent to an empty string. + * @return {@code this} instance. */ public TextStringBuilder replaceAll(final String searchStr, final String replaceStr) { final int searchLen = searchStr == null ? 0 : searchStr.length(); @@ -2749,9 +2743,9 @@ public TextStringBuilder replaceAll(final String searchStr, final String replace * occurrences where the character 'a' is followed by a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining + * @param matcher the matcher to use to find the deletion, null causes no action. + * @param replaceStr the replace string, null is equivalent to an empty string. + * @return {@code this} instance. */ public TextStringBuilder replaceAll(final StringMatcher matcher, final String replaceStr) { return replace(matcher, replaceStr, 0, size, -1); @@ -2760,9 +2754,9 @@ public TextStringBuilder replaceAll(final StringMatcher matcher, final String re /** * Replaces the first instance of the search character with the replace character in the builder. * - * @param search the search character - * @param replace the replace character - * @return this, to enable chaining + * @param search the search character. + * @param replace the replace character. + * @return {@code this} instance. */ public TextStringBuilder replaceFirst(final char search, final char replace) { if (search != replace) { @@ -2779,9 +2773,9 @@ public TextStringBuilder replaceFirst(final char search, final char replace) { /** * Replaces the first instance of the search string with the replace string. * - * @param searchStr the search string, null causes no action to occur - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining + * @param searchStr the search string, null causes no action to occur. + * @param replaceStr the replace string, null is equivalent to an empty string. + * @return {@code this} instance. */ public TextStringBuilder replaceFirst(final String searchStr, final String replaceStr) { final int searchLen = searchStr == null ? 0 : searchStr.length(); @@ -2802,9 +2796,9 @@ public TextStringBuilder replaceFirst(final String searchStr, final String repla * the character 'a' is followed by a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining + * @param matcher the matcher to use to find the deletion, null causes no action. + * @param replaceStr the replace string, null is equivalent to an empty string. + * @return {@code this} instance. */ public TextStringBuilder replaceFirst(final StringMatcher matcher, final String replaceStr) { return replace(matcher, replaceStr, 0, size, 1); @@ -2813,12 +2807,12 @@ public TextStringBuilder replaceFirst(final StringMatcher matcher, final String /** * Internal method to delete a range without validation. * - * @param startIndex the start index, must be valid - * @param endIndex the end index (exclusive), must be valid - * @param removeLen the length to remove (endIndex - startIndex), must be valid - * @param insertStr the string to replace with, null means delete range - * @param insertLen the length of the insert string, must be valid - * @throws IndexOutOfBoundsException if any index is invalid + * @param startIndex the start index, must be valid. + * @param endIndex the end index (exclusive), must be valid. + * @param removeLen the length to remove (endIndex - startIndex), must be valid. + * @param insertStr the string to replace with, null means delete range. + * @param insertLen the length of the insert string, must be valid. + * @throws IndexOutOfBoundsException if any index is invalid. */ private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr, final int insertLen) { @@ -2840,13 +2834,13 @@ private void replaceImpl(final int startIndex, final int endIndex, final int rem * occurrences where the character 'a' is followed by a number. *

    * - * @param matcher the matcher to use to find the deletion, null causes no action - * @param replaceStr the string to replace the match with, null is a delete - * @param from the start index, must be valid - * @param to the end index (exclusive), must be valid - * @param replaceCount the number of times to replace, -1 for replace all - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if any index is invalid + * @param matcher the matcher to use to find the deletion, null causes no action. + * @param replaceStr the string to replace the match with, null is a delete. + * @param from the start index, must be valid. + * @param to the end index (exclusive), must be valid. + * @param replaceCount the number of times to replace, -1 for replace all. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if any index is invalid. */ private TextStringBuilder replaceImpl(final StringMatcher matcher, final String replaceStr, final int from, int to, int replaceCount) { @@ -2872,8 +2866,8 @@ private TextStringBuilder replaceImpl(final StringMatcher matcher, final String /** * Resizes the buffer to at least the size specified. * - * @param minCapacity the minimum required capacity - * @throws OutOfMemoryError if the {@code minCapacity} is negative + * @param minCapacity the minimum required capacity. + * @throws OutOfMemoryError if the {@code minCapacity} is negative. */ private void resizeBuffer(final int minCapacity) { // Overflow-conscious code treats the min and new capacity as unsigned. @@ -2891,7 +2885,7 @@ private void resizeBuffer(final int minCapacity) { /** * Reverses the string builder placing each character in the opposite index. * - * @return this, to enable chaining + * @return {@code this} instance. */ public TextStringBuilder reverse() { if (size == 0) { @@ -2914,8 +2908,8 @@ public TextStringBuilder reverse() { * available, the whole builder is returned. Thus the returned string may be shorter than the length requested. *

    * - * @param length the number of characters to extract, negative returns empty string - * @return The new string + * @param length the number of characters to extract, negative returns empty string. + * @return The new string. */ public String rightString(final int length) { if (length <= 0) { @@ -2930,11 +2924,11 @@ public String rightString(final int length) { /** * Clears and sets this builder to the given value. * - * @see #charAt(int) - * @see #deleteCharAt(int) * @param str the new value. - * @return this, to enable chaining + * @return {@code this} instance. * @since 1.9 + * @see #charAt(int) + * @see #deleteCharAt(int) */ public TextStringBuilder set(final CharSequence str) { return clear().append(str); @@ -2943,12 +2937,12 @@ public TextStringBuilder set(final CharSequence str) { /** * Sets the character at the specified index. * - * @see #charAt(int) - * @see #deleteCharAt(int) * @param index the index to set * @param ch the new character - * @return this, to enable chaining + * @return {@code this} instance. * @throws IndexOutOfBoundsException if the index is invalid + * @see #charAt(int) + * @see #deleteCharAt(int) */ public TextStringBuilder setCharAt(final int index, final char ch) { validateIndex(index); @@ -2959,9 +2953,9 @@ public TextStringBuilder setCharAt(final int index, final char ch) { /** * Updates the length of the builder by either dropping the last characters or adding filler of Unicode zero. * - * @param length the length to set to, must be zero or positive - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the length is negative + * @param length the length to set to, must be zero or positive. + * @return {@code this} instance. + * @throws IndexOutOfBoundsException if the length is negative. */ public TextStringBuilder setLength(final int length) { if (length < 0) { @@ -2992,8 +2986,8 @@ public TextStringBuilder setNewLineText(final String newLine) { /** * Sets the text to be appended when null is added. * - * @param nullText the null text, null means no append - * @return this, to enable chaining + * @param nullText the null text, null means no append. + * @return {@code this} instance. */ public TextStringBuilder setNullText(String nullText) { if (nullText != null && nullText.isEmpty()) { @@ -3009,7 +3003,7 @@ public TextStringBuilder setNullText(String nullText) { * This method is the same as {@link #length()} and is provided to match the API of Collections. *

    * - * @return The length + * @return The length. */ public int size() { return size; @@ -3021,8 +3015,8 @@ public int size() { * Note that this method handles null input quietly, unlike String. *

    * - * @param str the string to search for, null returns false - * @return true if the builder starts with the string + * @param str the string to search for, null returns false. + * @return true if the builder starts with the string. */ public boolean startsWith(final String str) { if (str == null) { @@ -3063,9 +3057,9 @@ public CharSequence subSequence(final int startIndex, final int endIndex) { /** * Extracts a portion of this string builder as a string. * - * @param start the start index, inclusive, must be valid - * @return The new string - * @throws IndexOutOfBoundsException if the index is invalid + * @param start the start index, inclusive, must be valid. + * @return The new string. + * @throws IndexOutOfBoundsException if the index is invalid. */ public String substring(final int start) { return substring(start, size); @@ -3078,10 +3072,10 @@ public String substring(final int start) { * builder, and continues without error, unlike StringBuffer or String. *

    * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @return The new string - * @throws IndexOutOfBoundsException if the index is invalid + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @return The new string. + * @throws IndexOutOfBoundsException if the index is invalid. */ public String substring(final int startIndex, int endIndex) { endIndex = validateRange(startIndex, endIndex); @@ -3091,7 +3085,7 @@ public String substring(final int startIndex, int endIndex) { /** * Copies the builder's character array into a new character array. * - * @return a new array that represents the contents of the builder + * @return a new array that represents the contents of the builder. */ public char[] toCharArray() { return size == 0 ? ArrayUtils.EMPTY_CHAR_ARRAY : Arrays.copyOf(buffer, size); @@ -3100,11 +3094,10 @@ public char[] toCharArray() { /** * Copies part of the builder's character array into a new character array. * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string - * @return a new array that holds part of the contents of the builder - * @throws IndexOutOfBoundsException if startIndex is invalid, or if endIndex is invalid (but endIndex greater than - * size is valid) + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. + * @return a new array that holds part of the contents of the builder. + * @throws IndexOutOfBoundsException if startIndex is invalid, or if endIndex is invalid (but endIndex greater than size is valid). */ public char[] toCharArray(final int startIndex, int endIndex) { endIndex = validateRange(startIndex, endIndex); @@ -3118,7 +3111,7 @@ public char[] toCharArray(final int startIndex, int endIndex) { * Note that unlike StringBuffer, the string version returned is independent of the string builder. *

    * - * @return The builder as a String + * @return The builder as a String. */ @Override public String toString() { @@ -3128,7 +3121,7 @@ public String toString() { /** * Gets a StringBuffer version of the string builder, creating a new instance each time the method is called. * - * @return The builder as a StringBuffer + * @return The builder as a StringBuffer. */ public StringBuffer toStringBuffer() { return new StringBuffer(size).append(buffer, 0, size); @@ -3137,7 +3130,7 @@ public StringBuffer toStringBuffer() { /** * Gets a StringBuilder version of the string builder, creating a new instance each time the method is called. * - * @return The builder as a StringBuilder + * @return The builder as a StringBuilder. */ public StringBuilder toStringBuilder() { return new StringBuilder(size).append(buffer, 0, size); @@ -3146,7 +3139,7 @@ public StringBuilder toStringBuilder() { /** * Trims the builder by removing characters less than or equal to a space from the beginning and end. * - * @return this, to enable chaining + * @return {@code this} instance. */ public TextStringBuilder trim() { if (size == 0) { @@ -3185,10 +3178,10 @@ protected void validateIndex(final int index) { /** * Validates parameters defining a range of the builder. * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string + * @param startIndex the start index, inclusive, must be valid. + * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string. * @return A valid end index. - * @throws StringIndexOutOfBoundsException if the index is invalid + * @throws StringIndexOutOfBoundsException if the index is invalid. */ protected int validateRange(final int startIndex, int endIndex) { if (startIndex < 0) { diff --git a/src/main/java/org/apache/commons/text/WordUtils.java b/src/main/java/org/apache/commons/text/WordUtils.java index 48b43caf85..ca41c6c3c3 100644 --- a/src/main/java/org/apache/commons/text/WordUtils.java +++ b/src/main/java/org/apache/commons/text/WordUtils.java @@ -130,8 +130,8 @@ public static String abbreviate(final String str, int lower, int upper, final St * WordUtils.capitalize("i am FINE") = "I Am FINE" *
    * - * @param str the String to capitalize, may be null - * @return capitalized String, {@code null} if null String input + * @param str the String to capitalize, may be null. + * @return capitalized String, {@code null} if null String input. * @see #uncapitalize(String) * @see #capitalizeFully(String) */ @@ -162,9 +162,9 @@ public static String capitalize(final String str) { * WordUtils.capitalize("i am fine", new char[]{}) = "I am fine" *
    * - * @param str the String to capitalize, may be null - * @param delimiters set of characters to determine capitalization, null means whitespace - * @return capitalized String, {@code null} if null String input + * @param str the String to capitalize, may be null. + * @param delimiters set of characters to determine capitalization, null means whitespace. + * @return capitalized String, {@code null} if null String input. * @see #uncapitalize(String) * @see #capitalizeFully(String) */ @@ -214,8 +214,8 @@ public static String capitalize(final String str, final char... delimiters) { * WordUtils.capitalizeFully("i am FINE") = "I Am Fine" *
    * - * @param str the String to capitalize, may be null - * @return capitalized String, {@code null} if null String input + * @param str the String to capitalize, may be null. + * @return capitalized String, {@code null} if null String input. */ public static String capitalizeFully(final String str) { return capitalizeFully(str, null); @@ -242,9 +242,9 @@ public static String capitalizeFully(final String str) { * WordUtils.capitalizeFully("i aM.fine", {'.'}) = "I am.Fine" *
    * - * @param str the String to capitalize, may be null - * @param delimiters set of characters to determine capitalization, null means whitespace - * @return capitalized String, {@code null} if null String input + * @param str the String to capitalize, may be null. + * @param delimiters set of characters to determine capitalization, null means whitespace. + * @return capitalized String, {@code null} if null String input. */ public static String capitalizeFully(String str, final char... delimiters) { if (StringUtils.isEmpty(str)) { @@ -271,9 +271,9 @@ public static String capitalizeFully(String str, final char... delimiters) { * WordUtils.containsAllWords("abc def", "def", "abc") = true *
    * - * @param word The CharSequence to check, may be null - * @param words The array of String words to search for, may be null - * @return {@code true} if all search words are found, {@code false} otherwise + * @param word The CharSequence to check, may be null. + * @param words The array of String words to search for, may be null. + * @return {@code true} if all search words are found, {@code false} otherwise. */ public static boolean containsAllWords(final CharSequence word, final CharSequence... words) { if (StringUtils.isEmpty(word) || ArrayUtils.isEmpty(words)) { @@ -296,7 +296,7 @@ public static boolean containsAllWords(final CharSequence word, final CharSequen * The function provides O(1) lookup time. * Whitespace is defined by {@link Character#isWhitespace(char)} and is used as the defaultvalue if delimiters is null. * - * @param delimiters set of characters to determine delimiters, null means whitespace + * @param delimiters set of characters to determine delimiters, null means whitespace. * @return Predicate taking a code point value as an argument and returning true if a delimiter. */ private static Predicate generateIsDelimiterFunction(final char[] delimiters) { @@ -330,8 +330,8 @@ private static Predicate generateIsDelimiterFunction(final char[] delim * WordUtils.initials("Ben J.Lee") = "BJ" *
    * - * @param str the String to get initials from, may be null - * @return String of initial letters, {@code null} if null String input + * @param str the String to get initials from, may be null. + * @return String of initial letters, {@code null} if null String input. * @see #initials(String,char[]) */ public static String initials(final String str) { @@ -358,9 +358,9 @@ public static String initials(final String str) { * WordUtils.initials(*, new char[0]) = "" *
    * - * @param str the String to get initials from, may be null - * @param delimiters set of characters to determine words, null means whitespace - * @return String of initial characters, {@code null} if null String input + * @param str the String to get initials from, may be null. + * @param delimiters set of characters to determine words, null means whitespace. + * @return String of initial characters, {@code null} if null String input. * @see #initials(String) */ public static String initials(final String str, final char... delimiters) { @@ -393,10 +393,10 @@ public static String initials(final String str, final char... delimiters) { /** * Is the character a delimiter. * - * @param ch the character to check - * @param delimiters the delimiters - * @return true if it is a delimiter - * @deprecated as of 1.2 and will be removed in 2.0 + * @param ch the character to check. + * @param delimiters the delimiters. + * @return true if it is a delimiter. + * @deprecated as of 1.2 and will be removed in 2.0. */ @Deprecated public static boolean isDelimiter(final char ch, final char[] delimiters) { @@ -414,10 +414,10 @@ public static boolean isDelimiter(final char ch, final char[] delimiters) { /** * Is the codePoint a delimiter. * - * @param codePoint the codePint to check - * @param delimiters the delimiters - * @return true if it is a delimiter - * @deprecated as of 1.2 and will be removed in 2.0 + * @param codePoint the codePint to check. + * @param delimiters the delimiters. + * @return true if it is a delimiter. + * @deprecated as of 1.2 and will be removed in 2.0. */ @Deprecated public static boolean isDelimiter(final int codePoint, final char[] delimiters) { @@ -452,8 +452,8 @@ public static boolean isDelimiter(final int codePoint, final char[] delimiters) * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" *
    * - * @param str the String to swap case, may be null - * @return The changed String, {@code null} if null String input + * @param str the String to swap case, may be null. + * @return The changed String, {@code null} if null String input. */ public static String swapCase(final String str) { if (StringUtils.isEmpty(str)) { @@ -499,8 +499,8 @@ public static String swapCase(final String str) { * WordUtils.uncapitalize("I Am FINE") = "i am fINE" *
    * - * @param str the String to uncapitalize, may be null - * @return uncapitalized String, {@code null} if null String input + * @param str the String to uncapitalize, may be null. + * @return uncapitalized String, {@code null} if null String input. * @see #capitalize(String) */ public static String uncapitalize(final String str) { @@ -527,9 +527,9 @@ public static String uncapitalize(final String str) { * WordUtils.uncapitalize("I am fine", new char[]{}) = "i am fine" *
    * - * @param str the String to uncapitalize, may be null - * @param delimiters set of characters to determine uncapitalization, null means whitespace - * @return uncapitalized String, {@code null} if null String input + * @param str the String to uncapitalize, may be null. + * @param delimiters set of characters to determine uncapitalization, null means whitespace. + * @return uncapitalized String, {@code null} if null String input. * @see #capitalize(String) */ public static String uncapitalize(final String str, final char... delimiters) { @@ -607,9 +607,9 @@ public static String uncapitalize(final String str, final char... delimiters) { * * (assuming that '\n' is the systems line separator) * - * @param str the String to be word wrapped, may be null - * @param wrapLength the column to wrap the words at, less than 1 is treated as 1 - * @return a line with newlines inserted, {@code null} if null input + * @param str the String to be word wrapped, may be null. + * @param wrapLength the column to wrap the words at, less than 1 is treated as 1. + * @return a line with newlines inserted, {@code null} if null input. */ public static String wrap(final String str, final int wrapLength) { return wrap(str, wrapLength, null, false); @@ -683,12 +683,11 @@ public static String wrap(final String str, final int wrapLength) { * * * - * @param str the String to be word wrapped, may be null - * @param wrapLength the column to wrap the words at, less than 1 is treated as 1 - * @param newLineStr the string to insert for a new line, - * {@code null} uses the system property line separator - * @param wrapLongWords true if long words (such as URLs) should be wrapped - * @return a line with newlines inserted, {@code null} if null input + * @param str the String to be word wrapped, may be null. + * @param wrapLength the column to wrap the words at, less than 1 is treated as 1. + * @param newLineStr the string to insert for a new line, {@code null} uses the system property line separator. + * @param wrapLongWords true if long words (such as URLs) should be wrapped. + * @return a line with newlines inserted, {@code null} if null input. */ public static String wrap(final String str, final int wrapLength, @@ -780,14 +779,12 @@ public static String wrap(final String str, * "flammable\ninflammable" * * - * @param str the String to be word wrapped, may be null - * @param wrapLength the column to wrap the words at, less than 1 is treated as 1 - * @param newLineStr the string to insert for a new line, - * {@code null} uses the system property line separator - * @param wrapLongWords true if long words (such as URLs) should be wrapped - * @param wrapOn regex expression to be used as a breakable characters, - * if blank string is provided a space character will be used - * @return a line with newlines inserted, {@code null} if null input + * @param str the String to be word wrapped, may be null. + * @param wrapLength the column to wrap the words at, less than 1 is treated as 1. + * @param newLineStr the string to insert for a new line, {@code null} uses the system property line separator. + * @param wrapLongWords true if long words (such as URLs) should be wrapped. + * @param wrapOn regex expression to be used as a breakable characters, if blank string is provided a space character will be used. + * @return a line with newlines inserted, {@code null} if null input. */ public static String wrap(final String str, int wrapLength, From f99e435a750594a88b562bf9f6f97fd442d34d3b Mon Sep 17 00:00:00 2001 From: Michael Hausegger Date: Wed, 3 Dec 2025 19:42:20 +0100 Subject: [PATCH 193/265] Added new tests for the main Levenshtein algorithm implementations (#728) * Added new tests for the main Levenshtein algorithm implementation classes * Added new tests for the main Levenshtein algorithm implementation classes * Added tests * Remove extra vertical whitespace * Added tests --------- Co-authored-by: TheRealHaui Co-authored-by: Gary Gregory --- .../text/similarity/EditDistanceFromTest.java | 45 +++++++++++++++++++ .../similarity/JaccardSimilarityTest.java | 10 +++++ .../similarity/JaroWinklerDistanceTest.java | 6 +++ .../LevenshteinDetailedDistanceTest.java | 8 ++++ .../similarity/LevenshteinDistanceTest.java | 10 +++++ .../LongestCommonSubsequenceTest.java | 7 +++ .../similarity/SimilarityScoreFromTest.java | 22 ++++++++- 7 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 src/test/java/org/apache/commons/text/similarity/EditDistanceFromTest.java diff --git a/src/test/java/org/apache/commons/text/similarity/EditDistanceFromTest.java b/src/test/java/org/apache/commons/text/similarity/EditDistanceFromTest.java new file mode 100644 index 0000000000..32d85752aa --- /dev/null +++ b/src/test/java/org/apache/commons/text/similarity/EditDistanceFromTest.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.similarity; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class EditDistanceFromTest { + + private LongestCommonSubsequenceDistance longestCommonSubsequenceDistance; + private EditDistanceFrom editDistanceFrom; + + @BeforeEach + void doBeforeEachTest() { + longestCommonSubsequenceDistance = new LongestCommonSubsequenceDistance(); + editDistanceFrom = new EditDistanceFrom<>(longestCommonSubsequenceDistance, "asdf"); + } + + @Test + void testGetLeft() { + assertEquals("asdf", editDistanceFrom.getLeft()); + } + + @Test + void testGetSimilarityScore() { + assertEquals(longestCommonSubsequenceDistance, editDistanceFrom.getEditDistance()); + } + +} diff --git a/src/test/java/org/apache/commons/text/similarity/JaccardSimilarityTest.java b/src/test/java/org/apache/commons/text/similarity/JaccardSimilarityTest.java index 334ea748fc..f7ef2ab75f 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaccardSimilarityTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaccardSimilarityTest.java @@ -89,4 +89,14 @@ void testGettingJaccardSimilarityNullString() { void testGettingJaccardSimilarityStringNull() { assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(" ", null)); } + + @Test + void testGettingJaccardSimilarityNullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(null, new SimilarityCharacterInput("asdf"))); + } + + @Test + void testGettingJaccardSimilaritySimilarityInputNull() { + assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(new SimilarityCharacterInput("asdf"), null)); + } } diff --git a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java index 509d58bb59..7df3a10338 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java @@ -18,6 +18,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -105,4 +106,9 @@ void testGetJaroWinklerDistance_StringString() { assertEquals(1 - 0.51111d, distance.apply("foo", " foo"), 0.00001d); } + @Test + void testMatches() { + assertArrayEquals(new int[]{2, 0, 2}, distance.matches("ab", "aba")); + } + } diff --git a/src/test/java/org/apache/commons/text/similarity/LevenshteinDetailedDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/LevenshteinDetailedDistanceTest.java index 9ba1baf753..f80cbc7915 100644 --- a/src/test/java/org/apache/commons/text/similarity/LevenshteinDetailedDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/LevenshteinDetailedDistanceTest.java @@ -41,6 +41,14 @@ void testApplyThrowsIllegalArgumentExceptionAndCreatesLevenshteinDetailedDistanc void testApplyWithNullSimilarityInput() { assertThrows(IllegalArgumentException.class, () -> new LevenshteinDetailedDistance(0).apply((SimilarityInput) null, (SimilarityInput) null)); + assertThrows(IllegalArgumentException.class, + () -> new LevenshteinDetailedDistance(0).apply(new SimilarityCharacterInput("asdf"), (SimilarityCharacterInput) null)); + assertThrows(IllegalArgumentException.class, + () -> new LevenshteinDetailedDistance(0).apply((SimilarityCharacterInput) null, new SimilarityCharacterInput("asdf"))); + assertThrows(IllegalArgumentException.class, + () -> new LevenshteinDetailedDistance(null).apply(new SimilarityCharacterInput("asdf"), (SimilarityCharacterInput) null)); + assertThrows(IllegalArgumentException.class, + () -> new LevenshteinDetailedDistance(null).apply((SimilarityCharacterInput) null, new SimilarityCharacterInput("asdf"))); } @Test diff --git a/src/test/java/org/apache/commons/text/similarity/LevenshteinDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/LevenshteinDistanceTest.java index 99dd5e72b5..8aa3960d72 100644 --- a/src/test/java/org/apache/commons/text/similarity/LevenshteinDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/LevenshteinDistanceTest.java @@ -34,6 +34,10 @@ class LevenshteinDistanceTest { @Test void testApplyThrowsIllegalArgumentExceptionSimilarityInput() { assertThrows(IllegalArgumentException.class, () -> new LevenshteinDistance(0).apply((SimilarityInput) null, (SimilarityInput) null)); + assertThrows(IllegalArgumentException.class, () -> new LevenshteinDistance(0).apply(new SimilarityCharacterInput("asdf"), + (SimilarityCharacterInput) null)); + assertThrows(IllegalArgumentException.class, () -> new LevenshteinDistance(0).apply((SimilarityCharacterInput) null, + new SimilarityCharacterInput("asdf"))); } @Test @@ -85,6 +89,12 @@ void testGetLevenshteinDistance_StringNullInt(final Class cls) { assertThrows(IllegalArgumentException.class, () -> UNLIMITED_DISTANCE.apply(SimilarityInputTest.build(cls, "a"), SimilarityInputTest.build(cls, null))); } + @Test + void testGetLevenshteinDistance_EmptyStringString() { + assertEquals(-1, new LevenshteinDistance(0).apply(new SimilarityCharacterInput(""), + new SimilarityCharacterInput("asdf"))); + } + @ParameterizedTest @MethodSource("org.apache.commons.text.similarity.SimilarityInputTest#similarityInputs()") void testGetLevenshteinDistance_StringString(final Class cls) { diff --git a/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java b/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java index b280361a1f..e5208a2011 100644 --- a/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java @@ -18,6 +18,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -133,4 +134,10 @@ void testLongestCommonSubsequenceApply() { assertEquals(4, subject.apply("leettteft", "ritttght")); assertEquals(15, subject.apply("the same string", "the same string")); } + + @Test + void testLongestCommonSubstringLengthArray() { + assertArrayEquals(new int[][]{ {0, 0, 0, 0}, {0, 1, 1, 1}, {0, 1, 2, 2}}, subject.longestCommonSubstringLengthArray("ab", "abc")); + } + } diff --git a/src/test/java/org/apache/commons/text/similarity/SimilarityScoreFromTest.java b/src/test/java/org/apache/commons/text/similarity/SimilarityScoreFromTest.java index 9f141f7e4e..cd037b4dc5 100644 --- a/src/test/java/org/apache/commons/text/similarity/SimilarityScoreFromTest.java +++ b/src/test/java/org/apache/commons/text/similarity/SimilarityScoreFromTest.java @@ -20,17 +20,35 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class SimilarityScoreFromTest { + private LongestCommonSubsequence longestCommonSubsequence; + private SimilarityScoreFrom similarityScoreFrom; + + @BeforeEach + void doBeforeEachTest() { + longestCommonSubsequence = new LongestCommonSubsequence(); + similarityScoreFrom = new SimilarityScoreFrom<>(longestCommonSubsequence, "asdf"); + } + @Test void testApply() { - final LongestCommonSubsequence longestCommonSubsequence = new LongestCommonSubsequence(); - final SimilarityScoreFrom similarityScoreFrom = new SimilarityScoreFrom<>(longestCommonSubsequence, "asdf"); assertEquals(1, similarityScoreFrom.apply("s")); } + @Test + void testGetLeft() { + assertEquals("asdf", similarityScoreFrom.getLeft()); + } + + @Test + void testGetSimilarityScore() { + assertEquals(longestCommonSubsequence, similarityScoreFrom.getSimilarityScore()); + } + @Test void testFailsToCreateSimilarityScoreFromThrowsIllegalArgumentException() { assertThrows(IllegalArgumentException.class, () -> new SimilarityScoreFrom<>(null, "")); From 67af4ec0b0917a800ce21e27c35b9f9a2b465da5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 13:43:17 -0500 Subject: [PATCH 194/265] Sort members --- .../text/similarity/JaccardSimilarityTest.java | 16 ++++++++-------- .../text/similarity/LevenshteinDistanceTest.java | 12 ++++++------ .../text/similarity/SimilarityScoreFromTest.java | 10 +++++----- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/test/java/org/apache/commons/text/similarity/JaccardSimilarityTest.java b/src/test/java/org/apache/commons/text/similarity/JaccardSimilarityTest.java index f7ef2ab75f..a50382fab5 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaccardSimilarityTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaccardSimilarityTest.java @@ -81,22 +81,22 @@ void testGettingJaccardSimilarityNullNull() { } @Test - void testGettingJaccardSimilarityNullString() { - assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(null, "right")); + void testGettingJaccardSimilarityNullSimilarityInput() { + assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(null, new SimilarityCharacterInput("asdf"))); } @Test - void testGettingJaccardSimilarityStringNull() { - assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(" ", null)); + void testGettingJaccardSimilarityNullString() { + assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(null, "right")); } @Test - void testGettingJaccardSimilarityNullSimilarityInput() { - assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(null, new SimilarityCharacterInput("asdf"))); + void testGettingJaccardSimilaritySimilarityInputNull() { + assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(new SimilarityCharacterInput("asdf"), null)); } @Test - void testGettingJaccardSimilaritySimilarityInputNull() { - assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(new SimilarityCharacterInput("asdf"), null)); + void testGettingJaccardSimilarityStringNull() { + assertThrows(IllegalArgumentException.class, () -> classBeingTested.apply(" ", null)); } } diff --git a/src/test/java/org/apache/commons/text/similarity/LevenshteinDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/LevenshteinDistanceTest.java index 8aa3960d72..e7a88ca498 100644 --- a/src/test/java/org/apache/commons/text/similarity/LevenshteinDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/LevenshteinDistanceTest.java @@ -65,6 +65,12 @@ void testGetLevenshteinDistance(final Class cls) { assertEquals(1, UNLIMITED_DISTANCE.apply(SimilarityInputTest.build(cls, "hello"), SimilarityInputTest.build(cls, "hallo"))); } + @Test + void testGetLevenshteinDistance_EmptyStringString() { + assertEquals(-1, new LevenshteinDistance(0).apply(new SimilarityCharacterInput(""), + new SimilarityCharacterInput("asdf"))); + } + @ParameterizedTest @MethodSource("org.apache.commons.text.similarity.SimilarityInputTest#similarityInputs()") void testGetLevenshteinDistance_NullString(final Class cls) { @@ -89,12 +95,6 @@ void testGetLevenshteinDistance_StringNullInt(final Class cls) { assertThrows(IllegalArgumentException.class, () -> UNLIMITED_DISTANCE.apply(SimilarityInputTest.build(cls, "a"), SimilarityInputTest.build(cls, null))); } - @Test - void testGetLevenshteinDistance_EmptyStringString() { - assertEquals(-1, new LevenshteinDistance(0).apply(new SimilarityCharacterInput(""), - new SimilarityCharacterInput("asdf"))); - } - @ParameterizedTest @MethodSource("org.apache.commons.text.similarity.SimilarityInputTest#similarityInputs()") void testGetLevenshteinDistance_StringString(final Class cls) { diff --git a/src/test/java/org/apache/commons/text/similarity/SimilarityScoreFromTest.java b/src/test/java/org/apache/commons/text/similarity/SimilarityScoreFromTest.java index cd037b4dc5..4231862212 100644 --- a/src/test/java/org/apache/commons/text/similarity/SimilarityScoreFromTest.java +++ b/src/test/java/org/apache/commons/text/similarity/SimilarityScoreFromTest.java @@ -39,6 +39,11 @@ void testApply() { assertEquals(1, similarityScoreFrom.apply("s")); } + @Test + void testFailsToCreateSimilarityScoreFromThrowsIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> new SimilarityScoreFrom<>(null, "")); + } + @Test void testGetLeft() { assertEquals("asdf", similarityScoreFrom.getLeft()); @@ -49,9 +54,4 @@ void testGetSimilarityScore() { assertEquals(longestCommonSubsequence, similarityScoreFrom.getSimilarityScore()); } - @Test - void testFailsToCreateSimilarityScoreFromThrowsIllegalArgumentException() { - assertThrows(IllegalArgumentException.class, () -> new SimilarityScoreFrom<>(null, "")); - } - } From cb5d68fd17e249eaac1b73bc7585c2c0c5f374f5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 13:44:31 -0500 Subject: [PATCH 195/265] Sort imports --- .../apache/commons/text/similarity/JaroWinklerDistanceTest.java | 2 +- .../commons/text/similarity/LongestCommonSubsequenceTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java index 7df3a10338..2d63394d16 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java @@ -16,9 +16,9 @@ */ package org.apache.commons.text.similarity; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java b/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java index e5208a2011..2ca0a4b994 100644 --- a/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java @@ -16,9 +16,9 @@ */ package org.apache.commons.text.similarity; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; From 759f19ab636b935a191953abd72e8ef662df7d37 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 13:46:20 -0500 Subject: [PATCH 196/265] Add new tests for the main Levenshtein algorithm implementations #728 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e689fcd749..f8912d2005 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -59,7 +59,7 @@ The type attribute can be add,update,fix,remove. Add Damerau-Levenshtein distance #687. Add unit tests to increase coverage #719. Add new test for CharSequenceTranslator#with() #725. - Add test assertions for SimilarityCharacterInput#equals() #727. + Add tests and assertions to org.apache.commons.text.similarity to get to 100% code coverage #727, #728. Bump org.apache.commons:commons-parent from 85 to 93 #704, #723, #726. Bump commons.bytebuddy.version from 1.17.6 to 1.18.2 #696, #722. From 85f345e9dca78f1efb9f3fdd874bf721596af640 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 15:57:24 -0500 Subject: [PATCH 197/265] Reduce vertical whitespace --- .../text/lookup/StringLookupFactoryTest.java | 48 ++++++------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java index 5ffe49f358..c037aa591a 100644 --- a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java +++ b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java @@ -63,23 +63,17 @@ public static void assertDefaultKeys(final Map stringLooku private static void assertMappedLookups(final Map lookupMap, final String... keys) { final Set remainingKeys = new HashSet<>(lookupMap.keySet()); - for (final String key : keys) { final String normalizedKey = StringLookupFactory.toKey(key); assertNotNull(normalizedKey, () -> "Expected map to contain string lookup for key " + key); - remainingKeys.remove(normalizedKey); } - assertTrue(remainingKeys.isEmpty(), () -> "Unexpected keys in lookup map: " + remainingKeys); } private static void checkDefaultStringLookupsHolder(final Properties props, final String... keys) { - final StringLookupFactory.DefaultStringLookupsHolder holder = - new StringLookupFactory.DefaultStringLookupsHolder(props); - + final StringLookupFactory.DefaultStringLookupsHolder holder = new StringLookupFactory.DefaultStringLookupsHolder(props); final Map lookupMap = holder.getDefaultStringLookups(); - assertMappedLookups(lookupMap, keys); } @@ -90,7 +84,6 @@ private static void checkDefaultStringLookupsHolder(final Properties props, fina public static void main(final String[] args) { final Map lookupMap = new HashMap<>(); StringLookupFactory.INSTANCE.addDefaultStringLookups(lookupMap); - System.out.println("Default string lookups"); for (final String key : lookupMap.keySet()) { System.out.println("- " + key); @@ -139,11 +132,9 @@ void testDefault() { @Test void testDefaultStringLookupsHolder_allLookups() { final Properties props = new Properties(); - props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, - "BASE64_DECODER BASE64_ENCODER const, date, dns, environment " - + "file ,java, local_host properties, resource_bundle,script,system_properties " - + "url url_decoder , url_encoder, xml"); - + props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, "BASE64_DECODER BASE64_ENCODER const, date, dns, environment " + + "file ,java, local_host properties, resource_bundle,script,system_properties url url_decoder , url_encoder, xml"); + // @formatter:off checkDefaultStringLookupsHolder(props, "base64", StringLookupFactory.KEY_BASE64_DECODER, @@ -165,23 +156,20 @@ void testDefaultStringLookupsHolder_allLookups() { StringLookupFactory.KEY_DNS, StringLookupFactory.KEY_URL, StringLookupFactory.KEY_SCRIPT); + // @formatter:on } @Test void testDefaultStringLookupsHolder_givenSingleLookup() { final Properties props = new Properties(); props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, "base64_encoder"); - - checkDefaultStringLookupsHolder(props, - "base64", - StringLookupFactory.KEY_BASE64_ENCODER); + checkDefaultStringLookupsHolder(props, "base64", StringLookupFactory.KEY_BASE64_ENCODER); } @Test void testDefaultStringLookupsHolder_givenSingleLookup_weirdString() { final Properties props = new Properties(); props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, " \n \t ,, DnS , , "); - checkDefaultStringLookupsHolder(props, StringLookupFactory.KEY_DNS); } @@ -189,9 +177,7 @@ void testDefaultStringLookupsHolder_givenSingleLookup_weirdString() { void testDefaultStringLookupsHolder_invalidLookupsDefinition() { final Properties props = new Properties(); props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, "base64_encoder nope"); - - final Exception exc = assertThrows(IllegalArgumentException.class, - () -> new StringLookupFactory.DefaultStringLookupsHolder(props)); + final Exception exc = assertThrows(IllegalArgumentException.class, () -> new StringLookupFactory.DefaultStringLookupsHolder(props)); assertEquals("Invalid default string lookups definition: base64_encoder nope", exc.getMessage()); } @@ -199,17 +185,15 @@ void testDefaultStringLookupsHolder_invalidLookupsDefinition() { void testDefaultStringLookupsHolder_lookupsPropertyEmptyAndBlank() { final Properties propsWithNull = new Properties(); propsWithNull.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, ""); - checkDefaultStringLookupsHolder(propsWithNull); - final Properties propsWithBlank = new Properties(); propsWithBlank.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, " "); - checkDefaultStringLookupsHolder(propsWithBlank); } @Test void testDefaultStringLookupsHolder_lookupsPropertyNotPresent() { + // @formatter:off checkDefaultStringLookupsHolder(new Properties(), "base64", StringLookupFactory.KEY_BASE64_DECODER, @@ -229,17 +213,19 @@ void testDefaultStringLookupsHolder_lookupsPropertyNotPresent() { StringLookupFactory.KEY_XML, StringLookupFactory.KEY_XML_DECODER, StringLookupFactory.KEY_XML_ENCODER); + // @formatter:on } @Test void testDefaultStringLookupsHolder_multipleLookups() { final Properties props = new Properties(); props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, "dns, url script "); - + // @formatter:off checkDefaultStringLookupsHolder(props, StringLookupFactory.KEY_DNS, StringLookupFactory.KEY_URL, StringLookupFactory.KEY_SCRIPT); + // @formatter:on } /** @@ -248,15 +234,12 @@ void testDefaultStringLookupsHolder_multipleLookups() { @Test void testSingletons() { final StringLookupFactory stringLookupFactory = StringLookupFactory.INSTANCE; - assertSame(StringLookupFactory.INSTANCE_BASE64_DECODER, - stringLookupFactory.base64DecoderStringLookup()); - assertSame(StringLookupFactory.INSTANCE_BASE64_ENCODER, - stringLookupFactory.base64EncoderStringLookup()); + assertSame(StringLookupFactory.INSTANCE_BASE64_DECODER, stringLookupFactory.base64DecoderStringLookup()); + assertSame(StringLookupFactory.INSTANCE_BASE64_ENCODER, stringLookupFactory.base64EncoderStringLookup()); assertSame(ConstantStringLookup.INSTANCE, stringLookupFactory.constantStringLookup()); assertSame(DateStringLookup.INSTANCE, stringLookupFactory.dateStringLookup()); assertSame(DnsStringLookup.INSTANCE, stringLookupFactory.dnsStringLookup()); - assertSame(StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES, - stringLookupFactory.environmentVariableStringLookup()); + assertSame(StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES, stringLookupFactory.environmentVariableStringLookup()); assertSame(InterpolatorStringLookup.INSTANCE, stringLookupFactory.interpolatorStringLookup()); assertSame(JavaPlatformStringLookup.INSTANCE, stringLookupFactory.javaPlatformStringLookup()); assertSame(InetAddressStringLookup.LOCAL_HOST, stringLookupFactory.localHostStringLookup()); @@ -264,8 +247,7 @@ void testSingletons() { assertSame(StringLookupFactory.INSTANCE_NULL, stringLookupFactory.nullStringLookup()); assertSame(ResourceBundleStringLookup.INSTANCE, stringLookupFactory.resourceBundleStringLookup()); assertSame(ScriptStringLookup.INSTANCE, stringLookupFactory.scriptStringLookup()); - assertSame(StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES, - stringLookupFactory.systemPropertyStringLookup()); + assertSame(StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES, stringLookupFactory.systemPropertyStringLookup()); assertSame(UrlDecoderStringLookup.INSTANCE, stringLookupFactory.urlDecoderStringLookup()); assertSame(UrlEncoderStringLookup.INSTANCE, stringLookupFactory.urlEncoderStringLookup()); assertSame(UrlStringLookup.INSTANCE, stringLookupFactory.urlStringLookup()); From 0297671c98d184724a6a576186008cd28a7c9a45 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 15:59:53 -0500 Subject: [PATCH 198/265] Move the XmlStringLookup secure toggle to a system property --- pom.xml | 5 +++ .../text/lookup/StringLookupFactory.java | 24 ++++------ .../commons/text/lookup/XmlStringLookup.java | 44 +++++++------------ .../text/lookup/StringLookupFactoryTest.java | 2 + .../text/lookup/XmlStringLookupTest.java | 11 +++-- 5 files changed, 39 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index 0c180d36f2..bcab4f571a 100644 --- a/pom.xml +++ b/pom.xml @@ -92,6 +92,11 @@ junit-jupiter test + + org.junit-pioneer + junit-pioneer + test + net.bytebuddy diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java index 3135f5fae3..863baa7f34 100644 --- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java +++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java @@ -1618,19 +1618,17 @@ public StringLookup xmlEncoderStringLookup() { * if a lookup causes causes a path to resolve outside of these fences. Otherwise, the result is unfenced to preserved behavior from previous versions. *

    *

    - * We looks up values in an XML document in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. + * We looks up values in an XML document in the format {@code "DocumentPath:XPath"}. *

    *

    * For example: *

    *
      *
    • {@code "com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • *
    *

    - * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure - * value in the key overrides instance settings given in the constructor. + * Secure processing is enabled by default and can be overridden with the system property {@code "XmlStringLookup.secure"} set to {@code false}. The secure + * boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. *

    *

    * Using a {@link StringLookup} from the {@link StringLookupFactory}: @@ -1664,19 +1662,17 @@ public StringLookup xmlStringLookup() { * if a lookup causes causes a path to resolve outside of these fences. Otherwise, the result is unfenced to preserved behavior from previous versions. *

    *

    - * We looks up values in an XML document in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. + * We looks up values in an XML document in the format {@code "]DocumentPath:XPath"}. *

    *

    * For example: *

    *
      *
    • {@code "com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • *
    *

    - * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure - * value in the key overrides instance settings given in the constructor. + * Secure processing is enabled by default and can be overridden with the system property {@code "XmlStringLookup.secure"} set to {@code false}. The secure + * boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. *

    *

    * Using a {@link StringLookup} from the {@link StringLookupFactory}: @@ -1713,19 +1709,17 @@ public StringLookup xmlStringLookup(final Map factoryFeatures) * if a lookup causes causes a path to resolve outside of these fences. Otherwise, the result is unfenced to preserved behavior from previous versions. *

    *

    - * We looks up values in an XML document in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. + * We looks up values in an XML document in the format {@code "DocumentPath:XPath"}. *

    *

    * For example: *

    *
      *
    • {@code "com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • *
    *

    - * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure - * value in the key overrides instance settings given in the constructor. + * Secure processing is enabled by default and can be overridden with the system property {@code "XmlStringLookup.secure"} set to {@code false}. The secure + * boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. *

    *

    * Using a {@link StringLookup} from the {@link StringLookupFactory} fenced by the current directory ({@code Paths.get("")}): diff --git a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java index aa873a0088..26739c02b8 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java @@ -30,21 +30,20 @@ import javax.xml.xpath.XPathFactory; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.SystemProperties; import org.w3c.dom.Document; /** - * Looks up values in an XML document in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. + * Looks up values in an XML document in the format {@code "DocumentPath:XPath"}. *

    * For example: *

    *
      *
    • {@code "com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • *
    *

    - * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure - * value in the key overrides instance settings given in the constructor. + * Secure processing is enabled by default and can be overridden with the system property {@code "XmlStringLookup.secure"} set to {@code false}. The secure + * boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. *

    * * @since 1.5 @@ -52,14 +51,9 @@ final class XmlStringLookup extends AbstractPathFencedLookup { /** - * Minimum number of key parts. + * The number of key parts. */ - private static final int KEY_PARTS_MIN = 2; - - /** - * Minimum number of key parts. - */ - private static final int KEY_PARTS_MAX = 3; + private static final int KEY_PARTS_LEN = 2; /** * Defines default XPath factory features. @@ -76,11 +70,16 @@ final class XmlStringLookup extends AbstractPathFencedLookup { DEFAULT_XML_FEATURES = new HashMap<>(1); DEFAULT_XML_FEATURES.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); } + /** * Defines the singleton for this class with secure processing enabled. */ static final XmlStringLookup INSTANCE = new XmlStringLookup(DEFAULT_XML_FEATURES, DEFAULT_XPATH_FEATURES, (Path[]) null); + private static boolean isSecure() { + return SystemProperties.getBoolean(XmlStringLookup.class, "secure", () -> true); + } + /** * Defines XPath factory features. */ @@ -106,14 +105,12 @@ final class XmlStringLookup extends AbstractPathFencedLookup { } /** - * Looks up a value for the key in the format {@code "[secure=(true|false):]DocumentPath:XPath"}. + * Looks up a value for the key in the format {@code "DocumentPath:XPath"}. *

    * For example: *

    *
      *
    • {@code "com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=false:com/domain/document.xml:/path/to/node"}
    • - *
    • {@code "secure=true:com/domain/document.xml:/path/to/node"}
    • *
    *

    * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure @@ -130,12 +127,11 @@ public String lookup(final String key) { } final String[] keys = key.split(SPLIT_STR); final int keyLen = keys.length; - if (keyLen != KEY_PARTS_MIN && keyLen != KEY_PARTS_MAX) { - throw IllegalArgumentExceptions.format("Bad XML key format '%s'; the expected format is [secure=(true|false):]DocumentPath:XPath.", key); + if (keyLen != KEY_PARTS_LEN) { + throw IllegalArgumentExceptions.format("Bad XML key format '%s'; the expected format is 'DocumentPath:XPath'.", key); } - final boolean isKeySecure = keyLen == KEY_PARTS_MAX; - final Boolean secure = isKeySecure ? parseSecureKey(keys, key) : null; - final String documentPath = isKeySecure ? keys[1] : keys[0]; + final Boolean secure = isSecure(); + final String documentPath = keys[0]; final String xpath = StringUtils.substringAfterLast(key, SPLIT_CH); final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); try { @@ -160,12 +156,4 @@ public String lookup(final String key) { throw new IllegalArgumentException(e); } } - - private Boolean parseSecureKey(final String[] args, final String key) { - final String[] secParts = args[0].split("="); - if (secParts.length != 2 && !Objects.equals(secParts[0], "secure")) { - throw IllegalArgumentExceptions.format("Bad XML key format '%s'; the expected format is [secure=(true|false):]DocumentPath:XPath.", key); - } - return Boolean.valueOf(secParts[1]); - } } diff --git a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java index c037aa591a..bdc6cac1f3 100644 --- a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java +++ b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java @@ -32,6 +32,7 @@ import javax.xml.XMLConstants; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetSystemProperty; /** * Tests {@link StringLookupFactory}. @@ -272,6 +273,7 @@ void testXmlStringLookupExternalEntityOff() { } @Test + @SetSystemProperty(key = "XmlStringLookup.secure", value = "false") void testXmlStringLookupExternalEntityOn() { final String key = XmlStringLookupTest.DOC_DIR + "document-entity-ref.xml:/document/content"; assertEquals(XmlStringLookupTest.DATA, StringLookupFactory.INSTANCE.xmlStringLookup(XmlStringLookupTest.EMPTY_MAP).apply(key).trim()); diff --git a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java index a37cafbead..ead417ddec 100644 --- a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java @@ -35,6 +35,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringSubstitutor; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetSystemProperty; /** * Tests {@link XmlStringLookup}. @@ -68,6 +69,7 @@ void testExternalEntityOff() { } @Test + @SetSystemProperty(key = "XmlStringLookup.secure", value = "false") void testExternalEntityOn() { final String key = DOC_DIR + "document-entity-ref.xml:/document/content"; assertEquals(DATA, new XmlStringLookup(EMPTY_MAP, EMPTY_MAP).apply(key).trim()); @@ -81,9 +83,10 @@ void testInterpolatorExternalEntityOff() { } @Test + @SetSystemProperty(key = "XmlStringLookup.secure", value = "false") void testInterpolatorExternalEntityOffOverride() { final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); - assertEquals(DATA, stringSubstitutor.replace("${xml:secure=false:" + DOC_DIR + "document-entity-ref.xml:/document/content}").trim()); + assertEquals(DATA, stringSubstitutor.replace("${xml:" + DOC_DIR + "document-entity-ref.xml:/document/content}").trim()); } @Test @@ -93,18 +96,18 @@ void testInterpolatorExternalEntityOn() { } @Test + @SetSystemProperty(key = "XmlStringLookup.secure", value = "true") void testInterpolatorExternalEntityOnOverride() { final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); assertThrows(IllegalArgumentException.class, - () -> stringSubstitutor.replace("${xml:secure=true:" + DOC_DIR + "document-entity-ref.xml:/document/content}")); + () -> stringSubstitutor.replace("${xml:" + DOC_DIR + "document-entity-ref.xml:/document/content}")); } @Test void testInterpolatorSecureOnBla() { final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:" + DOC_DIR + "bla.xml:/document/content}")); - assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:secure=true:" + DOC_DIR + "bla.xml:/document/content}")); - // Using secure=false allows the BLA to occur. + // Using XmlStringLookup.secure=false allows the BLA to occur. } @Test From bb508f304a8835ac2319af1d872b2f1a9ff6f81d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 16:07:42 -0500 Subject: [PATCH 199/265] Bump actions/checkout from 6.0.0 to 6.0.1 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/maven.yml | 2 +- .github/workflows/scorecards-analysis.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 62500fe146..b47769e0ee 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index b58ce93016..1df8666044 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: 'Dependency Review PR' uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 882c73abbd..d2aef55fa4 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -34,7 +34,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: Set up JDK ${{ matrix.java }} diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 4f87551686..bcb94cd7f5 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -40,7 +40,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false From ed3df4b25cd5301921a6523ae7db2411f4a84d98 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 17:23:54 -0500 Subject: [PATCH 200/265] Internal clean up --- .../commons/text/lookup/XmlStringLookup.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java index 26739c02b8..85747eebc2 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java @@ -130,7 +130,7 @@ public String lookup(final String key) { if (keyLen != KEY_PARTS_LEN) { throw IllegalArgumentExceptions.format("Bad XML key format '%s'; the expected format is 'DocumentPath:XPath'.", key); } - final Boolean secure = isSecure(); + final boolean secure = isSecure(); final String documentPath = keys[0]; final String xpath = StringUtils.substringAfterLast(key, SPLIT_CH); final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); @@ -138,19 +138,15 @@ public String lookup(final String key) { for (final Entry p : xmlFactoryFeatures.entrySet()) { dbFactory.setFeature(p.getKey(), p.getValue()); } - if (secure != null) { - dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure.booleanValue()); - } + dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); try (InputStream inputStream = Files.newInputStream(getPath(documentPath))) { final Document doc = dbFactory.newDocumentBuilder().parse(inputStream); - final XPathFactory factory = XPathFactory.newInstance(); + final XPathFactory xpFactory = XPathFactory.newInstance(); for (final Entry p : xPathFactoryFeatures.entrySet()) { - factory.setFeature(p.getKey(), p.getValue()); - } - if (secure != null) { - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure.booleanValue()); + xpFactory.setFeature(p.getKey(), p.getValue()); } - return factory.newXPath().evaluate(xpath, doc); + xpFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); + return xpFactory.newXPath().evaluate(xpath, doc); } } catch (final Exception e) { throw new IllegalArgumentException(e); From 1c2d3821e67e08342b8cef4d4445c30b4a22daca Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Wed, 3 Dec 2025 23:44:05 +0100 Subject: [PATCH 201/265] Add tests with external DTD Add tests for `XmlStringLookup` with an external DTD. --- .../text/lookup/XmlStringLookupTest.java | 15 ++++++++++++ .../commons/text/document-external-dtd.dtd | 20 ++++++++++++++++ .../commons/text/document-external-dtd.xml | 24 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 src/test/resources/org/apache/commons/text/document-external-dtd.dtd create mode 100644 src/test/resources/org/apache/commons/text/document-external-dtd.xml diff --git a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java index ead417ddec..f0cc50ba96 100644 --- a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java @@ -76,6 +76,21 @@ void testExternalEntityOn() { assertEquals(DATA, new XmlStringLookup(EMPTY_MAP, XmlStringLookup.DEFAULT_XPATH_FEATURES).apply(key).trim()); } + @Test + void testInterpolatorExternalDtdOff() { + final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); + assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:" + DOC_DIR + + "document-external-dtd.xml:/document/content}")); + } + + @Test + @SetSystemProperty(key = "XmlStringLookup.secure", value = "false") + void testInterpolatorExternalDtdOn() { + final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); + assertEquals("This is an external entity.", + stringSubstitutor.replace("${xml:" + DOC_DIR + "document-external-dtd.xml:/document/content}").trim()); + } + @Test void testInterpolatorExternalEntityOff() { final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); diff --git a/src/test/resources/org/apache/commons/text/document-external-dtd.dtd b/src/test/resources/org/apache/commons/text/document-external-dtd.dtd new file mode 100644 index 0000000000..dbc9ca746b --- /dev/null +++ b/src/test/resources/org/apache/commons/text/document-external-dtd.dtd @@ -0,0 +1,20 @@ + + + + + diff --git a/src/test/resources/org/apache/commons/text/document-external-dtd.xml b/src/test/resources/org/apache/commons/text/document-external-dtd.xml new file mode 100644 index 0000000000..158f5d8336 --- /dev/null +++ b/src/test/resources/org/apache/commons/text/document-external-dtd.xml @@ -0,0 +1,24 @@ + + + + + Example of an External Entity + + &externalEntity; + + From b0ddbd17bbeee12ad33b8a61c60b4edbe6c85838 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Dec 2025 07:42:57 -0500 Subject: [PATCH 202/265] Bump actions/setup-java from 5.0.0 to 5.1.0 --- .github/workflows/maven.yml | 2 +- .../java/org/apache/commons/text/lookup/XmlStringLookup.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index d2aef55fa4..30ddf451ed 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -38,7 +38,7 @@ jobs: with: persist-credentials: false - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} diff --git a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java index 85747eebc2..8f129396ab 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java @@ -138,14 +138,14 @@ public String lookup(final String key) { for (final Entry p : xmlFactoryFeatures.entrySet()) { dbFactory.setFeature(p.getKey(), p.getValue()); } - dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); + //dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); try (InputStream inputStream = Files.newInputStream(getPath(documentPath))) { final Document doc = dbFactory.newDocumentBuilder().parse(inputStream); final XPathFactory xpFactory = XPathFactory.newInstance(); for (final Entry p : xPathFactoryFeatures.entrySet()) { xpFactory.setFeature(p.getKey(), p.getValue()); } - xpFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); + //xpFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); return xpFactory.newXPath().evaluate(xpath, doc); } } catch (final Exception e) { From 2e2d4bc90f1b3274e7943ac27d037d47c0cc098d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Dec 2025 07:43:20 -0500 Subject: [PATCH 203/265] Revert "Bump actions/setup-java from 5.0.0 to 5.1.0" This reverts commit b0ddbd17bbeee12ad33b8a61c60b4edbe6c85838. --- .github/workflows/maven.yml | 2 +- .../java/org/apache/commons/text/lookup/XmlStringLookup.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 30ddf451ed..d2aef55fa4 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -38,7 +38,7 @@ jobs: with: persist-credentials: false - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} diff --git a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java index 8f129396ab..85747eebc2 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java @@ -138,14 +138,14 @@ public String lookup(final String key) { for (final Entry p : xmlFactoryFeatures.entrySet()) { dbFactory.setFeature(p.getKey(), p.getValue()); } - //dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); + dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); try (InputStream inputStream = Files.newInputStream(getPath(documentPath))) { final Document doc = dbFactory.newDocumentBuilder().parse(inputStream); final XPathFactory xpFactory = XPathFactory.newInstance(); for (final Entry p : xPathFactoryFeatures.entrySet()) { xpFactory.setFeature(p.getKey(), p.getValue()); } - //xpFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); + xpFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); return xpFactory.newXPath().evaluate(xpath, doc); } } catch (final Exception e) { From b5052c97e84e1c174ec8bfbbb749e33f22917a07 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Dec 2025 07:43:42 -0500 Subject: [PATCH 204/265] Bump actions/setup-java from 5.0.0 to 5.1.0 --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index d2aef55fa4..30ddf451ed 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -38,7 +38,7 @@ jobs: with: persist-credentials: false - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} From 58e1e125daaa0aebf8c5ffaa82af48821a1ccf2d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Dec 2025 10:27:20 -0500 Subject: [PATCH 205/265] Simplify XML FSP (#731) * Simplify XML FSP * Simplify XML FSP --- src/changes/changes.xml | 2 +- .../text/lookup/StringLookupFactory.java | 5 ++--- .../commons/text/lookup/XmlStringLookup.java | 19 ++++++------------- .../text/lookup/XmlStringLookupTest.java | 15 +++++---------- 4 files changed, 14 insertions(+), 27 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f8912d2005..9a4b221ebc 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,7 +53,7 @@ The type attribute can be add,update,fix,remove. Fix Apache RAT plugin console warnings. Fix site XML to use version 2.0.0 XML schema. Removed unreachable threshold verification code in src/main/java/org/apache/commons/text/similarity #730. - Enable secure processing for the XML parser in XmlStringLookup #729. + Enable secure processing for the XML parser in XmlStringLookup in case the underlying JAXP implementation doesn't #729. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java index 863baa7f34..699b7deab7 100644 --- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java +++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java @@ -1718,15 +1718,14 @@ public StringLookup xmlStringLookup(final Map factoryFeatures) *

  • {@code "com/domain/document.xml:/path/to/node"}
  • * *

    - * Secure processing is enabled by default and can be overridden with the system property {@code "XmlStringLookup.secure"} set to {@code false}. The secure - * boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. + * Secure processing is enabled by default and can be overridden with this constructor. *

    *

    * Using a {@link StringLookup} from the {@link StringLookupFactory} fenced by the current directory ({@code Paths.get("")}): *

    * *
    -     * StringLookupFactory.INSTANCE.xmlStringLookup(map, Pathe.get("")).lookup("com/domain/document.xml:/path/to/node");
    +     * StringLookupFactory.INSTANCE.xmlStringLookup(map, Path.get("")).lookup("com/domain/document.xml:/path/to/node");
          * 
    *

    * To use a {@link StringLookup} fenced by the current directory, use: diff --git a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java index 85747eebc2..ee33441993 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java @@ -30,7 +30,6 @@ import javax.xml.xpath.XPathFactory; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.SystemProperties; import org.w3c.dom.Document; /** @@ -42,8 +41,7 @@ *

  • {@code "com/domain/document.xml:/path/to/node"}
  • * *

    - * Secure processing is enabled by default and can be overridden with the system property {@code "XmlStringLookup.secure"} set to {@code false}. The secure - * boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. + * Secure processing is enabled by default and can be overridden with {@link StringLookupFactory#xmlStringLookup(Map, Path...)}. *

    * * @since 1.5 @@ -72,14 +70,13 @@ final class XmlStringLookup extends AbstractPathFencedLookup { } /** - * Defines the singleton for this class with secure processing enabled. + * Defines the singleton for this class with secure processing enabled by default. + *

    + * Secure processing is enabled by default and can be overridden with {@link StringLookupFactory#xmlStringLookup(Map, Path...)}. + *

    */ static final XmlStringLookup INSTANCE = new XmlStringLookup(DEFAULT_XML_FEATURES, DEFAULT_XPATH_FEATURES, (Path[]) null); - private static boolean isSecure() { - return SystemProperties.getBoolean(XmlStringLookup.class, "secure", () -> true); - } - /** * Defines XPath factory features. */ @@ -113,8 +110,7 @@ private static boolean isSecure() { *
  • {@code "com/domain/document.xml:/path/to/node"}
  • * *

    - * Secure processing is enabled by default. The secure boolean String parsing follows the syntax defined by {@link Boolean#parseBoolean(String)}. The secure - * value in the key overrides instance settings given in the constructor. + * Secure processing is enabled by default and can be overridden with {@link StringLookupFactory#xmlStringLookup(Map, Path...)}. *

    * * @param key the key to be looked up, may be null. @@ -130,7 +126,6 @@ public String lookup(final String key) { if (keyLen != KEY_PARTS_LEN) { throw IllegalArgumentExceptions.format("Bad XML key format '%s'; the expected format is 'DocumentPath:XPath'.", key); } - final boolean secure = isSecure(); final String documentPath = keys[0]; final String xpath = StringUtils.substringAfterLast(key, SPLIT_CH); final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); @@ -138,14 +133,12 @@ public String lookup(final String key) { for (final Entry p : xmlFactoryFeatures.entrySet()) { dbFactory.setFeature(p.getKey(), p.getValue()); } - dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); try (InputStream inputStream = Files.newInputStream(getPath(documentPath))) { final Document doc = dbFactory.newDocumentBuilder().parse(inputStream); final XPathFactory xpFactory = XPathFactory.newInstance(); for (final Entry p : xPathFactoryFeatures.entrySet()) { xpFactory.setFeature(p.getKey(), p.getValue()); } - xpFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure); return xpFactory.newXPath().evaluate(xpath, doc); } } catch (final Exception e) { diff --git a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java index f0cc50ba96..7327bca7ef 100644 --- a/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/XmlStringLookupTest.java @@ -69,7 +69,6 @@ void testExternalEntityOff() { } @Test - @SetSystemProperty(key = "XmlStringLookup.secure", value = "false") void testExternalEntityOn() { final String key = DOC_DIR + "document-entity-ref.xml:/document/content"; assertEquals(DATA, new XmlStringLookup(EMPTY_MAP, EMPTY_MAP).apply(key).trim()); @@ -79,16 +78,14 @@ void testExternalEntityOn() { @Test void testInterpolatorExternalDtdOff() { final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); - assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:" + DOC_DIR - + "document-external-dtd.xml:/document/content}")); + assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:" + DOC_DIR + "document-external-dtd.xml:/document/content}")); } @Test - @SetSystemProperty(key = "XmlStringLookup.secure", value = "false") + @SetSystemProperty(key = "javax.xml.accessExternalDTD", value = "file") void testInterpolatorExternalDtdOn() { final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); - assertEquals("This is an external entity.", - stringSubstitutor.replace("${xml:" + DOC_DIR + "document-external-dtd.xml:/document/content}").trim()); + assertEquals("This is an external entity.", stringSubstitutor.replace("${xml:" + DOC_DIR + "document-external-dtd.xml:/document/content}").trim()); } @Test @@ -98,7 +95,7 @@ void testInterpolatorExternalEntityOff() { } @Test - @SetSystemProperty(key = "XmlStringLookup.secure", value = "false") + @SetSystemProperty(key = "javax.xml.accessExternalDTD", value = "file") void testInterpolatorExternalEntityOffOverride() { final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); assertEquals(DATA, stringSubstitutor.replace("${xml:" + DOC_DIR + "document-entity-ref.xml:/document/content}").trim()); @@ -111,11 +108,9 @@ void testInterpolatorExternalEntityOn() { } @Test - @SetSystemProperty(key = "XmlStringLookup.secure", value = "true") void testInterpolatorExternalEntityOnOverride() { final StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator(); - assertThrows(IllegalArgumentException.class, - () -> stringSubstitutor.replace("${xml:" + DOC_DIR + "document-entity-ref.xml:/document/content}")); + assertThrows(IllegalArgumentException.class, () -> stringSubstitutor.replace("${xml:" + DOC_DIR + "document-entity-ref.xml:/document/content}")); } @Test From c6e17ec24cc8374eb12676b717bf797f41b6e539 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Dec 2025 10:42:56 -0500 Subject: [PATCH 206/265] Use direct access - Javadoc - Test deprecated and not --- .../commons/text/similarity/JaroWinklerDistance.java | 3 ++- .../commons/text/similarity/JaroWinklerDistanceTest.java | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java b/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java index 8bd8d7b7a8..e2e3d0df3f 100644 --- a/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/JaroWinklerDistance.java @@ -36,7 +36,8 @@ public class JaroWinklerDistance implements EditDistance { * @param first the first string to be matched. * @param second the second string to be matched. * @return array containing: matches, half transpositions, and prefix - * @deprecated Deprecated as of 1.7. This method will be removed in 2.0, and moved to a Jaro Winkler similarity class. TODO see TEXT-104. + * @deprecated Deprecated as of 1.7, use {@link JaroWinklerSimilarity#matches(CharSequence, CharSequence)}. This method will be removed in 2.0. TODO see + * TEXT-104. */ @Deprecated protected static int[] matches(final CharSequence first, final CharSequence second) { diff --git a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java index 2d63394d16..0f4ee10c04 100644 --- a/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/JaroWinklerDistanceTest.java @@ -108,7 +108,13 @@ void testGetJaroWinklerDistance_StringString() { @Test void testMatches() { - assertArrayEquals(new int[]{2, 0, 2}, distance.matches("ab", "aba")); + assertArrayEquals(new int[]{2, 0, 2}, JaroWinklerSimilarity.matches("ab", "aba")); + } + + @SuppressWarnings("deprecation") + @Test + void testMatchesDeprecated() { + assertArrayEquals(new int[]{2, 0, 2}, JaroWinklerDistance.matches("ab", "aba")); } } From 502c4c41be5671681b58a9b50297f99737e8ea93 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Dec 2025 15:53:32 +0000 Subject: [PATCH 207/265] Prepare for the next release candidate --- README.md | 6 ++-- RELEASE-NOTES.txt | 59 ++++++++++++++++++++++++++++++-- src/changes/changes.xml | 4 +-- src/changes/release-notes.vm | 2 +- src/site/xdoc/download_text.xml | 28 +++++++-------- src/site/xdoc/issue-tracking.xml | 2 +- src/site/xdoc/mail-lists.xml | 2 +- 7 files changed, 79 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 81333cf313..3cd07a15d7 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Apache Commons Text [![Java CI](https://github.com/apache/commons-text/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/commons-text/actions/workflows/maven.yml) [![Maven Central](https://img.shields.io/maven-central/v/org.apache.commons/commons-text?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.commons/commons-text) -[![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-text/1.14.0.svg)](https://javadoc.io/doc/org.apache.commons/commons-text/1.14.0) +[![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-text/1.15.0.svg)](https://javadoc.io/doc/org.apache.commons/commons-text/1.15.0) [![CodeQL](https://github.com/apache/commons-text/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/apache/commons-text/actions/workflows/codeql-analysis.yml) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/commons-text/badge)](https://api.securityscorecards.dev/projects/github.com/apache/commons-text) @@ -69,7 +69,7 @@ Alternatively, you can pull it from the central Maven repositories: org.apache.commons commons-text - 1.14.0 + 1.15.0 ``` @@ -90,7 +90,7 @@ There are some guidelines which will make applying PRs easier for us: + Respect the existing code style for each file. + Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change. + Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running `mvn`. -+ Before you pushing a PR, run `mvn` (by itself), this runs the default goal, which contains all build checks. ++ Before you push a PR, run `mvn` (without arguments). This runs the default goal which contains all build checks. + To see the code coverage report, regardless of coverage failures, run `mvn clean site -Dcommons.jacoco.haltOnFailure=false -Pjacoco` If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas). diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index f3e1471648..f299b31453 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -14,8 +14,63 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +Apache Commons Text 1.15.0 Release Notes +---------------------------------------- + +The Apache Commons Text team is pleased to announce the release of Apache Commons Text 1.15.0. + +Apache Commons Text is a set of utility functions and reusable components for processing +and manipulating text in a Java environment. + +Release 1.15.0. This is a feature and maintenance release. Java 8 or later is required. + + +New features +------------ + +* Add experimental CycloneDX VEX file #683. Thanks to Piotr P. Karwasz, Gary Gregory. +* TEXT-235: Add Damerau-Levenshtein distance #687. Thanks to LorgeN, Gary Gregory. +* Add unit tests to increase coverage #719. Thanks to Michael Hausegger, Gary Gregory. +* Add new test for CharSequenceTranslator#with() #725. Thanks to Michael Hausegger, Gary Gregory. +* Add tests and assertions to org.apache.commons.text.similarity to get to 100% code coverage #727, #728. Thanks to Michael Hausegger. + +Fixed Bugs +---------- + +* Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). Thanks to Gary Gregory. +* TEXT-236: Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. Thanks to Pierre Post, Sumit Bera, Alex Herbert, Gary Gregory. +* Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724. Thanks to Michael Hausegger. +* Fix Apache RAT plugin console warnings. Thanks to Gary Gregory. +* Fix site XML to use version 2.0.0 XML schema. Thanks to Gary Gregory. +* Removed unreachable threshold verification code in src/main/java/org/apache/commons/text/similarity #730. Thanks to Michael Hausegger. +* Enable secure processing for the XML parser in XmlStringLookup in case the underlying JAXP implementation doesn't #729. Thanks to 김ë¯ŧėžŦ (minjas0507), Gary Gregory, Piotr Karwasz. + +Changes +------- + +* Bump org.apache.commons:commons-parent from 85 to 93 #704, #723, #726. Thanks to Gary Gregory. +* Bump commons.bytebuddy.version from 1.17.6 to 1.18.2 #696, #722. Thanks to Gary Gregory. +* Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. Thanks to Gary Gregory, Dependabot. +* Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Thanks to Gary Gregory. +* Bump commons-io:commons-io from 2.20.0 to 2.21.0. Thanks to Gary Gregory. + + +Historical list of changes: https://commons.apache.org/proper/commons-text/changes.html + +For complete information on Apache Commons Text, including instructions on how to submit bug reports, +patches, or suggestions for improvement, see the Apache Commons Text website: + +https://commons.apache.org/proper/commons-text + +Download page: https://commons.apache.org/proper/commons-text/download_text.cgi + +Have fun! +-Apache Commons Team + +----------------------------------------------------------------------------- + Apache Commons Text 1.14.0 Release Notes ------------------------------------------------- +---------------------------------------- The Apache Commons Text team is pleased to announce the release of Apache Commons Text 1.14.0. @@ -327,7 +382,7 @@ New features * TEXT-207: Add DoubleFormat utility. * TEXT-190: Document negative limit for WordUtils abbreviate method Thanks to Benjamin Bing. -* TEXT-188: Speed up LevenshteinDistance with threshold by exiting early Thanks to Jakob Vesterstrøm. +* TEXT-188: Speed up LevenshteinDistance with threshold by exiting early Thanks to Jakob Vesterstrøm. * TEXT-185: Release Notes page hasn't been updated for 1.9 release yet. Thanks to Larry West, Gary Gregory. * Add StrBuilder.isNotEmpty(). Thanks to Gary Gregory. diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 9a4b221ebc..3f2071af29 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -45,7 +45,7 @@ The type attribute can be add,update,fix,remove. Apache Commons Text Changes - + Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. @@ -53,7 +53,7 @@ The type attribute can be add,update,fix,remove. Fix Apache RAT plugin console warnings. Fix site XML to use version 2.0.0 XML schema. Removed unreachable threshold verification code in src/main/java/org/apache/commons/text/similarity #730. - Enable secure processing for the XML parser in XmlStringLookup in case the underlying JAXP implementation doesn't #729. + Enable secure processing for the XML parser in XmlStringLookup in case the underlying JAXP implementation doesn't #729. Add experimental CycloneDX VEX file #683. Add Damerau-Levenshtein distance #687. diff --git a/src/changes/release-notes.vm b/src/changes/release-notes.vm index c9f6686a7e..35e7a381b8 100644 --- a/src/changes/release-notes.vm +++ b/src/changes/release-notes.vm @@ -32,7 +32,7 @@ See the License for the specific language governing permissions and limitations under the License. ${project.name} ${version} Release Notes ------------------------------------------------- +---------------------------------------- The ${developmentTeam} is pleased to announce the release of ${project.name} ${version}. diff --git a/src/site/xdoc/download_text.xml b/src/site/xdoc/download_text.xml index 4f7cbc7c3a..e2a425aa83 100644 --- a/src/site/xdoc/download_text.xml +++ b/src/site/xdoc/download_text.xml @@ -58,7 +58,7 @@ limitations under the License. --> + xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Download Apache Commons Text Apache Commons Team @@ -115,32 +115,32 @@ limitations under the License.

    -
    +
    - - - + + + - - - + + +
    commons-text-1.14.0-bin.tar.gzsha512pgpcommons-text-1.15.0-bin.tar.gzsha512pgp
    commons-text-1.14.0-bin.zipsha512pgpcommons-text-1.15.0-bin.zipsha512pgp
    - - - + + + - - - + + +
    commons-text-1.14.0-src.tar.gzsha512pgpcommons-text-1.15.0-src.tar.gzsha512pgp
    commons-text-1.14.0-src.zipsha512pgpcommons-text-1.15.0-src.zipsha512pgp
    diff --git a/src/site/xdoc/issue-tracking.xml b/src/site/xdoc/issue-tracking.xml index 9ef2de7e3f..83219a0dd5 100644 --- a/src/site/xdoc/issue-tracking.xml +++ b/src/site/xdoc/issue-tracking.xml @@ -43,7 +43,7 @@ limitations under the License. --> + xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons Text Issue tracking Apache Commons Team diff --git a/src/site/xdoc/mail-lists.xml b/src/site/xdoc/mail-lists.xml index c8734db5fb..806e21bb19 100644 --- a/src/site/xdoc/mail-lists.xml +++ b/src/site/xdoc/mail-lists.xml @@ -41,7 +41,7 @@ limitations under the License. --> + xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons Text Mailing Lists Apache Commons Team From 04e937470d3679cc163df85d82d5b6d2e3e71128 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Dec 2025 15:55:50 +0000 Subject: [PATCH 208/265] Prepare for the release candidate 1.15.0 RC1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index bcab4f571a..325a76ce79 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 93 commons-text - 1.15.0-SNAPSHOT + 1.15.0 Apache Commons Text Apache Commons Text is a set of utility functions and reusable components for processing and manipulating text in a Java environment. @@ -33,7 +33,7 @@ ISO-8859-1 UTF-8 - 2025-07-24T12:03:40Z + 2025-12-04T15:53:46Z 1.8 1.8 text From e680120e74a56e51ecff52713cb5167cbcc47867 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 5 Dec 2025 07:33:40 -0500 Subject: [PATCH 209/265] Fix benchmarks --- pom.xml | 36 +++++++++++++++++-- .../LongestCommonSubsequencePerformance.java | 8 ++--- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index bcab4f571a..f159e87218 100644 --- a/pom.xml +++ b/pom.xml @@ -598,13 +598,45 @@ + benchmark true org.apache + + + org.openjdk.jmh + jmh-core + ${commons.jmh.version} + test + + + org.openjdk.jmh + jmh-generator-annprocess + ${commons.jmh.version} + test + + + org.apache.commons + commons-collections4 + 4.5.0 + test + + + + + maven-compiler-plugin + ${commons.compiler.version} + + + **/* + + + + org.codehaus.mojo exec-maven-plugin @@ -620,12 +652,12 @@ java -classpath - + org.openjdk.jmh.Main -rf json -rff - target/jmh-result.${benchmark}.json + target/jmh-result.json ${benchmark} diff --git a/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java b/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java index a810e1167c..eef5f9d30e 100644 --- a/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java +++ b/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java @@ -134,7 +134,7 @@ public void setup() { } @Benchmark - void testLCS(final InputData data) { + public void testLCS(final InputData data) { final LongestCommonSubsequence lcs = new LongestCommonSubsequence(); for (final Pair input : data.inputs) { lcs.longestCommonSubsequence(input.getLeft(), input.getRight()); @@ -142,7 +142,7 @@ void testLCS(final InputData data) { } @Benchmark - void testLCSBaseline(final InputData data) { + public void testLCSBaseline(final InputData data) { final BaselineLongestCommonSubsequence lcs = new BaselineLongestCommonSubsequence(); for (final Pair input : data.inputs) { lcs.longestCommonSubsequence(input.getLeft(), input.getRight()); @@ -150,7 +150,7 @@ void testLCSBaseline(final InputData data) { } @Benchmark - void testLCSLen(final InputData data) { + public void testLCSLen(final InputData data) { final LongestCommonSubsequence lcs = new LongestCommonSubsequence(); for (final Pair input : data.inputs) { lcs.apply(input.getLeft(), input.getRight()); @@ -158,7 +158,7 @@ void testLCSLen(final InputData data) { } @Benchmark - void testLCSLenBaseline(final InputData data) { + public void testLCSLenBaseline(final InputData data) { final BaselineLongestCommonSubsequence lcs = new BaselineLongestCommonSubsequence(); for (final Pair input : data.inputs) { lcs.apply(input.getLeft(), input.getRight()); From d6d521ad37e07e0a71fb4170f7be468287cc0229 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 5 Dec 2025 08:19:57 -0500 Subject: [PATCH 210/265] Fix benchmark Add license header --- pom.xml | 7 +++- .../LongestCommonSubsequencePerformance.java | 33 +++++++++---------- .../commons/text/lcs-perf-analysis-inputs.csv | 16 ++++++++- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index f159e87218..8790371545 100644 --- a/pom.xml +++ b/pom.xml @@ -135,6 +135,12 @@ ${jmh.version} test + + org.apache.commons + commons-csv + 1.14.1 + test + clean verify apache-rat:check japicmp:cmp checkstyle:check pmd:check spotbugs:check javadoc:javadoc @@ -149,7 +155,6 @@ src/site/resources/download_text.cgi src/site/resources/release-notes/RELEASE-NOTES-*.txt src/test/resources/org/apache/commons/text/stringEscapeUtilsTestData.txt - src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv src/test/resources/org/apache/commons/text/oss-fuzz/** diff --git a/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java b/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java index eef5f9d30e..49d1318ed3 100644 --- a/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java +++ b/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java @@ -16,16 +16,14 @@ */ package org.apache.commons.text.jmh; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; -import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.TimeUnit; +import org.apache.commons.csv.CSVFormat; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.text.similarity.LongestCommonSubsequence; @@ -114,22 +112,21 @@ public static class InputData { final List> inputs = new ArrayList<>(); @Setup(Level.Trial) - public void setup() { + public void setup() throws IOException { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - try (InputStream is = classLoader.getResourceAsStream("org/apache/commons/text/lcs-perf-analysis-inputs.csv"); - InputStreamReader isr = new InputStreamReader(Objects.requireNonNull(is)); - BufferedReader br = new BufferedReader(isr)) { - String line; - while ((line = br.readLine()) != null && !line.trim().isEmpty()) { - line = line.trim(); - final int indexOfComma = line.indexOf(','); - final String inputA = line.substring(0, indexOfComma); - final String inputB = line.substring(1 + indexOfComma); - this.inputs.add(ImmutablePair.of(inputA, inputB)); - } - } catch (final IOException exception) { - throw new UncheckedIOException(exception.getMessage(), exception); - } + CSVFormat.DEFAULT.builder().setCommentMarker('#').setTrim(true).get() + .parse(new InputStreamReader( + Objects.requireNonNull(classLoader.getResourceAsStream("org/apache/commons/text/lcs-perf-analysis-inputs.csv")))) + .forEach(record -> { + final String line = record.get(0); + final int indexOfComma = line.indexOf(','); + if (indexOfComma < 0) { + throw new IllegalStateException("Invalid input line: " + line); + } + final String inputA = line.substring(0, indexOfComma); + final String inputB = line.substring(1 + indexOfComma); + this.inputs.add(ImmutablePair.of(inputA, inputB)); + }); } } diff --git a/src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv b/src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv index 53610d3579..8253e4f6be 100644 --- a/src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv +++ b/src/test/resources/org/apache/commons/text/lcs-perf-analysis-inputs.csv @@ -1,4 +1,18 @@ -"This is test data for a JMH (the Java Microbenchmark Harness) which is used from the class org.apache.commons.text.jmh.LongestCommonSubsequencePerformance." +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"This is test data for a JMH (the Java Microbenchmark Harness), which is used from the class org.apache.commons.text.jmh.LongestCommonSubsequencePerformance." "The quick brown fox jumps over the lazy dog. A man, a plan, a canal, Panama. Was it a car or a cat I saw? Step on no pets. Rats live on no evil star." "Here, the field iterations will be populated with appropriate values from the @Param annotation by the JMH when it is passed to the benchmark method. The @Setup annotated method is invoked before each invocation of the benchmark and creates a new Hasher ensuring isolation. When the execution is finished, we'll get a result similar to the one below: When running microbenchmarks, it's very important to be aware of optimizations. Otherwise, they may affect the","benchmark results in a very misleading way. To make matters a bit more concrete, let's consider an example: We expect object allocation costs more than doing nothing at all. However, if we run the benchmarks: Apparently finding a place in the TLAB, creating and initializing an object is almost free! Just by looking at these numbers, we should know that something does not quite add up here." "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. This code is free software; you can redistribute it and/or modify it published by the Free Software Foundation. Oracle designates this This code is distributed in the hope that it will be useful, but WITHOUT FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License You should have received a copy of the GNU General Public License version","Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? under the terms of the GNU General Public License version 2 only, as particular file as subject to the *Classpath* exception as provided ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or version 2 for more details (a copy is included in the LICENSE file that 2 along with this work; if not, write to the Free Software Foundation," From d98c3d74640f737d08bf13c105bba19611e97f80 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 5 Dec 2025 15:06:23 -0500 Subject: [PATCH 211/265] Bump github/codeql-action from 4.31.6 to 4.31.7 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b47769e0ee..c928d7b1b4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/autobuild@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index bcb94cd7f5..cefcc23f34 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/upload-sarif@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 with: sarif_file: results.sarif From 6ffa7c2703ebf069e0df2cbb0ca9aafab4274ff9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 5 Dec 2025 17:03:18 -0500 Subject: [PATCH 212/265] Ask for details on AI usage in creating a pull request --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 4cbe168c3e..9ff35c83e7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -23,7 +23,7 @@ Before you push a pull request, review this list: - [ ] Read the [contribution guidelines](CONTRIBUTING.md) for this project. - [ ] Read the [ASF Generative Tooling Guidance](https://www.apache.org/legal/generative-tooling.html) if you use Artificial Intelligence (AI). -- [ ] I used AI to create any part of, or all of, this pull request. +- [ ] I used AI to create any part of, or all of, this pull request. Which AI tool was used to create this pull request, and to what extent did it contribute? - [ ] Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself. - [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice. - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. From d38b9c23e1dcd1682ce37c90466a7fda40882aad Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 6 Dec 2025 11:40:24 -0500 Subject: [PATCH 213/265] Add NetBean IDE metadata files to .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 03ca919d66..c5860d17e9 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,7 @@ site-content .externalToolBuilders /.checkstyle /.DS_Store + +# NetBeans files +nb-configuration.xml +nbactions.xml From df4916e11b96662c99dfca61fb1e31f5c1e715c7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 7 Dec 2025 07:17:34 -0500 Subject: [PATCH 214/265] Normalize spelling --- .../java/org/apache/commons/text/similarity/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/similarity/package-info.java b/src/main/java/org/apache/commons/text/similarity/package-info.java index 3a2273ff1b..a0cdec2daa 100644 --- a/src/main/java/org/apache/commons/text/similarity/package-info.java +++ b/src/main/java/org/apache/commons/text/similarity/package-info.java @@ -37,7 +37,7 @@ * * *

    The {@link org.apache.commons.text.similarity.CosineDistance Cosine Distance} - * utilises a {@link org.apache.commons.text.similarity.RegexTokenizer regular expression tokenizer (\w+)}. + * utilizes a {@link org.apache.commons.text.similarity.RegexTokenizer regular expression tokenizer (\w+)}. * And the {@link org.apache.commons.text.similarity.LevenshteinDistance Levenshtein Distance}'s * behavior can be changed to take into consideration a maximum throughput.

    * From 001fc65a0c5c4e2fdc337094243db517ac1bbf8f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 7 Dec 2025 22:18:19 +0000 Subject: [PATCH 215/265] Bump to next development version --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 325a76ce79..a3e1315e0a 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 93 commons-text - 1.15.0 + 1.15.1-SNAPSHOT Apache Commons Text Apache Commons Text is a set of utility functions and reusable components for processing and manipulating text in a Java environment. @@ -33,7 +33,7 @@ ISO-8859-1 UTF-8 - 2025-12-04T15:53:46Z + 2025-12-07T22:18:14Z 1.8 1.8 text From 8b2c08751d4b8838ebbee7ad91f53c1f2ef0e677 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 7 Dec 2025 22:19:24 +0000 Subject: [PATCH 216/265] Updates for the next release --- src/changes/changes.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 3f2071af29..547a6d5f1d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -45,6 +45,11 @@ The type attribute can be add,update,fix,remove. Apache Commons Text Changes
    + + + + + Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). From e7ab51e35c30af2f668ccd504bcee7301668614f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 7 Dec 2025 23:02:27 +0000 Subject: [PATCH 217/265] Updates for the next release --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 42cbea80c3..f795a65026 100644 --- a/pom.xml +++ b/pom.xml @@ -39,8 +39,8 @@ text text org.apache.commons.text - 1.15.0 - 1.15.1 + 1.15.01 + 1.15.2 (Java 8+) TEXT 12318221 @@ -61,7 +61,7 @@ - 1.14.0 + 1.15.0 RC1 true scm:svn:https://dist.apache.org/repos/dist/dev/commons/${commons.componentid} From 3d40bb3765f3f9838de4fe0321325d0438affae1 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 9 Dec 2025 10:12:23 -0500 Subject: [PATCH 218/265] Fix spelling in comments --- src/test/java/org/apache/commons/text/StrBuilderTest.java | 2 +- .../java/org/apache/commons/text/TextStringBuilderTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/apache/commons/text/StrBuilderTest.java b/src/test/java/org/apache/commons/text/StrBuilderTest.java index 338768f4f5..c27cf469fc 100644 --- a/src/test/java/org/apache/commons/text/StrBuilderTest.java +++ b/src/test/java/org/apache/commons/text/StrBuilderTest.java @@ -1894,7 +1894,7 @@ void testSubSequenceIntInt() { // End index greater than length() assertThrows(IndexOutOfBoundsException.class, () -> sb.subSequence(2, sb.length() + 1)); - // Start index greater then end index + // Start index greater than end index assertThrows(IndexOutOfBoundsException.class, () -> sb.subSequence(3, 2)); // Normal cases diff --git a/src/test/java/org/apache/commons/text/TextStringBuilderTest.java b/src/test/java/org/apache/commons/text/TextStringBuilderTest.java index 3317543f73..ff2cc7d00b 100644 --- a/src/test/java/org/apache/commons/text/TextStringBuilderTest.java +++ b/src/test/java/org/apache/commons/text/TextStringBuilderTest.java @@ -2190,7 +2190,7 @@ void testSubSequenceIntInt() { // End index greater than length() assertThrows(IndexOutOfBoundsException.class, () -> sb.subSequence(2, sb.length() + 1)); - // Start index greater then end index + // Start index greater than end index assertThrows(IndexOutOfBoundsException.class, () -> sb.subSequence(3, 2)); // Normal cases From 9e34d3d2b2f58c35937477d859042920cdaf3a00 Mon Sep 17 00:00:00 2001 From: Dominik Stadler Date: Fri, 12 Dec 2025 13:49:13 +0100 Subject: [PATCH 219/265] Add more test coverage (#732) * Enable test which can be enabled now * Ensure test does not fail on non-US default locale * Cover a few lines/branches Add some more tests to cover a bit more. Also apply some IDE-suggestions, assert-order, simplify assertions. * Adjust based on review comments Remove added @Deprecated Remove comments which silence warnings in IDEs Inline local variables * Revert "Ensure test does not fail on non-US default locale" This reverts commit 5a6af9ed28cc7523044150a5b57b109fbfc28cd8. * Some more minor adjustments of added tests based on code review --- .../org/apache/commons/text/OssFuzzTest.java | Bin 16930 -> 16771 bytes .../commons/text/StringSubstitutorTest.java | 8 ++++- .../commons/text/TextStringBuilderTest.java | 7 ++++ .../apache/commons/text/WordUtilsTest.java | 28 +++++++++++++++- .../text/lookup/StringLookupFactoryTest.java | 13 ++++++++ .../similarity/IntersectionResultTest.java | 5 ++- .../similarity/LevenshteinResultsTest.java | 16 +++++++++ .../LongestCommonSubsequenceTest.java | 4 +++ .../translate/CharSequenceTranslatorTest.java | 18 ++++++++-- .../text/translate/OctalUnescaperTest.java | 31 ++++++++++++++++++ .../translate/SinglePassTranslatorTest.java | 14 ++++++-- .../text/translate/UnicodeUnescaperTest.java | 5 +++ 12 files changed, 142 insertions(+), 7 deletions(-) diff --git a/src/test/java/org/apache/commons/text/OssFuzzTest.java b/src/test/java/org/apache/commons/text/OssFuzzTest.java index 0b4e1a555ab1e9c074ea7fcebda4e188184551da..c3772e5a372d8e65be74c83afeb17071e84024fa 100644 GIT binary patch delta 30 mcmZ3~!r0u*xFMN&au@UE$p(&+n^&;-*i6=R44XW`aS{Nt5etO? delta 89 zcmZo}W?a<5xFMOD(U%%PKaJD5!lV)2@+< results.length; i++) { @@ -45,6 +45,9 @@ void testEquals() { for (int j = 0; j < results.length; j++) { Assertions.assertEquals(results[i].equals(results[j]), i == j); } + + Assertions.assertFalse(results[i].equals(null), "Should not be Equal to null"); + Assertions.assertNotEquals("Test", results[i], "Should not be Equal to a different type of object"); } } diff --git a/src/test/java/org/apache/commons/text/similarity/LevenshteinResultsTest.java b/src/test/java/org/apache/commons/text/similarity/LevenshteinResultsTest.java index af8f5d92ba..ac93db0605 100644 --- a/src/test/java/org/apache/commons/text/similarity/LevenshteinResultsTest.java +++ b/src/test/java/org/apache/commons/text/similarity/LevenshteinResultsTest.java @@ -40,6 +40,15 @@ void testEqualsReturningFalse() { assertFalse(levenshteinResults.equals(levenshteinResultsTwo)); } + @Test + void testEqualsDifferentDistance() { + final Integer integerOne = 1662; + final Integer integerTwo = 1164; + final LevenshteinResults levenshteinResults = new LevenshteinResults(integerOne, integerOne, integerOne, integerOne); + final LevenshteinResults levenshteinResultsTwo = new LevenshteinResults(integerTwo, integerOne, integerOne, integerOne); + assertFalse(levenshteinResults.equals(levenshteinResultsTwo)); + } + @Test void testEqualsSameObject() { final Integer integer = 1662; @@ -62,4 +71,11 @@ void testEqualsWithNull() { assertFalse(levenshteinResults.equals(null)); } + @Test + void testEqualsWithDifferentObject() { + final Integer integer = -647; + final LevenshteinResults levenshteinResults = new LevenshteinResults(integer, null, null, integer); + assertFalse(levenshteinResults.equals("Test")); + } + } diff --git a/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java b/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java index 2ca0a4b994..8063c911e7 100644 --- a/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java @@ -89,6 +89,8 @@ void testLogestCommonSubsequence() { assertEquals("", subject.logestCommonSubsequence("", "")); assertEquals("", subject.logestCommonSubsequence("left", "")); assertEquals("", subject.logestCommonSubsequence("", "right")); + assertEquals("", subject.logestCommonSubsequence("l", "a")); + assertEquals("", subject.logestCommonSubsequence("left", "a")); assertEquals("fog", subject.logestCommonSubsequence("frog", "fog")); assertEquals("", subject.logestCommonSubsequence("fly", "ant")); assertEquals("h", subject.logestCommonSubsequence("elephant", "hippo")); @@ -106,6 +108,8 @@ void testLongestCommonSubsequence() { assertEquals("", subject.longestCommonSubsequence("", "")); assertEquals("", subject.longestCommonSubsequence("left", "")); assertEquals("", subject.longestCommonSubsequence("", "right")); + assertEquals("", subject.longestCommonSubsequence("l", "a")); + assertEquals("", subject.longestCommonSubsequence("left", "a")); assertEquals("fog", subject.longestCommonSubsequence("frog", "fog")); assertEquals("", subject.longestCommonSubsequence("fly", "ant")); assertEquals("h", subject.longestCommonSubsequence("elephant", "hippo")); diff --git a/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java index 7585f71df1..3bb3328377 100644 --- a/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java +++ b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java @@ -17,9 +17,11 @@ package org.apache.commons.text.translate; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; +import java.io.UncheckedIOException; import java.io.Writer; import org.junit.jupiter.api.Test; @@ -46,8 +48,20 @@ void testWith() throws IOException { final CharSequenceTranslator charSequenceTranslatorThree = new TestCharSequenceTranslator(); final CharSequenceTranslator aggregatedTranslator = charSequenceTranslatorOne.with(charSequenceTranslatorTwo, charSequenceTranslatorThree); aggregatedTranslator.translate("", 0, null); - assertTrue(aggregatedTranslator instanceof AggregateTranslator); + assertInstanceOf(AggregateTranslator.class, aggregatedTranslator); assertEquals(3, translateInvocationCounter); } + @Test + void testIOException() { + final CharSequenceTranslator translator = new CharSequenceTranslator() { + @Override + public int translate(CharSequence input, int index, Writer writer) throws IOException { + throw new IOException("Test exception"); + } + }; + + assertThrows(UncheckedIOException.class, + () -> translator.translate(".")); + } } diff --git a/src/test/java/org/apache/commons/text/translate/OctalUnescaperTest.java b/src/test/java/org/apache/commons/text/translate/OctalUnescaperTest.java index e9b78b44b7..1f7d4b7be3 100644 --- a/src/test/java/org/apache/commons/text/translate/OctalUnescaperTest.java +++ b/src/test/java/org/apache/commons/text/translate/OctalUnescaperTest.java @@ -38,6 +38,10 @@ void testBetween() { result = oue.translate(input); assertEquals("\377", result, "Failed to unescape octal characters via the between method"); + input = "\\777"; + result = oue.translate(input); + assertEquals("\777", result, "Failed to unescape octal characters via the between method"); + input = "\\377 and"; result = oue.translate(input); assertEquals("\377 and", result, "Failed to unescape octal characters via the between method"); @@ -79,4 +83,31 @@ void testBetween() { assertEquals("\\999", result, "Failed to ignore an out of range octal character via the between method"); } + @Test + void testInvalid() { + final OctalUnescaper oue = new OctalUnescaper(); + final String input = "\\4a"; + final String result = oue.translate(input); + assertEquals("\4a", result, "Failed to unescape octal characters via the between method"); + } + + @Test + void testHighLowSurrogate() { + final OctalUnescaper oue = new OctalUnescaper(); + String input = "\\377\uD800and"; + String result = oue.translate(input); + assertEquals("\377\uD800and", result, "Failed to unescape octal characters via the between method"); + + input = "\\377\uD83D\uDE80and"; + result = oue.translate(input); + assertEquals("\377\uD83D\uDE80and", result, "Failed to unescape octal characters via the between method"); + + input = "\\377\uD83D\uDC00and"; + result = oue.translate(input); + assertEquals("\377\uD83D\uDC00and", result, "Failed to unescape octal characters via the between method"); + + input = "\\377\uD83D"; + result = oue.translate(input); + assertEquals("\377\uD83D", result, "Failed to unescape octal characters via the between method"); + } } diff --git a/src/test/java/org/apache/commons/text/translate/SinglePassTranslatorTest.java b/src/test/java/org/apache/commons/text/translate/SinglePassTranslatorTest.java index 37e6fdebd0..12ade3f325 100644 --- a/src/test/java/org/apache/commons/text/translate/SinglePassTranslatorTest.java +++ b/src/test/java/org/apache/commons/text/translate/SinglePassTranslatorTest.java @@ -19,7 +19,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import java.io.IOException; import java.io.StringWriter; import java.io.Writer; @@ -34,7 +33,7 @@ class SinglePassTranslatorTest { private final SinglePassTranslator dummyTranslator = new SinglePassTranslator() { @Override - void translateWhole(final CharSequence input, final Writer writer) throws IOException { + void translateWhole(final CharSequence input, final Writer writer) { // noop } }; @@ -63,4 +62,15 @@ void testTranslateThrowsIllegalArgumentException() { assertThrows(IllegalArgumentException.class, () -> dummyTranslator.translate("(,Fk", 647, null)); } + @Test + void testTranslateThrowsIllegalArgumentExceptionWithNonAnonymousClass() { + assertThrows(IllegalArgumentException.class, () -> new TestTranslator().translate("(,Fk", 647, null)); + } + + private static final class TestTranslator extends SinglePassTranslator { + @Override + void translateWhole(final CharSequence input, final Writer writer) { + // noop + } + } } diff --git a/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java b/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java index cd106c66c4..f20d710678 100644 --- a/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java +++ b/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java @@ -49,4 +49,9 @@ void testUuuuu() { final String result = escaper.translate(input); assertEquals("G", result, "Failed to unescape Unicode characters with many 'u' characters"); } + + @Test + void testTooShort() { + assertThrows(IllegalArgumentException.class, () -> new UnicodeUnescaper().translate("\\u")); + } } From 94200bc822aa17d93d07286672ed3aaa96a0fe24 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 07:58:33 -0500 Subject: [PATCH 220/265] Bump the level of test coverage checks. See: Improve test coverage #732. --- pom.xml | 9 +++++---- src/changes/changes.xml | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index f795a65026..17345d6bdc 100644 --- a/pom.xml +++ b/pom.xml @@ -72,13 +72,14 @@ commons.releaseManagerKey --> + true 1.00 - 0.97 - 0.98 + 0.99 + 0.99 0.95 - 0.94 - 0.98 + 0.99 + 0.97
    diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 547a6d5f1d..5be0355c4b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,8 +47,10 @@ The type attribute can be add,update,fix,remove. + Improve test coverage #732. + Bump the level of test coverage checks. From 2f36f016a3ff14523ab66f1ec4137d02c9e4f193 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 08:17:31 -0500 Subject: [PATCH 221/265] Bump github/codeql-action from 4.31.7 to 4.31.8 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c928d7b1b4..8223940b02 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/autobuild@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index cefcc23f34..217e1d4180 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/upload-sarif@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 with: sarif_file: results.sarif From f63330b8c6dae451199242168abb282078b519ab Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 14:17:18 -0500 Subject: [PATCH 222/265] Sort members --- .../text/lookup/StringLookupFactoryTest.java | 28 +++++++++---------- .../similarity/LevenshteinResultsTest.java | 22 +++++++-------- .../translate/CharSequenceTranslatorTest.java | 22 +++++++-------- .../text/translate/OctalUnescaperTest.java | 16 +++++------ .../translate/SinglePassTranslatorTest.java | 14 +++++----- .../text/translate/UnicodeUnescaperTest.java | 10 +++---- 6 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java index 43e6f237f1..caeccd8289 100644 --- a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java +++ b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java @@ -103,6 +103,12 @@ void testAddDefaultStringLookupsNull() { StringLookupFactory.INSTANCE.addDefaultStringLookups(null); } + @Test + void testClear() { + // this will clear out the global cache in ConstantStringLookup + StringLookupFactory.clear(); + } + /** * Tests that we return the singleton. */ @@ -229,6 +235,14 @@ void testDefaultStringLookupsHolder_multipleLookups() { // @formatter:on } + /** + * Tests that we return the singleton. + */ + @Test + void testDeprecatedSingletons() { + assertSame(StringLookupFactory.INSTANCE_BASE64_DECODER, StringLookupFactory.INSTANCE.base64StringLookup()); + } + /** * Tests that we return the singleton. */ @@ -257,14 +271,6 @@ void testSingletons() { assertSame(XmlEncoderStringLookup.INSTANCE, stringLookupFactory.xmlEncoderStringLookup()); } - /** - * Tests that we return the singleton. - */ - @Test - void testDeprecatedSingletons() { - assertSame(StringLookupFactory.INSTANCE_BASE64_DECODER, StringLookupFactory.INSTANCE.base64StringLookup()); - } - @Test void testXmlStringLookup() { final StringLookupFactory stringLookupFactory = StringLookupFactory.INSTANCE; @@ -286,10 +292,4 @@ void testXmlStringLookupExternalEntityOn() { final String key = XmlStringLookupTest.DOC_DIR + "document-entity-ref.xml:/document/content"; assertEquals(XmlStringLookupTest.DATA, StringLookupFactory.INSTANCE.xmlStringLookup(XmlStringLookupTest.EMPTY_MAP).apply(key).trim()); } - - @Test - void testClear() { - // this will clear out the global cache in ConstantStringLookup - StringLookupFactory.clear(); - } } diff --git a/src/test/java/org/apache/commons/text/similarity/LevenshteinResultsTest.java b/src/test/java/org/apache/commons/text/similarity/LevenshteinResultsTest.java index ac93db0605..d72f91f9c4 100644 --- a/src/test/java/org/apache/commons/text/similarity/LevenshteinResultsTest.java +++ b/src/test/java/org/apache/commons/text/similarity/LevenshteinResultsTest.java @@ -32,20 +32,20 @@ void testEqualsDifferenceInSubstitutionCount() { } @Test - void testEqualsReturningFalse() { + void testEqualsDifferentDistance() { final Integer integerOne = 1662; final Integer integerTwo = 1164; final LevenshteinResults levenshteinResults = new LevenshteinResults(integerOne, integerOne, integerOne, integerOne); - final LevenshteinResults levenshteinResultsTwo = new LevenshteinResults(integerOne, integerOne, integerTwo, integerTwo); + final LevenshteinResults levenshteinResultsTwo = new LevenshteinResults(integerTwo, integerOne, integerOne, integerOne); assertFalse(levenshteinResults.equals(levenshteinResultsTwo)); } @Test - void testEqualsDifferentDistance() { + void testEqualsReturningFalse() { final Integer integerOne = 1662; final Integer integerTwo = 1164; final LevenshteinResults levenshteinResults = new LevenshteinResults(integerOne, integerOne, integerOne, integerOne); - final LevenshteinResults levenshteinResultsTwo = new LevenshteinResults(integerTwo, integerOne, integerOne, integerOne); + final LevenshteinResults levenshteinResultsTwo = new LevenshteinResults(integerOne, integerOne, integerTwo, integerTwo); assertFalse(levenshteinResults.equals(levenshteinResultsTwo)); } @@ -56,6 +56,13 @@ void testEqualsSameObject() { assertTrue(levenshteinResults.equals(levenshteinResults)); } + @Test + void testEqualsWithDifferentObject() { + final Integer integer = -647; + final LevenshteinResults levenshteinResults = new LevenshteinResults(integer, null, null, integer); + assertFalse(levenshteinResults.equals("Test")); + } + @Test void testEqualsWithNonNull() { final Integer integer = 1; @@ -71,11 +78,4 @@ void testEqualsWithNull() { assertFalse(levenshteinResults.equals(null)); } - @Test - void testEqualsWithDifferentObject() { - final Integer integer = -647; - final LevenshteinResults levenshteinResults = new LevenshteinResults(integer, null, null, integer); - assertFalse(levenshteinResults.equals("Test")); - } - } diff --git a/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java index 3bb3328377..894fc877b1 100644 --- a/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java +++ b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java @@ -41,17 +41,6 @@ public int translate(final CharSequence input, final int index, final Writer wri //Used to count translate invocations private int translateInvocationCounter; - @Test - void testWith() throws IOException { - final CharSequenceTranslator charSequenceTranslatorOne = new TestCharSequenceTranslator(); - final CharSequenceTranslator charSequenceTranslatorTwo = new TestCharSequenceTranslator(); - final CharSequenceTranslator charSequenceTranslatorThree = new TestCharSequenceTranslator(); - final CharSequenceTranslator aggregatedTranslator = charSequenceTranslatorOne.with(charSequenceTranslatorTwo, charSequenceTranslatorThree); - aggregatedTranslator.translate("", 0, null); - assertInstanceOf(AggregateTranslator.class, aggregatedTranslator); - assertEquals(3, translateInvocationCounter); - } - @Test void testIOException() { final CharSequenceTranslator translator = new CharSequenceTranslator() { @@ -64,4 +53,15 @@ public int translate(CharSequence input, int index, Writer writer) throws IOExce assertThrows(UncheckedIOException.class, () -> translator.translate(".")); } + + @Test + void testWith() throws IOException { + final CharSequenceTranslator charSequenceTranslatorOne = new TestCharSequenceTranslator(); + final CharSequenceTranslator charSequenceTranslatorTwo = new TestCharSequenceTranslator(); + final CharSequenceTranslator charSequenceTranslatorThree = new TestCharSequenceTranslator(); + final CharSequenceTranslator aggregatedTranslator = charSequenceTranslatorOne.with(charSequenceTranslatorTwo, charSequenceTranslatorThree); + aggregatedTranslator.translate("", 0, null); + assertInstanceOf(AggregateTranslator.class, aggregatedTranslator); + assertEquals(3, translateInvocationCounter); + } } diff --git a/src/test/java/org/apache/commons/text/translate/OctalUnescaperTest.java b/src/test/java/org/apache/commons/text/translate/OctalUnescaperTest.java index 1f7d4b7be3..2dd9cefa3a 100644 --- a/src/test/java/org/apache/commons/text/translate/OctalUnescaperTest.java +++ b/src/test/java/org/apache/commons/text/translate/OctalUnescaperTest.java @@ -83,14 +83,6 @@ void testBetween() { assertEquals("\\999", result, "Failed to ignore an out of range octal character via the between method"); } - @Test - void testInvalid() { - final OctalUnescaper oue = new OctalUnescaper(); - final String input = "\\4a"; - final String result = oue.translate(input); - assertEquals("\4a", result, "Failed to unescape octal characters via the between method"); - } - @Test void testHighLowSurrogate() { final OctalUnescaper oue = new OctalUnescaper(); @@ -110,4 +102,12 @@ void testHighLowSurrogate() { result = oue.translate(input); assertEquals("\377\uD83D", result, "Failed to unescape octal characters via the between method"); } + + @Test + void testInvalid() { + final OctalUnescaper oue = new OctalUnescaper(); + final String input = "\\4a"; + final String result = oue.translate(input); + assertEquals("\4a", result, "Failed to unescape octal characters via the between method"); + } } diff --git a/src/test/java/org/apache/commons/text/translate/SinglePassTranslatorTest.java b/src/test/java/org/apache/commons/text/translate/SinglePassTranslatorTest.java index 12ade3f325..1a66bc1973 100644 --- a/src/test/java/org/apache/commons/text/translate/SinglePassTranslatorTest.java +++ b/src/test/java/org/apache/commons/text/translate/SinglePassTranslatorTest.java @@ -30,6 +30,13 @@ */ class SinglePassTranslatorTest { + private static final class TestTranslator extends SinglePassTranslator { + @Override + void translateWhole(final CharSequence input, final Writer writer) { + // noop + } + } + private final SinglePassTranslator dummyTranslator = new SinglePassTranslator() { @Override @@ -66,11 +73,4 @@ void testTranslateThrowsIllegalArgumentException() { void testTranslateThrowsIllegalArgumentExceptionWithNonAnonymousClass() { assertThrows(IllegalArgumentException.class, () -> new TestTranslator().translate("(,Fk", 647, null)); } - - private static final class TestTranslator extends SinglePassTranslator { - @Override - void translateWhole(final CharSequence input, final Writer writer) { - // noop - } - } } diff --git a/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java b/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java index f20d710678..2879f56c1e 100644 --- a/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java +++ b/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java @@ -34,6 +34,11 @@ void testLessThanFour() { assertThrows(IllegalArgumentException.class, () -> escaper.translate(input)); } + @Test + void testTooShort() { + assertThrows(IllegalArgumentException.class, () -> new UnicodeUnescaper().translate("\\u")); + } + // Requested in LANG-507 @Test void testUPlus() { @@ -49,9 +54,4 @@ void testUuuuu() { final String result = escaper.translate(input); assertEquals("G", result, "Failed to unescape Unicode characters with many 'u' characters"); } - - @Test - void testTooShort() { - assertThrows(IllegalArgumentException.class, () -> new UnicodeUnescaper().translate("\\u")); - } } From 1e8c3f704d2f15d343a910c6192985a59d4b664f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 14:19:45 -0500 Subject: [PATCH 223/265] Use final --- .../java/org/apache/commons/text/StringSubstitutorTest.java | 2 +- .../commons/text/translate/CharSequenceTranslatorTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java index 4022fc3da1..83544c9490 100644 --- a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java +++ b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java @@ -1088,7 +1088,7 @@ void testSubstitutePreserveEscape() throws IOException { @Test void testToString() { final StringSubstitutor s = new StringSubstitutor(null, "prefix", "suffix"); - String str = s.toString(); + final String str = s.toString(); assertTrue(str.contains("\"prefix\""), "Had: " + str); } } diff --git a/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java index 894fc877b1..cd16956cd3 100644 --- a/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java +++ b/src/test/java/org/apache/commons/text/translate/CharSequenceTranslatorTest.java @@ -45,7 +45,7 @@ public int translate(final CharSequence input, final int index, final Writer wri void testIOException() { final CharSequenceTranslator translator = new CharSequenceTranslator() { @Override - public int translate(CharSequence input, int index, Writer writer) throws IOException { + public int translate(final CharSequence input, final int index, final Writer writer) throws IOException { throw new IOException("Test exception"); } }; From 70e527e723307dd26b790382632fb152d45cd1fb Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 14:21:16 -0500 Subject: [PATCH 224/265] Don't use @Deprecated on test methods --- .../java/org/apache/commons/text/StrBuilderAppendInsertTest.java | 1 - src/test/java/org/apache/commons/text/StrBuilderTest.java | 1 - src/test/java/org/apache/commons/text/StrLookupTest.java | 1 - src/test/java/org/apache/commons/text/StrMatcherTest.java | 1 - src/test/java/org/apache/commons/text/StrSubstitutorTest.java | 1 - src/test/java/org/apache/commons/text/StrTokenizerTest.java | 1 - .../commons/text/similarity/LongestCommonSubsequenceTest.java | 1 - 7 files changed, 7 deletions(-) diff --git a/src/test/java/org/apache/commons/text/StrBuilderAppendInsertTest.java b/src/test/java/org/apache/commons/text/StrBuilderAppendInsertTest.java index 15a8313e97..05e64ae8df 100644 --- a/src/test/java/org/apache/commons/text/StrBuilderAppendInsertTest.java +++ b/src/test/java/org/apache/commons/text/StrBuilderAppendInsertTest.java @@ -35,7 +35,6 @@ * * @deprecated This class will be removed in 2.0. */ -@Deprecated class StrBuilderAppendInsertTest { /** The system line separator. */ diff --git a/src/test/java/org/apache/commons/text/StrBuilderTest.java b/src/test/java/org/apache/commons/text/StrBuilderTest.java index c27cf469fc..6ae331e931 100644 --- a/src/test/java/org/apache/commons/text/StrBuilderTest.java +++ b/src/test/java/org/apache/commons/text/StrBuilderTest.java @@ -45,7 +45,6 @@ * * @deprecated This class will be removed in 2.0. */ -@Deprecated class StrBuilderTest { private static final class MockReadable implements Readable { diff --git a/src/test/java/org/apache/commons/text/StrLookupTest.java b/src/test/java/org/apache/commons/text/StrLookupTest.java index 125737a4a6..3b74af62b8 100644 --- a/src/test/java/org/apache/commons/text/StrLookupTest.java +++ b/src/test/java/org/apache/commons/text/StrLookupTest.java @@ -32,7 +32,6 @@ * * @deprecated This class will be removed in 2.0. */ -@Deprecated class StrLookupTest { @Test diff --git a/src/test/java/org/apache/commons/text/StrMatcherTest.java b/src/test/java/org/apache/commons/text/StrMatcherTest.java index f20264aba2..43cd3163f5 100644 --- a/src/test/java/org/apache/commons/text/StrMatcherTest.java +++ b/src/test/java/org/apache/commons/text/StrMatcherTest.java @@ -26,7 +26,6 @@ * * @deprecated This class will be removed in 2.0. */ -@Deprecated class StrMatcherTest { private static final char[] BUFFER1 = "0,1\t2 3\n\r\f\u0000'\"".toCharArray(); diff --git a/src/test/java/org/apache/commons/text/StrSubstitutorTest.java b/src/test/java/org/apache/commons/text/StrSubstitutorTest.java index b4c3065033..ebefd2a568 100644 --- a/src/test/java/org/apache/commons/text/StrSubstitutorTest.java +++ b/src/test/java/org/apache/commons/text/StrSubstitutorTest.java @@ -39,7 +39,6 @@ * * @deprecated This class will be removed in 2.0. */ -@Deprecated class StrSubstitutorTest { private Map values; diff --git a/src/test/java/org/apache/commons/text/StrTokenizerTest.java b/src/test/java/org/apache/commons/text/StrTokenizerTest.java index 59ca3467f4..25731b0574 100644 --- a/src/test/java/org/apache/commons/text/StrTokenizerTest.java +++ b/src/test/java/org/apache/commons/text/StrTokenizerTest.java @@ -37,7 +37,6 @@ * * @deprecated This class will be removed in 2.0. */ -@Deprecated class StrTokenizerTest { private static final String CSV_SIMPLE_FIXTURE = "A,b,c"; diff --git a/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java b/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java index 8063c911e7..f7d64874de 100644 --- a/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java +++ b/src/test/java/org/apache/commons/text/similarity/LongestCommonSubsequenceTest.java @@ -84,7 +84,6 @@ void testGettingLongestCommonSubsequenceStringNull() { } @Test - @Deprecated void testLogestCommonSubsequence() { assertEquals("", subject.logestCommonSubsequence("", "")); assertEquals("", subject.logestCommonSubsequence("left", "")); From a78023d2782b40dd1f9b1fe719fe1f5eac5f8851 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 14:23:11 -0500 Subject: [PATCH 225/265] Use static imports only for JUnit assertions --- .../lookup/Base64DecoderStringLookupTest.java | 11 ++++++---- .../lookup/Base64EncoderStringLookupTest.java | 11 ++++++---- .../lookup/BiFunctionStringLookupTest.java | 21 +++++++++++-------- .../text/lookup/BiStringLookupTest.java | 5 +++-- .../lookup/ConstantStringLookupBasicTest.java | 15 +++++++------ .../text/lookup/ConstantStringLookupTest.java | 20 ++++++++++-------- .../text/lookup/DateStringLookupTest.java | 4 ++-- .../text/lookup/DnsStringLookupTest.java | 20 +++++++++++------- .../EnvironmentVariableStringLookupTest.java | 13 +++++++----- .../text/lookup/FileStringLookupTest.java | 15 ++++++------- .../text/lookup/FunctionStringLookupTest.java | 15 +++++++------ .../InetAddressStringLookupLocalHostTest.java | 18 +++++++++------- ...ddressStringLookupLoopbackAddressTest.java | 18 +++++++++------- .../lookup/InterpolatorStringLookupTest.java | 5 ++--- .../lookup/JavaPlatformStringLookupTest.java | 7 ++++--- .../text/lookup/NullStringLookupTest.java | 10 +++++---- .../lookup/PropertiesStringLookupTest.java | 19 +++++++++-------- .../ResourceBundleStringLookupTest.java | 11 +++++----- .../text/lookup/ScriptStringLookupTest.java | 15 +++++++------ .../SystemPropertyStringLookupTest.java | 11 ++++++---- .../lookup/UrlDecoderStringLookupTest.java | 14 +++++++------ .../lookup/UrlEncoderStringLookupTest.java | 10 +++++---- .../text/lookup/UrlStringLookupTest.java | 15 +++++++------ .../lookup/XmlDecoderStringLookupTest.java | 11 ++++++---- .../lookup/XmlEncoderStringLookupTest.java | 11 ++++++---- 25 files changed, 191 insertions(+), 134 deletions(-) diff --git a/src/test/java/org/apache/commons/text/lookup/Base64DecoderStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/Base64DecoderStringLookupTest.java index c5eac76e24..99cbeeaad4 100644 --- a/src/test/java/org/apache/commons/text/lookup/Base64DecoderStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/Base64DecoderStringLookupTest.java @@ -17,7 +17,10 @@ package org.apache.commons.text.lookup; -import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import org.junit.jupiter.api.Test; /** @@ -27,18 +30,18 @@ class Base64DecoderStringLookupTest { @Test void test() { - Assertions.assertEquals("HelloWorld!", StringLookupFactory.INSTANCE_BASE64_DECODER.apply("SGVsbG9Xb3JsZCE=")); + assertEquals("HelloWorld!", StringLookupFactory.INSTANCE_BASE64_DECODER.apply("SGVsbG9Xb3JsZCE=")); } @Test void testNull() { - Assertions.assertNull(StringLookupFactory.INSTANCE_BASE64_DECODER.apply(null)); + assertNull(StringLookupFactory.INSTANCE_BASE64_DECODER.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(StringLookupFactory.INSTANCE_BASE64_DECODER.toString().isEmpty()); + assertFalse(StringLookupFactory.INSTANCE_BASE64_DECODER.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/Base64EncoderStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/Base64EncoderStringLookupTest.java index df4d320df8..b6741bb074 100644 --- a/src/test/java/org/apache/commons/text/lookup/Base64EncoderStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/Base64EncoderStringLookupTest.java @@ -17,7 +17,10 @@ package org.apache.commons.text.lookup; -import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import org.junit.jupiter.api.Test; /** @@ -27,18 +30,18 @@ class Base64EncoderStringLookupTest { @Test void test() { - Assertions.assertEquals("SGVsbG9Xb3JsZCE=", StringLookupFactory.INSTANCE_BASE64_ENCODER.apply("HelloWorld!")); + assertEquals("SGVsbG9Xb3JsZCE=", StringLookupFactory.INSTANCE_BASE64_ENCODER.apply("HelloWorld!")); } @Test void testNull() { - Assertions.assertNull(StringLookupFactory.INSTANCE_BASE64_ENCODER.apply(null)); + assertNull(StringLookupFactory.INSTANCE_BASE64_ENCODER.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(StringLookupFactory.INSTANCE_BASE64_ENCODER.toString().isEmpty()); + assertFalse(StringLookupFactory.INSTANCE_BASE64_ENCODER.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/BiFunctionStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/BiFunctionStringLookupTest.java index e6f9337a8b..e73f64f7ee 100644 --- a/src/test/java/org/apache/commons/text/lookup/BiFunctionStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/BiFunctionStringLookupTest.java @@ -17,13 +17,16 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiFunction; import org.apache.commons.lang3.StringUtils; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -71,25 +74,25 @@ void testBiFunctionForNestedMap() { // Use map final BiStringLookup> stringLookup = StringLookupFactory.INSTANCE .biFunctionStringLookup(nestedMapBiFunction); - Assertions.assertEquals(rootValue2, stringLookup.lookup(rootKey2, rootMap)); - Assertions.assertEquals(subValue, stringLookup.lookup(rootKey + SEPARATOR + subKey, rootMap)); - Assertions.assertEquals(subSubValue, + assertEquals(rootValue2, stringLookup.lookup(rootKey2, rootMap)); + assertEquals(subValue, stringLookup.lookup(rootKey + SEPARATOR + subKey, rootMap)); + assertEquals(subSubValue, stringLookup.lookup(rootKey + SEPARATOR + subKeyMap + SEPARATOR + subSubKey, rootMap)); } @Test void testConcurrentHashMapNull() { - Assertions.assertNull(BiFunctionStringLookup.on(new ConcurrentHashMap<>()).apply(null)); + assertNull(BiFunctionStringLookup.on(new ConcurrentHashMap<>()).apply(null)); } @Test void testHashMapNull() { - Assertions.assertNull(BiFunctionStringLookup.on(new HashMap<>()).apply(null)); + assertNull(BiFunctionStringLookup.on(new HashMap<>()).apply(null)); } @Test void testNullBiFunction() { - Assertions.assertNull(BiFunctionStringLookup.on((BiFunction) null).apply(null)); + assertNull(BiFunctionStringLookup.on((BiFunction) null).apply(null)); } @Test @@ -98,13 +101,13 @@ void testOne() { final String value = "value"; final Map map = new HashMap<>(); map.put(key, value); - Assertions.assertEquals(value, FunctionStringLookup.on(map).apply(key)); + assertEquals(value, FunctionStringLookup.on(map).apply(key)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(BiFunctionStringLookup.on(new HashMap<>()).toString().isEmpty()); + assertFalse(BiFunctionStringLookup.on(new HashMap<>()).toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/BiStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/BiStringLookupTest.java index 5aee02abb2..a54b35dbbf 100644 --- a/src/test/java/org/apache/commons/text/lookup/BiStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/BiStringLookupTest.java @@ -17,7 +17,8 @@ package org.apache.commons.text.lookup; -import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; /** @@ -27,7 +28,7 @@ class BiStringLookupTest { @Test void testDefaultMethod() { - Assertions.assertEquals("a", ((BiStringLookup) key -> key).lookup("a", "b")); + assertEquals("a", ((BiStringLookup) key -> key).lookup("a", "b")); } } diff --git a/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupBasicTest.java b/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupBasicTest.java index f3a4bbfeb4..d438abac97 100644 --- a/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupBasicTest.java +++ b/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupBasicTest.java @@ -17,8 +17,11 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -55,12 +58,12 @@ public void beforeEach() { @Test void testNull() { - Assertions.assertNull(ConstantStringLookup.INSTANCE.apply(null)); + assertNull(ConstantStringLookup.INSTANCE.apply(null)); } @Test void testNullClassFetch() { - Assertions.assertNull(new ConstantStringLookup() { + assertNull(new ConstantStringLookup() { @Override protected Class fetchClass(final String className) throws ClassNotFoundException { return null; @@ -70,20 +73,20 @@ protected Class fetchClass(final String className) throws ClassNotFoundExcept @Test void testNullValue() { - Assertions.assertEquals(NULL_STRING_FIXTURE, ConstantStringLookup.INSTANCE + assertEquals(NULL_STRING_FIXTURE, ConstantStringLookup.INSTANCE .apply(ConstantStringLookupBasicTest.class.getName() + ".NULL_STRING_FIXTURE")); } @Test void testOne() { - Assertions.assertEquals(STRING_FIXTURE, + assertEquals(STRING_FIXTURE, ConstantStringLookup.INSTANCE.apply(ConstantStringLookupBasicTest.class.getName() + ".STRING_FIXTURE")); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(ConstantStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(ConstantStringLookup.INSTANCE.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupTest.java index 49d252acd8..fccc45d788 100644 --- a/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupTest.java @@ -16,10 +16,12 @@ */ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + import java.awt.event.KeyEvent; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -71,7 +73,7 @@ void testLookupCache() { */ @Test void testLookupConstant() { - Assertions.assertEquals(FIELD, stringLookup.apply(variable("FIELD")), "Wrong value of constant"); + assertEquals(FIELD, stringLookup.apply(variable("FIELD")), "Wrong value of constant"); } /** @@ -79,7 +81,7 @@ void testLookupConstant() { */ @Test void testLookupInvalidSyntax() { - Assertions.assertNull(stringLookup.apply("InvalidVariableName"), + assertNull(stringLookup.apply("InvalidVariableName"), "Non null return value for invalid variable name"); } @@ -88,7 +90,7 @@ void testLookupInvalidSyntax() { */ @Test void testLookupNonExisting() { - Assertions.assertNull(stringLookup.apply(variable("NO_FIELD")), + assertNull(stringLookup.apply(variable("NO_FIELD")), "Non null return value for non existing constant"); } @@ -99,8 +101,8 @@ void testLookupNonExisting() { void testLookupNonString() { final String ref = KeyEvent.class.getName() + ".VK_ESCAPE"; final String expected = Integer.toString(KeyEvent.VK_ESCAPE); - Assertions.assertEquals(expected, stringLookup.apply(ref), "Wrong result of first lookup"); - Assertions.assertEquals(expected, stringLookup.apply(ref), "Wrong result of 2nd lookup"); + assertEquals(expected, stringLookup.apply(ref), "Wrong result of first lookup"); + assertEquals(expected, stringLookup.apply(ref), "Wrong result of 2nd lookup"); } /** @@ -108,7 +110,7 @@ void testLookupNonString() { */ @Test void testLookupNull() { - Assertions.assertNull(stringLookup.apply(null), "Non null return value for null variable"); + assertNull(stringLookup.apply(null), "Non null return value for null variable"); } /** @@ -116,7 +118,7 @@ void testLookupNull() { */ @Test void testLookupPrivate() { - Assertions.assertNull(stringLookup.apply(variable("PRIVATE_FIELD")), + assertNull(stringLookup.apply(variable("PRIVATE_FIELD")), "Non null return value for non accessible field"); } @@ -125,7 +127,7 @@ void testLookupPrivate() { */ @Test void testLookupUnknownClass() { - Assertions.assertNull(stringLookup.apply("org.apache.commons.configuration.NonExistingConfig." + FIELD), + assertNull(stringLookup.apply("org.apache.commons.configuration.NonExistingConfig." + FIELD), "Non null return value for unknown class"); } diff --git a/src/test/java/org/apache/commons/text/lookup/DateStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/DateStringLookupTest.java index cd358a34b0..e09e8aa599 100644 --- a/src/test/java/org/apache/commons/text/lookup/DateStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/DateStringLookupTest.java @@ -18,6 +18,7 @@ package org.apache.commons.text.lookup; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -26,7 +27,6 @@ import java.text.SimpleDateFormat; import java.util.Date; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -62,7 +62,7 @@ void testFormat() { @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(DateStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(DateStringLookup.INSTANCE.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/DnsStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/DnsStringLookupTest.java index c1ce322b16..b62dee6aa5 100644 --- a/src/test/java/org/apache/commons/text/lookup/DnsStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/DnsStringLookupTest.java @@ -17,10 +17,14 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.net.InetAddress; import java.net.UnknownHostException; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -31,28 +35,28 @@ class DnsStringLookupTest { @Test void testAddressFromHostAddress() throws UnknownHostException { final InetAddress localHost = InetAddress.getLocalHost(); - Assertions.assertEquals(localHost.getHostAddress(), + assertEquals(localHost.getHostAddress(), DnsStringLookup.INSTANCE.apply("address|" + localHost.getHostAddress())); } @Test void testAddressFromHostName() throws UnknownHostException { final InetAddress localHost = InetAddress.getLocalHost(); - Assertions.assertEquals(localHost.getHostAddress(), + assertEquals(localHost.getHostAddress(), DnsStringLookup.INSTANCE.apply("address|" + localHost.getHostName())); } @Test void testCanonicalNameFromHostAddress() throws UnknownHostException { final InetAddress localHost = InetAddress.getLocalHost(); - Assertions.assertEquals(localHost.getCanonicalHostName(), + assertEquals(localHost.getCanonicalHostName(), DnsStringLookup.INSTANCE.apply("canonical-name|" + localHost.getHostAddress())); } @Test void testCanonicalNameFromHostName() throws UnknownHostException { final InetAddress localHost = InetAddress.getLocalHost(); - Assertions.assertEquals(localHost.getCanonicalHostName(), + assertEquals(localHost.getCanonicalHostName(), DnsStringLookup.INSTANCE.apply("canonical-name|" + localHost.getHostName())); } @@ -66,18 +70,18 @@ void testName() throws UnknownHostException { matched = true; } } - Assertions.assertTrue(matched); + assertTrue(matched); } @Test void testNull() { - Assertions.assertNull(DnsStringLookup.INSTANCE.apply(null)); + assertNull(DnsStringLookup.INSTANCE.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(DnsStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(DnsStringLookup.INSTANCE.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/EnvironmentVariableStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/EnvironmentVariableStringLookupTest.java index 2dd798087d..346adf154c 100644 --- a/src/test/java/org/apache/commons/text/lookup/EnvironmentVariableStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/EnvironmentVariableStringLookupTest.java @@ -17,8 +17,11 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import org.apache.commons.lang3.SystemUtils; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -28,24 +31,24 @@ class EnvironmentVariableStringLookupTest { @Test void testNull() { - Assertions.assertNull(StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES.apply(null)); + assertNull(StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES.apply(null)); } @Test void testOne() { if (SystemUtils.IS_OS_WINDOWS) { final String key = "PATH"; - Assertions.assertEquals(System.getenv(key), StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES.apply(key)); + assertEquals(System.getenv(key), StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES.apply(key)); } else if (SystemUtils.IS_OS_LINUX) { final String key = "USER"; - Assertions.assertEquals(System.getenv(key), StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES.apply(key)); + assertEquals(System.getenv(key), StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES.apply(key)); } } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES.toString().isEmpty()); + assertFalse(StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/FileStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/FileStringLookupTest.java index acfaae7a9a..d87be3ae1a 100644 --- a/src/test/java/org/apache/commons/text/lookup/FileStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/FileStringLookupTest.java @@ -18,6 +18,8 @@ package org.apache.commons.text.lookup; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; @@ -28,7 +30,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringSubstitutor; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -44,7 +45,7 @@ public static String readDocumentFixtureString() throws IOException { } public static void testFence(final String expectedString, final FileStringLookup fileStringLookup) { - Assertions.assertEquals(expectedString, fileStringLookup.apply("UTF-8:src/test/resources/org/apache/commons/text/document.properties")); + assertEquals(expectedString, fileStringLookup.apply("UTF-8:src/test/resources/org/apache/commons/text/document.properties")); assertThrows(IllegalArgumentException.class, () -> fileStringLookup.apply("UTF-8:/src/test/resources/org/apache/commons/text/document.properties")); assertThrows(IllegalArgumentException.class, () -> fileStringLookup.apply("UTF-8:../src/test/resources/org/apache/commons/text/document.properties")); } @@ -73,19 +74,19 @@ void testDefaultInstanceMissingFilePart() { @Test void testDefaultInstanceNull() { - Assertions.assertNull(FileStringLookup.INSTANCE.apply(null)); + assertNull(FileStringLookup.INSTANCE.apply(null)); } @Test void testDefaultInstanceOne() throws Exception { final String expectedString = readDocumentFixtureString(); - Assertions.assertEquals(expectedString, FileStringLookup.INSTANCE.apply("UTF-8:src/test/resources/org/apache/commons/text/document.properties")); + assertEquals(expectedString, FileStringLookup.INSTANCE.apply("UTF-8:src/test/resources/org/apache/commons/text/document.properties")); } @Test void testDefaultInstanceToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(FileStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(FileStringLookup.INSTANCE.toString().isEmpty()); } @Test @@ -120,13 +121,13 @@ void testFenceCurrentDirPlusOne() throws Exception { @Test void testFenceEmptyOne() throws Exception { final String expectedString = readDocumentFixtureString(); - Assertions.assertEquals(expectedString, new FileStringLookup().apply("UTF-8:src/test/resources/org/apache/commons/text/document.properties")); + assertEquals(expectedString, new FileStringLookup().apply("UTF-8:src/test/resources/org/apache/commons/text/document.properties")); } @Test void testFenceNullOne() throws Exception { final String expectedString = readDocumentFixtureString(); - Assertions.assertEquals(expectedString, + assertEquals(expectedString, new FileStringLookup((Path[]) null).apply("UTF-8:src/test/resources/org/apache/commons/text/document.properties")); } diff --git a/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java index c9f297336a..92ff7ac3c1 100644 --- a/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java @@ -17,12 +17,15 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -32,17 +35,17 @@ class FunctionStringLookupTest { @Test void testConcurrentHashMapNull() { - Assertions.assertNull(FunctionStringLookup.on(new ConcurrentHashMap<>()).apply(null)); + assertNull(FunctionStringLookup.on(new ConcurrentHashMap<>()).apply(null)); } @Test void testHashMapNull() { - Assertions.assertNull(FunctionStringLookup.on(new HashMap<>()).apply(null)); + assertNull(FunctionStringLookup.on(new HashMap<>()).apply(null)); } @Test void testNullFunction() { - Assertions.assertNull(FunctionStringLookup.on((Function) null).apply(null)); + assertNull(FunctionStringLookup.on((Function) null).apply(null)); } @Test @@ -51,13 +54,13 @@ void testOne() { final String value = "value"; final Map map = new HashMap<>(); map.put(key, value); - Assertions.assertEquals(value, FunctionStringLookup.on(map).apply(key)); + assertEquals(value, FunctionStringLookup.on(map).apply(key)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(FunctionStringLookup.on(new HashMap<>()).toString().isEmpty()); + assertFalse(FunctionStringLookup.on(new HashMap<>()).toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/InetAddressStringLookupLocalHostTest.java b/src/test/java/org/apache/commons/text/lookup/InetAddressStringLookupLocalHostTest.java index 762f10621d..8f2aad3cb2 100644 --- a/src/test/java/org/apache/commons/text/lookup/InetAddressStringLookupLocalHostTest.java +++ b/src/test/java/org/apache/commons/text/lookup/InetAddressStringLookupLocalHostTest.java @@ -17,10 +17,14 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + import java.net.InetAddress; import java.net.UnknownHostException; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -30,33 +34,33 @@ class InetAddressStringLookupLocalHostTest { @Test void testAddress() throws UnknownHostException { - Assertions.assertEquals(InetAddress.getLocalHost().getHostAddress(), InetAddressStringLookup.LOCAL_HOST.apply("address")); + assertEquals(InetAddress.getLocalHost().getHostAddress(), InetAddressStringLookup.LOCAL_HOST.apply("address")); } @Test void testBadKey() { - Assertions.assertThrows(IllegalArgumentException.class, () -> InetAddressStringLookup.LOCAL_HOST.apply("FOO")); + assertThrows(IllegalArgumentException.class, () -> InetAddressStringLookup.LOCAL_HOST.apply("FOO")); } @Test void testCanonicalName() throws UnknownHostException { - Assertions.assertEquals(InetAddress.getLocalHost().getCanonicalHostName(), InetAddressStringLookup.LOCAL_HOST.apply("canonical-name")); + assertEquals(InetAddress.getLocalHost().getCanonicalHostName(), InetAddressStringLookup.LOCAL_HOST.apply("canonical-name")); } @Test void testName() throws UnknownHostException { - Assertions.assertEquals(InetAddress.getLocalHost().getHostName(), InetAddressStringLookup.LOCAL_HOST.apply("name")); + assertEquals(InetAddress.getLocalHost().getHostName(), InetAddressStringLookup.LOCAL_HOST.apply("name")); } @Test void testNull() { - Assertions.assertNull(InetAddressStringLookup.LOCAL_HOST.apply(null)); + assertNull(InetAddressStringLookup.LOCAL_HOST.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(InetAddressStringLookup.LOCAL_HOST.toString().isEmpty()); + assertFalse(InetAddressStringLookup.LOCAL_HOST.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/InetAddressStringLookupLoopbackAddressTest.java b/src/test/java/org/apache/commons/text/lookup/InetAddressStringLookupLoopbackAddressTest.java index 282ea6dc48..b69c002edd 100644 --- a/src/test/java/org/apache/commons/text/lookup/InetAddressStringLookupLoopbackAddressTest.java +++ b/src/test/java/org/apache/commons/text/lookup/InetAddressStringLookupLoopbackAddressTest.java @@ -17,9 +17,13 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + import java.net.InetAddress; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -29,33 +33,33 @@ class InetAddressStringLookupLoopbackAddressTest { @Test void testAddress() { - Assertions.assertEquals(InetAddress.getLoopbackAddress().getHostAddress(), InetAddressStringLookup.LOOPACK_ADDRESS.apply("address")); + assertEquals(InetAddress.getLoopbackAddress().getHostAddress(), InetAddressStringLookup.LOOPACK_ADDRESS.apply("address")); } @Test void testBadKey() { - Assertions.assertThrows(IllegalArgumentException.class, () -> InetAddressStringLookup.LOOPACK_ADDRESS.apply("FOO")); + assertThrows(IllegalArgumentException.class, () -> InetAddressStringLookup.LOOPACK_ADDRESS.apply("FOO")); } @Test void testCanonicalName() { - Assertions.assertEquals(InetAddress.getLoopbackAddress().getCanonicalHostName(), InetAddressStringLookup.LOOPACK_ADDRESS.apply("canonical-name")); + assertEquals(InetAddress.getLoopbackAddress().getCanonicalHostName(), InetAddressStringLookup.LOOPACK_ADDRESS.apply("canonical-name")); } @Test void testName() { - Assertions.assertEquals(InetAddress.getLoopbackAddress().getHostName(), InetAddressStringLookup.LOOPACK_ADDRESS.apply("name")); + assertEquals(InetAddress.getLoopbackAddress().getHostName(), InetAddressStringLookup.LOOPACK_ADDRESS.apply("name")); } @Test void testNull() { - Assertions.assertNull(InetAddressStringLookup.LOOPACK_ADDRESS.apply(null)); + assertNull(InetAddressStringLookup.LOOPACK_ADDRESS.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(InetAddressStringLookup.LOOPACK_ADDRESS.toString().isEmpty()); + assertFalse(InetAddressStringLookup.LOOPACK_ADDRESS.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/InterpolatorStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/InterpolatorStringLookupTest.java index 6b49df48b0..631538a606 100644 --- a/src/test/java/org/apache/commons/text/lookup/InterpolatorStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/InterpolatorStringLookupTest.java @@ -27,7 +27,6 @@ import java.util.Map; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -115,12 +114,12 @@ void testLookupWithNullDefaultInterpolator() { @Test void testNull() { - Assertions.assertNull(InterpolatorStringLookup.INSTANCE.apply(null)); + assertNull(InterpolatorStringLookup.INSTANCE.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(new InterpolatorStringLookup().toString().isEmpty()); + assertFalse(new InterpolatorStringLookup().toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/JavaPlatformStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/JavaPlatformStringLookupTest.java index 759e4d5c54..3f08165340 100644 --- a/src/test/java/org/apache/commons/text/lookup/JavaPlatformStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/JavaPlatformStringLookupTest.java @@ -17,11 +17,12 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.commons.lang3.ArrayUtils; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -41,13 +42,13 @@ void testMain() { @Test void testNull() { - Assertions.assertNull(JavaPlatformStringLookup.INSTANCE.apply(null)); + assertNull(JavaPlatformStringLookup.INSTANCE.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(JavaPlatformStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(JavaPlatformStringLookup.INSTANCE.toString().isEmpty()); } @Test diff --git a/src/test/java/org/apache/commons/text/lookup/NullStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/NullStringLookupTest.java index 2612de2d47..768d894dce 100644 --- a/src/test/java/org/apache/commons/text/lookup/NullStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/NullStringLookupTest.java @@ -17,7 +17,9 @@ package org.apache.commons.text.lookup; -import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import org.junit.jupiter.api.Test; /** @@ -27,14 +29,14 @@ class NullStringLookupTest { @Test void test() { - Assertions.assertNull(StringLookupFactory.INSTANCE_NULL.apply("EverythingIsNull")); - Assertions.assertNull(StringLookupFactory.INSTANCE_NULL.apply(null)); + assertNull(StringLookupFactory.INSTANCE_NULL.apply("EverythingIsNull")); + assertNull(StringLookupFactory.INSTANCE_NULL.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(StringLookupFactory.INSTANCE_NULL.toString().isEmpty()); + assertFalse(StringLookupFactory.INSTANCE_NULL.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/PropertiesStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/PropertiesStringLookupTest.java index a9a3f86f74..9991056eab 100644 --- a/src/test/java/org/apache/commons/text/lookup/PropertiesStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/PropertiesStringLookupTest.java @@ -18,6 +18,8 @@ package org.apache.commons.text.lookup; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.nio.file.Path; @@ -27,7 +29,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringSubstitutor; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -131,10 +132,10 @@ void testMissingKey() { @Test void testNull() { - Assertions.assertNull(PropertiesStringLookup.INSTANCE.apply(null)); - Assertions.assertNull(new PropertiesStringLookup().apply(null)); - Assertions.assertNull(new PropertiesStringLookup(NULL_PATH_ARRAY).apply(null)); - Assertions.assertNull(new PropertiesStringLookup(CURRENT_PATH).apply(null)); + assertNull(PropertiesStringLookup.INSTANCE.apply(null)); + assertNull(new PropertiesStringLookup().apply(null)); + assertNull(new PropertiesStringLookup(NULL_PATH_ARRAY).apply(null)); + assertNull(new PropertiesStringLookup(CURRENT_PATH).apply(null)); } @Test @@ -149,10 +150,10 @@ void testOne() { @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(PropertiesStringLookup.INSTANCE.toString().isEmpty()); - Assertions.assertFalse(new PropertiesStringLookup().toString().isEmpty()); - Assertions.assertFalse(new PropertiesStringLookup(NULL_PATH_ARRAY).toString().isEmpty()); - Assertions.assertFalse(new PropertiesStringLookup(CURRENT_PATH).toString().isEmpty()); + assertFalse(PropertiesStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(new PropertiesStringLookup().toString().isEmpty()); + assertFalse(new PropertiesStringLookup(NULL_PATH_ARRAY).toString().isEmpty()); + assertFalse(new PropertiesStringLookup(CURRENT_PATH).toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/ResourceBundleStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/ResourceBundleStringLookupTest.java index b3721f24d6..21520a8959 100644 --- a/src/test/java/org/apache/commons/text/lookup/ResourceBundleStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/ResourceBundleStringLookupTest.java @@ -17,6 +17,8 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.spy; @@ -24,7 +26,6 @@ import java.util.ResourceBundle; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -39,7 +40,7 @@ class ResourceBundleStringLookupTest { void testAny() { final String bundleName = TEST_RESOURCE_BUNDLE; final String bundleKey = KEY; - Assertions.assertEquals(ResourceBundle.getBundle(bundleName).getString(bundleKey), + assertEquals(ResourceBundle.getBundle(bundleName).getString(bundleKey), ResourceBundleStringLookup.INSTANCE.apply(AbstractStringLookup.toLookupKey(bundleName, bundleKey))); } @@ -77,19 +78,19 @@ void testMissingKeyInSpec() { @Test void testNull() { - Assertions.assertNull(ResourceBundleStringLookup.INSTANCE.apply(null)); + assertNull(ResourceBundleStringLookup.INSTANCE.apply(null)); } @Test void testOne() { - Assertions.assertEquals(ResourceBundle.getBundle(TEST_RESOURCE_BUNDLE).getString(KEY), + assertEquals(ResourceBundle.getBundle(TEST_RESOURCE_BUNDLE).getString(KEY), new ResourceBundleStringLookup(TEST_RESOURCE_BUNDLE).apply(KEY)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(ResourceBundleStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(ResourceBundleStringLookup.INSTANCE.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/ScriptStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/ScriptStringLookupTest.java index 92e4189650..d61987c3a8 100644 --- a/src/test/java/org/apache/commons/text/lookup/ScriptStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/ScriptStringLookupTest.java @@ -17,11 +17,14 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import javax.script.ScriptEngineManager; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -48,17 +51,17 @@ void testNoScript() { @Test void testNull() { - Assertions.assertNull(ScriptStringLookup.INSTANCE.apply(null)); + assertNull(ScriptStringLookup.INSTANCE.apply(null)); } @Test void testOne() { - Assertions.assertEquals("Hello World!", ScriptStringLookup.INSTANCE.apply(JS_NAME + ":\"Hello World!\"")); + assertEquals("Hello World!", ScriptStringLookup.INSTANCE.apply(JS_NAME + ":\"Hello World!\"")); } @Test void testSanityCheck() { - Assertions.assertNotNull(new ScriptEngineManager().getEngineByName(JS_NAME), JS_NAME); + assertNotNull(new ScriptEngineManager().getEngineByName(JS_NAME), JS_NAME); } @Test @@ -68,14 +71,14 @@ void testScriptMissingColon() { @Test void testScriptUsingMultipleColons() { - Assertions.assertEquals("It Works", + assertEquals("It Works", ScriptStringLookup.INSTANCE.apply(JS_NAME + ":true ? \"It Works\" : \"It Does Not Work\" ")); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(ScriptStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(ScriptStringLookup.INSTANCE.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/SystemPropertyStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/SystemPropertyStringLookupTest.java index 84ae67e2c5..7e71681edb 100644 --- a/src/test/java/org/apache/commons/text/lookup/SystemPropertyStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/SystemPropertyStringLookupTest.java @@ -17,7 +17,10 @@ package org.apache.commons.text.lookup; -import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import org.junit.jupiter.api.Test; /** @@ -27,19 +30,19 @@ class SystemPropertyStringLookupTest { @Test void testNull() { - Assertions.assertNull(StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES.apply(null)); + assertNull(StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES.toString().isEmpty()); + assertFalse(StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES.toString().isEmpty()); } @Test void testUserName() { final String key = "user.name"; - Assertions.assertEquals(System.getProperty(key), StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES.apply(key)); + assertEquals(System.getProperty(key), StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES.apply(key)); } } diff --git a/src/test/java/org/apache/commons/text/lookup/UrlDecoderStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/UrlDecoderStringLookupTest.java index b0a87bb5f2..a6b218b80a 100644 --- a/src/test/java/org/apache/commons/text/lookup/UrlDecoderStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/UrlDecoderStringLookupTest.java @@ -17,6 +17,9 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -24,7 +27,6 @@ import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -36,7 +38,7 @@ class UrlDecoderStringLookupTest { @Test void testAllPercent() { - Assertions.assertEquals(DATA, UrlDecoderStringLookup.INSTANCE.apply("Hello%20World%21")); + assertEquals(DATA, UrlDecoderStringLookup.INSTANCE.apply("Hello%20World%21")); } @Test @@ -49,23 +51,23 @@ void testExceptionGettingString() throws UnsupportedEncodingException { @Test void testExclamation() { - Assertions.assertEquals(DATA, UrlDecoderStringLookup.INSTANCE.apply("Hello%20World!")); + assertEquals(DATA, UrlDecoderStringLookup.INSTANCE.apply("Hello%20World!")); } @Test void testNull() { - Assertions.assertNull(UrlDecoderStringLookup.INSTANCE.apply(null)); + assertNull(UrlDecoderStringLookup.INSTANCE.apply(null)); } @Test void testPlus() { - Assertions.assertEquals(DATA, UrlDecoderStringLookup.INSTANCE.apply("Hello+World!")); + assertEquals(DATA, UrlDecoderStringLookup.INSTANCE.apply("Hello+World!")); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(UrlDecoderStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(UrlDecoderStringLookup.INSTANCE.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/UrlEncoderStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/UrlEncoderStringLookupTest.java index 0b4eb7572b..4805d094bc 100644 --- a/src/test/java/org/apache/commons/text/lookup/UrlEncoderStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/UrlEncoderStringLookupTest.java @@ -17,6 +17,9 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -24,7 +27,6 @@ import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -36,7 +38,7 @@ class UrlEncoderStringLookupTest { @Test void test() { - Assertions.assertEquals(DATA, UrlEncoderStringLookup.INSTANCE.apply("Hello World!")); + assertEquals(DATA, UrlEncoderStringLookup.INSTANCE.apply("Hello World!")); } @Test @@ -49,13 +51,13 @@ void testExceptionGettingString() throws UnsupportedEncodingException { @Test void testNull() { - Assertions.assertNull(UrlEncoderStringLookup.INSTANCE.apply(null)); + assertNull(UrlEncoderStringLookup.INSTANCE.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(UrlEncoderStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(UrlEncoderStringLookup.INSTANCE.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/UrlStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/UrlStringLookupTest.java index e69fb60d4e..916e67cf82 100644 --- a/src/test/java/org/apache/commons/text/lookup/UrlStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/UrlStringLookupTest.java @@ -17,6 +17,10 @@ package org.apache.commons.text.lookup; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.net.URI; @@ -25,7 +29,6 @@ import java.nio.file.Path; import java.nio.file.Paths; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -55,13 +58,13 @@ void testFileScheme() throws Exception { // System.out.println(uri); final byte[] expectedBytes = Files.readAllBytes(path); final String expectedString = new String(expectedBytes, StandardCharsets.UTF_8); - Assertions.assertEquals(expectedString, UrlStringLookup.INSTANCE.apply("UTF-8:" + uri.toString())); + assertEquals(expectedString, UrlStringLookup.INSTANCE.apply("UTF-8:" + uri.toString())); } @Test void testHttpScheme() { - Assertions.assertNotNull(UrlStringLookup.INSTANCE.apply("UTF-8:https://www.apache.org")); - Assertions.assertNotNull(UrlStringLookup.INSTANCE.apply("UTF-8:https://www.google.com")); + assertNotNull(UrlStringLookup.INSTANCE.apply("UTF-8:https://www.apache.org")); + assertNotNull(UrlStringLookup.INSTANCE.apply("UTF-8:https://www.google.com")); } @Test @@ -71,13 +74,13 @@ void testMissingUrl() { @Test void testNull() { - Assertions.assertNull(UrlStringLookup.INSTANCE.apply(null)); + assertNull(UrlStringLookup.INSTANCE.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(UrlStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(UrlStringLookup.INSTANCE.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/XmlDecoderStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/XmlDecoderStringLookupTest.java index d378f59673..117c6f38b7 100644 --- a/src/test/java/org/apache/commons/text/lookup/XmlDecoderStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/XmlDecoderStringLookupTest.java @@ -17,7 +17,10 @@ package org.apache.commons.text.lookup; -import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import org.junit.jupiter.api.Test; /** @@ -29,18 +32,18 @@ class XmlDecoderStringLookupTest { @Test void testDecode() { - Assertions.assertEquals(DATA, XmlDecoderStringLookup.INSTANCE.apply("<element>")); + assertEquals(DATA, XmlDecoderStringLookup.INSTANCE.apply("<element>")); } @Test void testNull() { - Assertions.assertNull(XmlDecoderStringLookup.INSTANCE.apply(null)); + assertNull(XmlDecoderStringLookup.INSTANCE.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(XmlDecoderStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(XmlDecoderStringLookup.INSTANCE.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/text/lookup/XmlEncoderStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/XmlEncoderStringLookupTest.java index b597fc1484..219cd6ed12 100644 --- a/src/test/java/org/apache/commons/text/lookup/XmlEncoderStringLookupTest.java +++ b/src/test/java/org/apache/commons/text/lookup/XmlEncoderStringLookupTest.java @@ -17,7 +17,10 @@ package org.apache.commons.text.lookup; -import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + import org.junit.jupiter.api.Test; /** @@ -29,18 +32,18 @@ class XmlEncoderStringLookupTest { @Test void testDecode() { - Assertions.assertEquals(DATA, XmlEncoderStringLookup.INSTANCE.apply("")); + assertEquals(DATA, XmlEncoderStringLookup.INSTANCE.apply("")); } @Test void testNull() { - Assertions.assertNull(XmlEncoderStringLookup.INSTANCE.apply(null)); + assertNull(XmlEncoderStringLookup.INSTANCE.apply(null)); } @Test void testToString() { // does not blow up and gives some kind of string. - Assertions.assertFalse(XmlEncoderStringLookup.INSTANCE.toString().isEmpty()); + assertFalse(XmlEncoderStringLookup.INSTANCE.toString().isEmpty()); } } From 88e375d5622cacc5c927fd71806b1d06febbbfc7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 14:27:49 -0500 Subject: [PATCH 226/265] Bump actions/cache from 4.3.0 to 5.0.1 --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8223940b02..b1cc918df2 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -48,7 +48,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From 86963d1b3caf5024e99a5a161ad4168823b58803 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 14:48:51 -0500 Subject: [PATCH 227/265] Reduce vertical whitespace --- src/changes/changes.xml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 5be0355c4b..dcbfe45203 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -320,7 +320,6 @@ The type attribute can be add,update,fix,remove. [build] maven-pmd-plugin 3.12.0 -> 3.13.0. [build] org.mockito 3.3.3 -> 3.4.4. - commons-text web page missing "RELEASE-NOTES-1.7.txt" (doc) Fixed wrong value for Jaro-Winkler example #117 @@ -330,7 +329,6 @@ The type attribute can be add,update,fix,remove. Expand Javadoc for StringSubstitutor and friends. [site] checkstyle.version 8.21 -> 8.23. - WordUtils.wrap must calculate offset increment from wrapOn pattern length Jaro Winkler Distance refers to similarity @@ -348,14 +346,12 @@ The type attribute can be add,update,fix,remove. Update tests from org.assertj:assertj-core 3.12.1 to 3.12.2. Update site from com.puppycrawl.tools:checkstyle 8.18 to 8.21. - Add the resource string bundle string lookup to the default set of lookups Add StringLookupFactory methods for the URL encoder and decoder string lookups org.apache.commons.text.lookup.StringLookupFactory.interpolatorStringLookup() should reuse a singleton instance Add a Base64 encoder string lookup. - Improve JaccardSimilarity computational cost JSON escaping incorrect for the delete control character @@ -372,7 +368,6 @@ The type attribute can be add,update,fix,remove. Add URL encoder and decoder string lookups. Add constant string lookup like the one in Apache Commons Configuration. - StringEscapeUtils#unescapeJson does not unescape double quotes and forward slash Remove mention of SQL escaping from user guide @@ -380,7 +375,6 @@ The type attribute can be add,update,fix,remove. Allow full customization with new API org.apache.commons.text.lookup.StringLookupFactory.interpolatorStringLookup(Map<String, StringLookup>, StringLookup, boolean). WordUtils.wrap throws StringIndexOutOfBoundsException when wrapLength is Integer.MAX_VALUE. - Add Automatic-Module-Name MANIFEST entry for Java 9 compatibility Build failure with java 9-ea+159 @@ -391,7 +385,6 @@ The type attribute can be add,update,fix,remove. Add a local host string lookup: LocalHostStringLookup StrLookup API confusing - Upversion commons-lang to 3.7 Exception thrown in ExtendedMessageFormat using quotes with custom registry @@ -412,7 +405,6 @@ The type attribute can be add,update,fix,remove. Add StrLookup.resourceBundleLookup(ResourceBundle) Typo in LongestCommonSubsequence#logestCommonSubsequence - WordUtils should use toXxxxCase(int) rather than toXxxxCase(char) WordUtils.abbreviate support @@ -422,7 +414,6 @@ The type attribute can be add,update,fix,remove. Correct round issue in Jaro Winkler implementation Similar to LANG-1025, clirr fails site build. - Fixing the 200 checkstyle errors present in 1.0-beta-1 Mutable fields should be private - Incorporate suggestions from RC2 into 1.0 release Naming packages org.apache.commons.text.beta @@ -483,6 +473,5 @@ The type attribute can be add,update,fix,remove. Add Hamming distance Incorporate String algorithms from Commons Lang - From 4746223a5f14308b47c5adfac132b26aa69fbd25 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 17 Dec 2025 07:51:19 -0500 Subject: [PATCH 228/265] Bump github/codeql-action from 4.31.8 to 4.31.9 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b1cc918df2..d7e8c4a82c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 + uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 + uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 + uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 217e1d4180..48e22b5942 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 + uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 with: sarif_file: results.sarif From 788a011760c7308ad2bbce20b20056b5e292a35d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Dec 2025 13:51:57 -0500 Subject: [PATCH 229/265] Bump actions/upload-artifact from 5.0.0 to 6.0.0 --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 48e22b5942..3c49b0d632 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -57,7 +57,7 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 6.0.0 with: name: SARIF file path: results.sarif From a6caa498edb8d17f7a78d7ebfe7279986985e212 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 21 Dec 2025 15:41:22 -0500 Subject: [PATCH 230/265] Javadoc --- .../org/apache/commons/text/similarity/EditDistance.java | 8 ++++---- .../commons/text/similarity/ObjectSimilarityScore.java | 4 ++-- .../apache/commons/text/similarity/SimilarityScore.java | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/EditDistance.java b/src/main/java/org/apache/commons/text/similarity/EditDistance.java index 2b81d8d9c2..77b735dbd2 100644 --- a/src/main/java/org/apache/commons/text/similarity/EditDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/EditDistance.java @@ -27,10 +27,10 @@ * the set {@code S}: *

    *
      - *
    • {@code d(x,y) >= 0}, non-negativity or separation axiom
    • - *
    • {@code d(x,y) == 0}, if and only if, {@code x == y}
    • - *
    • {@code d(x,y) == d(y,x)}, symmetry, and
    • - *
    • {@code d(x,z) <= d(x,y) + d(y,z)}, the triangle inequality
    • + *
    • {@code d(x, y) >= 0}, non-negativity or separation axiom
    • + *
    • {@code d(x, y) == 0}, if and only if, {@code x == y}
    • + *
    • {@code d(x, y) == d(y, x)}, symmetry, and
    • + *
    • {@code d(x, z) <= d(x, y) + d(y, z)}, the triangle inequality
    • *
    * * diff --git a/src/main/java/org/apache/commons/text/similarity/ObjectSimilarityScore.java b/src/main/java/org/apache/commons/text/similarity/ObjectSimilarityScore.java index 393518aed7..21ce3afbcb 100644 --- a/src/main/java/org/apache/commons/text/similarity/ObjectSimilarityScore.java +++ b/src/main/java/org/apache/commons/text/similarity/ObjectSimilarityScore.java @@ -30,8 +30,8 @@ * A similarity score is the function {@code d: [X * X] -> [0, INFINITY)} with the following properties: *

    *
      - *
    • {@code d(x,y) >= 0}, non-negativity or separation axiom
    • - *
    • {@code d(x,y) == d(y,x)}, symmetry.
    • + *
    • {@code d(x, y) >= 0}, non-negativity or separation axiom
    • + *
    • {@code d(x, y) == d(y, x)}, symmetry.
    • *
    * *

    diff --git a/src/main/java/org/apache/commons/text/similarity/SimilarityScore.java b/src/main/java/org/apache/commons/text/similarity/SimilarityScore.java index 4a2f7de7e3..dcd1dbaf46 100644 --- a/src/main/java/org/apache/commons/text/similarity/SimilarityScore.java +++ b/src/main/java/org/apache/commons/text/similarity/SimilarityScore.java @@ -27,8 +27,8 @@ * following properties: *

    *
      - *
    • {@code d(x,y) >= 0}, non-negativity or separation axiom
    • - *
    • {@code d(x,y) == d(y,x)}, symmetry.
    • + *
    • {@code d(x, y) >= 0}, non-negativity or separation axiom
    • + *
    • {@code d(x, y) == d(y, x)}, symmetry.
    • *
    *

    * Notice, these are two of the properties that contribute to {@code d} being a metric. From 23d232af1331e15b3d752ffbaa18eae91e0fbb52 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 29 Dec 2025 08:52:06 -0500 Subject: [PATCH 231/265] Bump notice file end year from 2025 to 2026 --- NOTICE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE.txt b/NOTICE.txt index 0c73fbda69..167fda3832 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,5 +1,5 @@ Apache Commons Text -Copyright 2014-2025 The Apache Software Foundation +Copyright 2014-2026 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). From deef0f66abf905b9e4630cac24f46060aca694ed Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 31 Dec 2025 18:06:25 -0500 Subject: [PATCH 232/265] Javadoc: Empty Javadoc line before the 1st tag. --- src/main/java/org/apache/commons/text/StrTokenizer.java | 1 + src/main/java/org/apache/commons/text/TextRandomProvider.java | 1 + src/main/java/org/apache/commons/text/WordUtils.java | 1 + .../org/apache/commons/text/translate/SinglePassTranslator.java | 1 + 4 files changed, 4 insertions(+) diff --git a/src/main/java/org/apache/commons/text/StrTokenizer.java b/src/main/java/org/apache/commons/text/StrTokenizer.java index 66ede10fd3..9d757234e5 100644 --- a/src/main/java/org/apache/commons/text/StrTokenizer.java +++ b/src/main/java/org/apache/commons/text/StrTokenizer.java @@ -389,6 +389,7 @@ public StrTokenizer(final String input, final StrMatcher delim, final StrMatcher /** * Unsupported ListIterator operation. + * * @param obj this parameter ignored. * @throws UnsupportedOperationException always. */ diff --git a/src/main/java/org/apache/commons/text/TextRandomProvider.java b/src/main/java/org/apache/commons/text/TextRandomProvider.java index 84eb843db3..82477d6b89 100644 --- a/src/main/java/org/apache/commons/text/TextRandomProvider.java +++ b/src/main/java/org/apache/commons/text/TextRandomProvider.java @@ -39,6 +39,7 @@ * .build(); * } * + * * @since 1.1 */ public interface TextRandomProvider extends IntUnaryOperator { diff --git a/src/main/java/org/apache/commons/text/WordUtils.java b/src/main/java/org/apache/commons/text/WordUtils.java index ca41c6c3c3..720ca5f98c 100644 --- a/src/main/java/org/apache/commons/text/WordUtils.java +++ b/src/main/java/org/apache/commons/text/WordUtils.java @@ -779,6 +779,7 @@ public static String wrap(final String str, * "flammable\ninflammable" * * + * * @param str the String to be word wrapped, may be null. * @param wrapLength the column to wrap the words at, less than 1 is treated as 1. * @param newLineStr the string to insert for a new line, {@code null} uses the system property line separator. diff --git a/src/main/java/org/apache/commons/text/translate/SinglePassTranslator.java b/src/main/java/org/apache/commons/text/translate/SinglePassTranslator.java index 90dd7f23bc..2fd4f67100 100644 --- a/src/main/java/org/apache/commons/text/translate/SinglePassTranslator.java +++ b/src/main/java/org/apache/commons/text/translate/SinglePassTranslator.java @@ -37,6 +37,7 @@ private String getClassName() { /** * {@inheritDoc} + * * @throws IllegalArgumentException if {@code index != 0}. */ @Override From 02a5aa15b5a77d0048430483806f41f0637e8528 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jan 2026 16:55:27 -0500 Subject: [PATCH 233/265] Bump commons.bytebuddy.version from 1.18.2 to 1.18.3 (#734) Bumps `commons.bytebuddy.version` from 1.18.2 to 1.18.3. Updates `net.bytebuddy:byte-buddy` from 1.18.2 to 1.18.3 - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.18.2...byte-buddy-1.18.3) Updates `net.bytebuddy:byte-buddy-agent` from 1.18.2 to 1.18.3 - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.18.2...byte-buddy-1.18.3) --- updated-dependencies: - dependency-name: net.bytebuddy:byte-buddy dependency-version: 1.18.3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: net.bytebuddy:byte-buddy-agent dependency-version: 1.18.3 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 17345d6bdc..d79a4eeb05 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content 3.20.0 - 1.18.2 + 1.18.3 1.6 false 1.37 From a911fd8c119860fc17a97d2036ab6275893067e4 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 1 Jan 2026 16:56:10 -0500 Subject: [PATCH 234/265] Bump commons.bytebuddy.version from 1.18.2 to 1.18.3 #734 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index dcbfe45203..fe4bfb9e16 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,7 @@ The type attribute can be add,update,fix,remove. Bump the level of test coverage checks. + Bump commons.bytebuddy.version from 1.18.2 to 1.18.3 #734. From 5504c26dacf6a51701c949e47ab1c981cb4018b3 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 2 Jan 2026 17:39:04 -0500 Subject: [PATCH 235/265] Format XML --- src/changes/changes.xml | 831 ++++++++++++++++++++-------------------- 1 file changed, 415 insertions(+), 416 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index fe4bfb9e16..b45a1061c8 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -37,10 +37,8 @@ and commit The type attribute can be add,update,fix,remove. --> - - + Apache Commons Text Changes @@ -53,369 +51,370 @@ The type attribute can be add,update,fix,remove. Bump the level of test coverage checks. Bump commons.bytebuddy.version from 1.18.2 to 1.18.3 #734. - - - Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). - Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. - Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724. - Fix Apache RAT plugin console warnings. - Fix site XML to use version 2.0.0 XML schema. - Removed unreachable threshold verification code in src/main/java/org/apache/commons/text/similarity #730. - Enable secure processing for the XML parser in XmlStringLookup in case the underlying JAXP implementation doesn't #729. - - Add experimental CycloneDX VEX file #683. - Add Damerau-Levenshtein distance #687. - Add unit tests to increase coverage #719. - Add new test for CharSequenceTranslator#with() #725. - Add tests and assertions to org.apache.commons.text.similarity to get to 100% code coverage #727, #728. - - Bump org.apache.commons:commons-parent from 85 to 93 #704, #723, #726. - Bump commons.bytebuddy.version from 1.17.6 to 1.18.2 #696, #722. - Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. - Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. - Bump commons-io:commons-io from 2.20.0 to 2.21.0. - - - - Fix PMD UnnecessaryFullyQualifiedName in StringLookupFactory. - Fix PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder. - Fix PMD UnnecessaryFullyQualifiedName in PropertiesStringLookup. - Fix PMD UnnecessaryFullyQualifiedName in JavaPlatformStringLookup. - Fix PMD UnnecessaryFullyQualifiedName in StringSubstitutor. - Fix PMD UnnecessaryFullyQualifiedName in StrSubstitutor. - Fix PMD UnnecessaryFullyQualifiedName in AlphabetConverter. - Fix PMD AvoidBranchingStatementAsLastInLoop in TextStringBuilder. - Fix PMD AvoidBranchingStatementAsLastInLoop in StrBuilder. - org.apache.commons.text.translate.LookupTranslator.LookupTranslator(Map CharSequence>) now throws NullPointerException instead of java.security.InvalidParameterException. - - Interface StringLookup now extends UnaryOperator<String>. - Interface TextRandomProvider extends IntUnaryOperator. - Add RandomStringGenerator.Builder.usingRandom(IntUnaryOperator). - Add PMD check to default Maven goal. - Add org.apache.commons.text.RandomStringGenerator.Builder.setAccumulate(boolean). - - Bump org.apache.commons:commons-parent from 81 to 85 #668. - Bump commons-io:commons-io from 2.18.0 to 2.20.0. - Bump graalvm.version from 24.2.0 to 24.2.2 #665, #681. - Bump commons.bytebuddy.version from 1.17.5 to 1.17.6 (#677). - Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #680. - - - - Remove -nouses directive from maven-bundle-plugin. OSGi package imports now state 'uses' definitions for package imports, this doesn't affect JPMS (from org.apache.commons:commons-parent:80). - Deprecate EntityArrays.EntityArrays(). - StringLookupFactory.DefaultStringLookupsHolder.createDefaultStringLookups() maps DefaultStringLookup.LOCAL_HOST twice instead of once for LOCAL_HOST and LOOPBACK_ADDRESS. - - - Bump org.apache.commons:commons-parent from 79 to 81. - Bump commons.bytebuddy.version from 1.16.1 to 1.17.5 #643, #659, #660. - Bump graalvm.version from 24.1.2 to 24.2.0 #653. - - - - Add StringLookupFactory.loopbackAddressStringLookup(). - Add StringLookupFactory.KEY_LOOPBACK_ADDRESS. - Add DefaultStringLookup.LOOPBACK_ADDRESS. - Add richer inputs in package org.apache.commons.text.similarity with SimilarityInput. - Add HammingDistance.apply(SimilarityInput, SimilarityInput). - Add JaccardDistance.apply(SimilarityInput, SimilarityInput). - Add JaccardSimilarity.apply(SimilarityInput, SimilarityInput). - Add JaroWinklerDistance.apply(SimilarityInput, SimilarityInput). - Add JaroWinklerSimilarity.apply(SimilarityInput, SimilarityInput). - Add LevenshteinDetailedDistance.apply(SimilarityInput, SimilarityInput). - Add LevenshteinDistance.apply(SimilarityInput, SimilarityInput). - - Fix build on Java 22. - Fix build on Java 23-ea. - Make package-private constructor private: StrLookup.MapStrLookup.MapStrLookup(Map). - Make package-private constructor private: StrLookup.SystemPropertiesStrLookup.SystemPropertiesStrLookup(). - Make package-private class private and final: MapStrLookup. - Make package-private class private: StrMatcher.CharMatcher. - Make package-private class private: StrMatcher.CharSetMatcher. - Make package-private class private: StrMatcher.NoMatcher. - Make package-private class private: StrMatcher.StringMatcher. - Make package-private class private: StrMatcher.TrimMatcher. - Make package-private class private and final: IntersectionSimilarity.BagCount. - Make package-private class private and final: IntersectionSimilarity.TinyCount. - Deprecate LevenshteinDistance.LevenshteinDistance() in favor of LevenshteinDistance.getDefaultInstance(). - Deprecate LevenshteinDetailedDistance.LevenshteinDetailedDistance() in favor of LevenshteinDetailedDistance.getDefaultInstance(). - Improve StrBuilder documentation for new line text. - Improve TextStringBuilder documentation for new line text #547. - Required OSGi Import-Package version numbers in MANIFEST.MF #627. - - Bump org.apache.commons:commons-parent from 69 to 78 #542, #557, #571, #581, #584, #593, #600, #603, #614. - Bump tests on Java >= 22 org.graalvm.*:* from 24.0.0 to 24.1.1 #592, #610. - Bump commons.bytebuddy.version from 1.14.13 to 1.16.1 #538, #548, #553, #565, #579, #582, #585, #596, #597, #604, #612, #620, #623, #625, #640. - Bump SpotBugs from 4.8.3 to 4.8.5. - Bump org.assertj:assertj-core from 3.25.3 to 3.26.3 #554, #566. - Bump org.codehaus.mojo:taglist-maven-plugin from 3.0.0 to 3.2.1 #564, #611. - Bump org.apache.commons:commons-rng-simple from 1.5 to 1.6 #568. - Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #569, #575, #586. - Bump commons-io:commons-io from 2.16.1 to 2.18.0 #594, #628. - - - - Add StringLookupFactory.fileStringLookup(Path...) and deprecated fileStringLookup(). - Add StringLookupFactory.propertiesStringLookup(Path...) and deprecated propertiesStringLookup(). - Add StringLookupFactory.xmlStringLookup(Map, Path...) and deprecated xmlStringLookup() and xmlStringLookup(Map). - Add StringLookupFactory.builder() for fencing Path resolution of the file, properties and XML lookups. - Add DoubleFormat.Builder.get() as Builder now implements Supplier. - - WordUtils.containsAllWords​() may throw PatternSyntaxException. - Fix regression for determining whitespace in WordUtils #519. - Deprecate Builder in favor of Supplier. - - Bump commons-lang3 from 3.13.0 to 3.14.0. - Bump commons.bytebuddy.version from 1.14.9 to 1.14.13 #476, #482, #505, #521. - Bump org.codehaus.mojo:exec-maven-plugin from 3.1.0 to 3.2.0 #474, #508. - Bump commons-io from 2.15.0 to 2.16.1 #522, #527. - Bump commons-parent from 64 to 69 #524. - Bump org.assertj:assertj-core from 3.24.2 to 3.25.3. - - - - Fix StringTokenizer.getTokenList to return an independent modifiable list - Fix Javadoc for StringEscapeUtils.escapeHtml4 #382 - TextStringBuidler#hashCode() allocates a String on each call #387. - Fix Bundle-SymbolicName to use the package name org.apache.commons.text - Add and use a package-private singleton for RegexTokenizer. - Add and use a package-private singleton for CosineSimilarity. - Add and use a package-private singleton for LongestCommonSubsequence. - Add and use a package-private singleton for JaroWinklerSimilarity. - Add and use a package-private singleton for JaccardSimilarity. - [StepSecurity] ci: Harden GitHub Actions #428. - Improve AlphabetConverter Javadoc #429. - Fix exception message in IntersectionResult to make set-theoretic sense #438. - Add null-check in RandomStringGenerator#Builder#selectFrom() to avoid NullPointerException #434. - Add null-check in RandomStringGenerator#Builder#withinRange() to avoid NullPointerException. - Fix TextStringBuilder to over-allocate when ensuring capacity #452. - Constructor for ResourceBundleStringLookup should be private instead of package-private. - Constructor for UrlDecoderStringLookup should be private instead of package-private. - Constructor for UrlEncoderStringLookup should be private instead of package-private. - Javadoc of org.apache.commons.text.lookup.DefaultStringLookup.XML is incorrect. - Update DoubleFormat to state it is based on Double.toString. #467. - - Set SecureProcessing feature in XmlStringLookup by default. - Add StringLookupFactory.xmlStringLookup(Map<String, Boolean>...). - Add @FunctionalInterface to FormatFactory. - Add RandomStringGenerator.builder(). - Add XmlEncoderStringLookup/XmlDecoderStringLookup #449. - Add StringSubstitutor.toString(). - - Bump actions/cache. - Bump actions/setup-java. - Bump actions/checkout. - Bump pmd from 6.49.0 to 6.52.0 #364. - Bump commons-rng-simple from 1.4 to 1.5 #370. - Bump spotbugs-maven-plugin from 4.7.2.0 to 4.7.3.6 #371, #385. - Bump spotbugs from 4.7.2 to 4.7.3 #373. - Bump mockito-inline from 4.8.0 to 4.11.0 #380, #389, #396, #400. - Bump jmh.version from 1.35 to 1.37 #388. - Bump commons-parent from 54 to 64 #392, #401. - Bump assertj-core from 3.23.1 to 3.24.2 #405, #410. - Bump maven-checkstyle-plugin from 3.2.0 to 3.2.1 #407. - Bump commons-io from 2.11.0 to 2.15.0. - Bump commons-lang3 from 3.12.0 to 3.13.0. - - - - Fix CaseUtils when the input string contains only delimiters - Add GraalVM test dependencies to fix test failures with Java 15. - Incorrect values for Jaccard similarity with empty strings. - StringSubstitutor map constructor throws NPE on 1.9 with null map. - JaroWinklerDistance returns the same values as JaroWinklerSimilarity. - Correct Javadoc in FileStringLookup. - Minor Improvements #192, #196. - Use StringUtils.INDEX_NOT_FOUND constant. - Remove redundant local variable. - Replace lambda with method reference. - Simplify statements. - Replace statement lambda with expression lambda. - Use static class inner class in tests. - Simplify assertion. - Extract duplicate code. - Set void return method. - Remove unused exception from TextStringBuilder.readFrom(CharBuffer). This preserves binary compatibility but not source compatibility. - StrBuilder.StrBuilderReader.skip(long): Throw an exception when an implicit narrowing conversion in a compound assignment would result in information loss or a numeric error such as an overflows. - TextStringBuilder.TextStringBuilderReader.skip(long): Throw an exception when an implicit narrowing conversion in a compound assignment would result in information loss or a numeric error such as an overflows. - TextStringBuilder.equals whatever the capacity is #281. - A More Efficient Implementation for Calculating Size of Longest Common Subsequence. - LookupTranslator returns count of chars consumed, not of codepoints consumed. - Use Math.min() call instead of doing it manually. #335. - TextStringBuilder: Throw OutOfMemoryError instead of NegativeArraySizeException. - TextStringBuilder: Can't grow to sizes up to Integer.MAX_VALUE. - Make default string lookups configurable via system property. Remove dns, url, and script lookups from defaults. If these lookups are required for use in StringSubstitutor.createInterpolator(), they must be enabled via system property. See StringLookupFactory for details. - - Add DoubleFormat utility. - Document negative limit for WordUtils abbreviate method - Speed up LevenshteinDistance with threshold by exiting early - Release Notes page hasn't been updated for 1.9 release yet. - Add StrBuilder.isNotEmpty(). - - Bump actions/setup-java from v1.4.0 to 3 #147, #156, #155, #172, #215, #314. - Bump github/codeql-action from 1 to 2 #319. - Bump checkstyle from 8.34 to 9.3, #141, #168, #182, #188, #193, #201, #208, #211, #228, #235, #245, #253, #255, #262, #270, #280, #287, #299, #315, #321. - Bump spotbugs-maven-plugin from 4.0.0 to 4.7.2.0, #144, #150, #167, #176, #194, #210, #223, #250, #268, #273, #277, #278, #286, #293, #303, #320, #325, #338, #344, #354. - Bump spotbugs from 4.1.3 to 4.7.2 #175, 189, #209, #218, #247, #256, #264, #275, #284, #289, #296, #306, #355. - Bump mockito-inline from 3.4.4 to 4.8.0, #143, #148, #149, #152, #153, #154, #158, #159, #166, #177, #180, #187, #195, #197, #207, #216, #231, #236, #237, #243, #258, #259, #260, #261, #272, #285, #291, #305, #317, #330, #331, #347, #352. - Bump junit-jupiter from 5.6.2 to 5.9.1 #163, #204, #232, #265, #269, #288, #343, #357. - Bump assertj-core from 3.16.1 to 3.23.1 #151, #157, #160, #178, #184, #199, #244, #267, #294. - Bump commons-io from 2.7 to 2.11.0 #161 #251. - Bump commons-parent from 51 to 54 #145, #358. - Bump maven-pmd-plugin from 3.13.0 to 3.19.0 #186, #263, #302, #334, #349, #353. - Bump pmd from 6.42.0 to 6.46.0. - Bump graalvm.version from 20.2.0 to 22.0.0.2 #185, #198, #206, #227, #252, #276, #295, #300. - Bump commons.japicmp.version from 0.14.3 to 0.16.0. - Bump commons.jacoco.version 0.8.5 to 0.8.8; fixes Java 15 build. - Bump maven-checkstyle-plugin from 3.1.1 to 3.2.0 #202, #348. - Bump commons-lang3 3.11 -> 3.12.0. - Bump commons.javadoc.version from 3.2.0 to 3.4.1. - Bump commons.project-info.version from 3.1.0 to 3.1.2. - Bump jmh.version from 1.32 to 1.35 #254, #292, #313. - Bump commons-rng-simple from 1.3 to 1.4 #266. - Bump taglist-maven-plugin from 2.4 to 3.0.0 #297. - Bump commons.pmd-impl.version from 6.44.0 to 6.49.0 #323, #336, #345, #350. - Bump exec-maven-plugin from 3.0.0 to 3.1.0 #340. - - - Removed non-existing parameter from Javadocs and spelled out parameters in throws. - StringEscapeUtils.unescapeCsv doesn't remove quotes at begin and end of string. - ScriptStringLookup does not accept ":" #126. - StringSubstitutor incorrectly removes some escape characters. - Fix Javadocs #135. - Fix typos #137. - Make ConstantStringLookup.constantCache final #136. - Simplify if in CaseUtils #134. - [javadoc] Fix compiler warnings in Java code example in Javadoc #124. - Update from Apache Commons Lang 3.9 to 3.11. - Add StringMatcher.size(). - Refactor TextStringBuilder.readFrom(Readable), extracting readFrom(CharBuffer) and readFrom(Reader). - Add BiStringLookup and implementation BiFunctionStringLookup. - Add org.apache.commons.text.StringSubstitutor.StringSubstitutor(StringSubstitutor). - Add org.apache.commons.text.TextStringBuilder.TextStringBuilder(CharSequence). - Add org.apache.commons.text.TextStringBuilder.drainChar(int). - Add org.apache.commons.text.TextStringBuilder.drainChars(int, int, char[]. int). - Add org.apache.commons.text.TextStringBuilder.isNotEmpty(). - Add org.apache.commons.text.TextStringBuilder.isReallocated(). - Add org.apache.commons.text.TextStringBuilder.readFrom(Reader, int). - Add org.apache.commons.text.TextStringBuilder.set(String). - Add org.apache.commons.text.TextStringBuilder.wrap(char[]). - Add org.apache.commons.text.TextStringBuilder.wrap(char[], int). - Add org.apache.commons.text.io.StringSubstitutorReader. - Add org.apache.commons.text.lookup.StringLookupFactory.functionStringLookup(Function<String, V>). - Add org.apache.commons.text.matcher.StringMatcher.isMatch(CharSequence, int). - Add org.apache.commons.text.matcher.StringMatcher.isMatch(CharSequence, int, int, int). - Add org.apache.commons.text.matcher.StringMatcherFactory.andMatcher(StringMatcher...). - Add org.apache.commons.text.matcher.StringMatcherFactory.stringMatcher(char...). - [build] Skip clirr since we use JApiCmp. - [test] junit-jupiter 5.5.1 -> 5.5.2. - [test] org.assertj:assertj-core 3.13.2 -> 3.16.1. - [build] com.puppycrawl.tools:checkstyle 8.23 -> 8.34. - [build] Update JUnit from 5.5.2 to 5.6.2. - [build] commons.jacoco.version 0.8.4 -> 0.8.5. - [build] commons.javadoc.version 3.1.1 -> 3.2.0. - [build] commons.japicmp.version 0.14.1 -> 0.14.3. - [build] checkstyle.plugin.version 3.1.0 -> 3.1.1. - [build] checkstyle.version 8.27 -> 8.33. - [build] org.apache.commons:commons-parent 48 -> 51. - [build] maven-pmd-plugin 3.12.0 -> 3.13.0. - [build] org.mockito 3.3.3 -> 3.4.4. - - - commons-text web page missing "RELEASE-NOTES-1.7.txt" - (doc) Fixed wrong value for Jaro-Winkler example #117 - Add helper factory method org.apache.commons.text.StringSubstitutor.createInterpolator(). - Add String lookup for host names and IP addresses (DnsStringLookup). - StringLookupFactory.addDefaultStringLookups(Map) does not convert keys to lower case. - Expand Javadoc for StringSubstitutor and friends. - [site] checkstyle.version 8.21 -> 8.23. - - - WordUtils.wrap must calculate offset increment from wrapOn pattern length - Jaro Winkler Distance refers to similarity - Add an enum to the lookup package that lists all StringLookups - Add a toggle to throw an exception when a variable is unknown in StringSubstitutor - TextStringBuilder append sub-sequence not consistent with Appendable. - Fix possible infinite loop in WordUtils.wrap for a regex pattern that would trigger on a match of 0 length - Make prefixSet in LookupTranslator a BitSet - Fix the RegexTokenizer to use a static Pattern - Remove rounding from JaccardDistance and JaccardSimilarity - Fix the JaroWinklerSimilarity to use StringUtils.equals to test for CharSequence equality - Add a generic IntersectionSimilarity measure - Update Apache Commons Lang from 3.8.1 to 3.9. - ResourceBundleStringLookup.lookup(String) throws MissingResourceException instead of returning null. - Update tests from org.assertj:assertj-core 3.12.1 to 3.12.2. - Update site from com.puppycrawl.tools:checkstyle 8.18 to 8.21. - - - Add the resource string bundle string lookup to the default set of lookups - Add StringLookupFactory methods for the URL encoder and decoder string lookups - org.apache.commons.text.lookup.StringLookupFactory.interpolatorStringLookup() should reuse a singleton instance - Add a Base64 encoder string lookup. - - - Improve JaccardSimilarity computational cost - JSON escaping incorrect for the delete control character - Fixes JaroWinklerDistance: Wrong results due to precision of transpositions - JaroWinklerDistance: Calculation deviates from definition - Update Apache Commons Lang from 3.7 to 3.8.1 - Add a XML file XPath string lookup. - Add a Properties file string lookup. - Add a script string lookup. - Add a file string lookup. - Add a URL string lookup. - Add a Base64 string lookup. - Add org.apache.commons.text.lookup.StringLookupFactory.resourceBundleStringLookup(String). - Add URL encoder and decoder string lookups. - Add constant string lookup like the one in Apache Commons Configuration. - - - StringEscapeUtils#unescapeJson does not unescape double quotes and forward slash - Remove mention of SQL escaping from user guide - Update Java requirement from version 7 to 8. - Allow full customization with new API org.apache.commons.text.lookup.StringLookupFactory.interpolatorStringLookup(Map<String, StringLookup>, StringLookup, boolean). - WordUtils.wrap throws StringIndexOutOfBoundsException when wrapLength is Integer.MAX_VALUE. - - - Add Automatic-Module-Name MANIFEST entry for Java 9 compatibility - Build failure with java 9-ea+159 - Add an interpolator string lookup: StringLookupFactory#interpolatorStringLookup() - Add a StrSubstitutor replacement based on interfaces: StringSubstitutor - Add a StrBuilder replacement based on the StringMatcher interface: TextStringBuilder - Add a StrTokenizer replacement based on the StringMatcher interface: StringTokenizer - Add a local host string lookup: LocalHostStringLookup - StrLookup API confusing - - - Upversion commons-lang to 3.7 - Exception thrown in ExtendedMessageFormat using quotes with custom registry - StringEscapeUtils#UnEscapeJson doesn't recognize escape signs correctly - StrSubstitutor: Ability to turn off substitution in values - RandomStringGenerator able to pass multiple ranges to .withinRange() - Deprecate isDelimiter and use HashSets for delimiter checks - WordUtils.initials support for UTF-16 surrogate pairs - WordUtils should treat an empty delimiter array as no delimiters - Update RandomStringGenerator to accept a list of valid characters - Add CharacterPredicates for ASCII letters (uppercase/lowercase) and arabic numerals - Added CaseUtils class with camel case conversion support - RandomStringGenerator should be able to generate a String with a random length - Update commons-lang dependency to version 3.6 - Document that commons-csv should be used in preference to CsvTranslators - NumericEntityUnescaper.options - fix TODO - RandomStringGenerator claims to be immutable, but isn't - Add StrLookup.resourceBundleLookup(ResourceBundle) - Typo in LongestCommonSubsequence#logestCommonSubsequence - - - WordUtils should use toXxxxCase(int) rather than toXxxxCase(char) - WordUtils.abbreviate support - Putting WordUtils back in to the codebase - Add RandomStringGenerator - RandomStringGenerator: allow users to provide source of randomness - Correct round issue in Jaro Winkler implementation - Similar to LANG-1025, clirr fails site build. - - + + Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...). + Inserting at the end of a TextStringBuilder throws a StringIndexOutOfBoundsException. + Fix TextStringBuilderTest.testAppendToCharBuffer() to use proper argument type #724. + Fix Apache RAT plugin console warnings. + Fix site XML to use version 2.0.0 XML schema. + Removed unreachable threshold verification code in src/main/java/org/apache/commons/text/similarity #730. + Enable secure processing for the XML parser in XmlStringLookup in case the underlying JAXP implementation doesn't #729. + + Add experimental CycloneDX VEX file #683. + Add Damerau-Levenshtein distance #687. + Add unit tests to increase coverage #719. + Add new test for CharSequenceTranslator#with() #725. + Add tests and assertions to org.apache.commons.text.similarity to get to 100% code coverage #727, #728. + + Bump org.apache.commons:commons-parent from 85 to 93 #704, #723, #726. + Bump commons.bytebuddy.version from 1.17.6 to 1.18.2 #696, #722. + Bump graalvm.version from 24.2.2 to 25.0.1 #703, #716. + Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. + Bump commons-io:commons-io from 2.20.0 to 2.21.0. + + + + Fix PMD UnnecessaryFullyQualifiedName in StringLookupFactory. + Fix PMD UnnecessaryFullyQualifiedName in DefaultStringLookupsHolder. + Fix PMD UnnecessaryFullyQualifiedName in PropertiesStringLookup. + Fix PMD UnnecessaryFullyQualifiedName in JavaPlatformStringLookup. + Fix PMD UnnecessaryFullyQualifiedName in StringSubstitutor. + Fix PMD UnnecessaryFullyQualifiedName in StrSubstitutor. + Fix PMD UnnecessaryFullyQualifiedName in AlphabetConverter. + Fix PMD AvoidBranchingStatementAsLastInLoop in TextStringBuilder. + Fix PMD AvoidBranchingStatementAsLastInLoop in StrBuilder. + org.apache.commons.text.translate.LookupTranslator.LookupTranslator(Map CharSequence>) now throws NullPointerException instead of java.security.InvalidParameterException. + + Interface StringLookup now extends UnaryOperator<String>. + Interface TextRandomProvider extends IntUnaryOperator. + Add RandomStringGenerator.Builder.usingRandom(IntUnaryOperator). + Add PMD check to default Maven goal. + Add org.apache.commons.text.RandomStringGenerator.Builder.setAccumulate(boolean). + + Bump org.apache.commons:commons-parent from 81 to 85 #668. + Bump commons-io:commons-io from 2.18.0 to 2.20.0. + Bump graalvm.version from 24.2.0 to 24.2.2 #665, #681. + Bump commons.bytebuddy.version from 1.17.5 to 1.17.6 (#677). + Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #680. + + + + Remove -nouses directive from maven-bundle-plugin. OSGi package imports now state 'uses' definitions for package imports, this doesn't affect JPMS (from org.apache.commons:commons-parent:80). + Deprecate EntityArrays.EntityArrays(). + StringLookupFactory.DefaultStringLookupsHolder.createDefaultStringLookups() maps DefaultStringLookup.LOCAL_HOST twice instead of once for LOCAL_HOST and LOOPBACK_ADDRESS. + + + Bump org.apache.commons:commons-parent from 79 to 81. + Bump commons.bytebuddy.version from 1.16.1 to 1.17.5 #643, #659, #660. + Bump graalvm.version from 24.1.2 to 24.2.0 #653. + + + + Add StringLookupFactory.loopbackAddressStringLookup(). + Add StringLookupFactory.KEY_LOOPBACK_ADDRESS. + Add DefaultStringLookup.LOOPBACK_ADDRESS. + Add richer inputs in package org.apache.commons.text.similarity with SimilarityInput. + Add HammingDistance.apply(SimilarityInput, SimilarityInput). + Add JaccardDistance.apply(SimilarityInput, SimilarityInput). + Add JaccardSimilarity.apply(SimilarityInput, SimilarityInput). + Add JaroWinklerDistance.apply(SimilarityInput, SimilarityInput). + Add JaroWinklerSimilarity.apply(SimilarityInput, SimilarityInput). + Add LevenshteinDetailedDistance.apply(SimilarityInput, SimilarityInput). + Add LevenshteinDistance.apply(SimilarityInput, SimilarityInput). + + Fix build on Java 22. + Fix build on Java 23-ea. + Make package-private constructor private: StrLookup.MapStrLookup.MapStrLookup(Map). + Make package-private constructor private: StrLookup.SystemPropertiesStrLookup.SystemPropertiesStrLookup(). + Make package-private class private and final: MapStrLookup. + Make package-private class private: StrMatcher.CharMatcher. + Make package-private class private: StrMatcher.CharSetMatcher. + Make package-private class private: StrMatcher.NoMatcher. + Make package-private class private: StrMatcher.StringMatcher. + Make package-private class private: StrMatcher.TrimMatcher. + Make package-private class private and final: IntersectionSimilarity.BagCount. + Make package-private class private and final: IntersectionSimilarity.TinyCount. + Deprecate LevenshteinDistance.LevenshteinDistance() in favor of LevenshteinDistance.getDefaultInstance(). + Deprecate LevenshteinDetailedDistance.LevenshteinDetailedDistance() in favor of LevenshteinDetailedDistance.getDefaultInstance(). + Improve StrBuilder documentation for new line text. + Improve TextStringBuilder documentation for new line text #547. + Required OSGi Import-Package version numbers in MANIFEST.MF #627. + + Bump org.apache.commons:commons-parent from 69 to 78 #542, #557, #571, #581, #584, #593, #600, #603, #614. + Bump tests on Java >= 22 org.graalvm.*:* from 24.0.0 to 24.1.1 #592, #610. + Bump commons.bytebuddy.version from 1.14.13 to 1.16.1 #538, #548, #553, #565, #579, #582, #585, #596, #597, #604, #612, #620, #623, #625, #640. + Bump SpotBugs from 4.8.3 to 4.8.5. + Bump org.assertj:assertj-core from 3.25.3 to 3.26.3 #554, #566. + Bump org.codehaus.mojo:taglist-maven-plugin from 3.0.0 to 3.2.1 #564, #611. + Bump org.apache.commons:commons-rng-simple from 1.5 to 1.6 #568. + Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #569, #575, #586. + Bump commons-io:commons-io from 2.16.1 to 2.18.0 #594, #628. + + + + Add StringLookupFactory.fileStringLookup(Path...) and deprecated fileStringLookup(). + Add StringLookupFactory.propertiesStringLookup(Path...) and deprecated propertiesStringLookup(). + Add StringLookupFactory.xmlStringLookup(Map, Path...) and deprecated xmlStringLookup() and xmlStringLookup(Map). + Add StringLookupFactory.builder() for fencing Path resolution of the file, properties and XML lookups. + Add DoubleFormat.Builder.get() as Builder now implements Supplier. + + WordUtils.containsAllWords​() may throw PatternSyntaxException. + Fix regression for determining whitespace in WordUtils #519. + Deprecate Builder in favor of Supplier. + + Bump commons-lang3 from 3.13.0 to 3.14.0. + Bump commons.bytebuddy.version from 1.14.9 to 1.14.13 #476, #482, #505, #521. + Bump org.codehaus.mojo:exec-maven-plugin from 3.1.0 to 3.2.0 #474, #508. + Bump commons-io from 2.15.0 to 2.16.1 #522, #527. + Bump commons-parent from 64 to 69 #524. + Bump org.assertj:assertj-core from 3.24.2 to 3.25.3. + + + + Fix StringTokenizer.getTokenList to return an independent modifiable list + Fix Javadoc for StringEscapeUtils.escapeHtml4 #382 + TextStringBuidler#hashCode() allocates a String on each call #387. + Fix Bundle-SymbolicName to use the package name org.apache.commons.text + Add and use a package-private singleton for RegexTokenizer. + Add and use a package-private singleton for CosineSimilarity. + Add and use a package-private singleton for LongestCommonSubsequence. + Add and use a package-private singleton for JaroWinklerSimilarity. + Add and use a package-private singleton for JaccardSimilarity. + [StepSecurity] ci: Harden GitHub Actions #428. + Improve AlphabetConverter Javadoc #429. + Fix exception message in IntersectionResult to make set-theoretic sense #438. + Add null-check in RandomStringGenerator#Builder#selectFrom() to avoid NullPointerException #434. + Add null-check in RandomStringGenerator#Builder#withinRange() to avoid NullPointerException. + Fix TextStringBuilder to over-allocate when ensuring capacity #452. + Constructor for ResourceBundleStringLookup should be private instead of package-private. + Constructor for UrlDecoderStringLookup should be private instead of package-private. + Constructor for UrlEncoderStringLookup should be private instead of package-private. + Javadoc of org.apache.commons.text.lookup.DefaultStringLookup.XML is incorrect. + Update DoubleFormat to state it is based on Double.toString. #467. + + Set SecureProcessing feature in XmlStringLookup by default. + Add StringLookupFactory.xmlStringLookup(Map<String, Boolean>...). + Add @FunctionalInterface to FormatFactory. + Add RandomStringGenerator.builder(). + Add XmlEncoderStringLookup/XmlDecoderStringLookup #449. + Add StringSubstitutor.toString(). + + Bump actions/cache. + Bump actions/setup-java. + Bump actions/checkout. + Bump pmd from 6.49.0 to 6.52.0 #364. + Bump commons-rng-simple from 1.4 to 1.5 #370. + Bump spotbugs-maven-plugin from 4.7.2.0 to 4.7.3.6 #371, #385. + Bump spotbugs from 4.7.2 to 4.7.3 #373. + Bump mockito-inline from 4.8.0 to 4.11.0 #380, #389, #396, #400. + Bump jmh.version from 1.35 to 1.37 #388. + Bump commons-parent from 54 to 64 #392, #401. + Bump assertj-core from 3.23.1 to 3.24.2 #405, #410. + Bump maven-checkstyle-plugin from 3.2.0 to 3.2.1 #407. + Bump commons-io from 2.11.0 to 2.15.0. + Bump commons-lang3 from 3.12.0 to 3.13.0. + + + + Fix CaseUtils when the input string contains only delimiters + Add GraalVM test dependencies to fix test failures with Java 15. + Incorrect values for Jaccard similarity with empty strings. + StringSubstitutor map constructor throws NPE on 1.9 with null map. + JaroWinklerDistance returns the same values as JaroWinklerSimilarity. + Correct Javadoc in FileStringLookup. + Minor Improvements #192, #196. + Use StringUtils.INDEX_NOT_FOUND constant. + Remove redundant local variable. + Replace lambda with method reference. + Simplify statements. + Replace statement lambda with expression lambda. + Use static class inner class in tests. + Simplify assertion. + Extract duplicate code. + Set void return method. + Remove unused exception from TextStringBuilder.readFrom(CharBuffer). This preserves binary compatibility but not source compatibility. + StrBuilder.StrBuilderReader.skip(long): Throw an exception when an implicit narrowing conversion in a compound assignment would result in information loss or a numeric error such as an overflows. + TextStringBuilder.TextStringBuilderReader.skip(long): Throw an exception when an implicit narrowing conversion in a compound assignment would result in information loss or a numeric error such as an overflows. + TextStringBuilder.equals whatever the capacity is #281. + A More Efficient Implementation for Calculating Size of Longest Common Subsequence. + LookupTranslator returns count of chars consumed, not of codepoints consumed. + Use Math.min() call instead of doing it manually. #335. + TextStringBuilder: Throw OutOfMemoryError instead of NegativeArraySizeException. + TextStringBuilder: Can't grow to sizes up to Integer.MAX_VALUE. + Make default string lookups configurable via system property. Remove dns, url, and script lookups from defaults. If these lookups are required for use in StringSubstitutor.createInterpolator(), they must be enabled via system property. See StringLookupFactory for details. + + Add DoubleFormat utility. + Document negative limit for WordUtils abbreviate method + Speed up LevenshteinDistance with threshold by exiting early + Release Notes page hasn't been updated for 1.9 release yet. + Add StrBuilder.isNotEmpty(). + + Bump actions/setup-java from v1.4.0 to 3 #147, #156, #155, #172, #215, #314. + Bump github/codeql-action from 1 to 2 #319. + Bump checkstyle from 8.34 to 9.3, #141, #168, #182, #188, #193, #201, #208, #211, #228, #235, #245, #253, #255, #262, #270, #280, #287, #299, #315, #321. + Bump spotbugs-maven-plugin from 4.0.0 to 4.7.2.0, #144, #150, #167, #176, #194, #210, #223, #250, #268, #273, #277, #278, #286, #293, #303, #320, #325, #338, #344, #354. + Bump spotbugs from 4.1.3 to 4.7.2 #175, 189, #209, #218, #247, #256, #264, #275, #284, #289, #296, #306, #355. + Bump mockito-inline from 3.4.4 to 4.8.0, #143, #148, #149, #152, #153, #154, #158, #159, #166, #177, #180, #187, #195, #197, #207, #216, #231, #236, #237, #243, #258, #259, #260, #261, #272, #285, #291, #305, #317, #330, #331, #347, #352. + Bump junit-jupiter from 5.6.2 to 5.9.1 #163, #204, #232, #265, #269, #288, #343, #357. + Bump assertj-core from 3.16.1 to 3.23.1 #151, #157, #160, #178, #184, #199, #244, #267, #294. + Bump commons-io from 2.7 to 2.11.0 #161 #251. + Bump commons-parent from 51 to 54 #145, #358. + Bump maven-pmd-plugin from 3.13.0 to 3.19.0 #186, #263, #302, #334, #349, #353. + Bump pmd from 6.42.0 to 6.46.0. + Bump graalvm.version from 20.2.0 to 22.0.0.2 #185, #198, #206, #227, #252, #276, #295, #300. + Bump commons.japicmp.version from 0.14.3 to 0.16.0. + Bump commons.jacoco.version 0.8.5 to 0.8.8; fixes Java 15 build. + Bump maven-checkstyle-plugin from 3.1.1 to 3.2.0 #202, #348. + Bump commons-lang3 3.11 -> 3.12.0. + Bump commons.javadoc.version from 3.2.0 to 3.4.1. + Bump commons.project-info.version from 3.1.0 to 3.1.2. + Bump jmh.version from 1.32 to 1.35 #254, #292, #313. + Bump commons-rng-simple from 1.3 to 1.4 #266. + Bump taglist-maven-plugin from 2.4 to 3.0.0 #297. + Bump commons.pmd-impl.version from 6.44.0 to 6.49.0 #323, #336, #345, #350. + Bump exec-maven-plugin from 3.0.0 to 3.1.0 #340. + + + Removed non-existing parameter from Javadocs and spelled out parameters in throws. + StringEscapeUtils.unescapeCsv doesn't remove quotes at begin and end of string. + ScriptStringLookup does not accept ":" #126. + StringSubstitutor incorrectly removes some escape characters. + Fix Javadocs #135. + Fix typos #137. + Make ConstantStringLookup.constantCache final #136. + Simplify if in CaseUtils #134. + [javadoc] Fix compiler warnings in Java code example in Javadoc #124. + Update from Apache Commons Lang 3.9 to 3.11. + Add StringMatcher.size(). + Refactor TextStringBuilder.readFrom(Readable), extracting readFrom(CharBuffer) and readFrom(Reader). + Add BiStringLookup and implementation BiFunctionStringLookup. + Add org.apache.commons.text.StringSubstitutor.StringSubstitutor(StringSubstitutor). + Add org.apache.commons.text.TextStringBuilder.TextStringBuilder(CharSequence). + Add org.apache.commons.text.TextStringBuilder.drainChar(int). + Add org.apache.commons.text.TextStringBuilder.drainChars(int, int, char[]. int). + Add org.apache.commons.text.TextStringBuilder.isNotEmpty(). + Add org.apache.commons.text.TextStringBuilder.isReallocated(). + Add org.apache.commons.text.TextStringBuilder.readFrom(Reader, int). + Add org.apache.commons.text.TextStringBuilder.set(String). + Add org.apache.commons.text.TextStringBuilder.wrap(char[]). + Add org.apache.commons.text.TextStringBuilder.wrap(char[], int). + Add org.apache.commons.text.io.StringSubstitutorReader. + Add org.apache.commons.text.lookup.StringLookupFactory.functionStringLookup(Function<String, V>). + Add org.apache.commons.text.matcher.StringMatcher.isMatch(CharSequence, int). + Add org.apache.commons.text.matcher.StringMatcher.isMatch(CharSequence, int, int, int). + Add org.apache.commons.text.matcher.StringMatcherFactory.andMatcher(StringMatcher...). + Add org.apache.commons.text.matcher.StringMatcherFactory.stringMatcher(char...). + [build] Skip clirr since we use JApiCmp. + [test] junit-jupiter 5.5.1 -> 5.5.2. + [test] org.assertj:assertj-core 3.13.2 -> 3.16.1. + [build] com.puppycrawl.tools:checkstyle 8.23 -> 8.34. + [build] Update JUnit from 5.5.2 to 5.6.2. + [build] commons.jacoco.version 0.8.4 -> 0.8.5. + [build] commons.javadoc.version 3.1.1 -> 3.2.0. + [build] commons.japicmp.version 0.14.1 -> 0.14.3. + [build] checkstyle.plugin.version 3.1.0 -> 3.1.1. + [build] checkstyle.version 8.27 -> 8.33. + [build] org.apache.commons:commons-parent 48 -> 51. + [build] maven-pmd-plugin 3.12.0 -> 3.13.0. + [build] org.mockito 3.3.3 -> 3.4.4. + + + commons-text web page missing "RELEASE-NOTES-1.7.txt" + (doc) Fixed wrong value for Jaro-Winkler example #117 + Add helper factory method org.apache.commons.text.StringSubstitutor.createInterpolator(). + Add String lookup for host names and IP addresses (DnsStringLookup). + StringLookupFactory.addDefaultStringLookups(Map) does not convert keys to lower case. + Expand Javadoc for StringSubstitutor and friends. + [site] checkstyle.version 8.21 -> 8.23. + + + WordUtils.wrap must calculate offset increment from wrapOn pattern length + Jaro Winkler Distance refers to similarity + Add an enum to the lookup package that lists all StringLookups + Add a toggle to throw an exception when a variable is unknown in StringSubstitutor + TextStringBuilder append sub-sequence not consistent with Appendable. + Fix possible infinite loop in WordUtils.wrap for a regex pattern that would trigger on a match of 0 length + Make prefixSet in LookupTranslator a BitSet + Fix the RegexTokenizer to use a static Pattern + Remove rounding from JaccardDistance and JaccardSimilarity + Fix the JaroWinklerSimilarity to use StringUtils.equals to test for CharSequence equality + Add a generic IntersectionSimilarity measure + Update Apache Commons Lang from 3.8.1 to 3.9. + ResourceBundleStringLookup.lookup(String) throws MissingResourceException instead of returning null. + Update tests from org.assertj:assertj-core 3.12.1 to 3.12.2. + Update site from com.puppycrawl.tools:checkstyle 8.18 to 8.21. + + + Add the resource string bundle string lookup to the default set of lookups + Add StringLookupFactory methods for the URL encoder and decoder string lookups + org.apache.commons.text.lookup.StringLookupFactory.interpolatorStringLookup() should reuse a singleton instance + Add a Base64 encoder string lookup. + + + Improve JaccardSimilarity computational cost + JSON escaping incorrect for the delete control character + Fixes JaroWinklerDistance: Wrong results due to precision of transpositions + JaroWinklerDistance: Calculation deviates from definition + Update Apache Commons Lang from 3.7 to 3.8.1 + Add a XML file XPath string lookup. + Add a Properties file string lookup. + Add a script string lookup. + Add a file string lookup. + Add a URL string lookup. + Add a Base64 string lookup. + Add org.apache.commons.text.lookup.StringLookupFactory.resourceBundleStringLookup(String). + Add URL encoder and decoder string lookups. + Add constant string lookup like the one in Apache Commons Configuration. + + + StringEscapeUtils#unescapeJson does not unescape double quotes and forward slash + Remove mention of SQL escaping from user guide + Update Java requirement from version 7 to 8. + Allow full customization with new API org.apache.commons.text.lookup.StringLookupFactory.interpolatorStringLookup(Map<String, StringLookup>, StringLookup, boolean). + WordUtils.wrap throws StringIndexOutOfBoundsException when wrapLength is Integer.MAX_VALUE. + + + Add Automatic-Module-Name MANIFEST entry for Java 9 compatibility + Build failure with java 9-ea+159 + Add an interpolator string lookup: StringLookupFactory#interpolatorStringLookup() + Add a StrSubstitutor replacement based on interfaces: StringSubstitutor + Add a StrBuilder replacement based on the StringMatcher interface: TextStringBuilder + Add a StrTokenizer replacement based on the StringMatcher interface: StringTokenizer + Add a local host string lookup: LocalHostStringLookup + StrLookup API confusing + + + Upversion commons-lang to 3.7 + Exception thrown in ExtendedMessageFormat using quotes with custom registry + StringEscapeUtils#UnEscapeJson doesn't recognize escape signs correctly + StrSubstitutor: Ability to turn off substitution in values + RandomStringGenerator able to pass multiple ranges to .withinRange() + Deprecate isDelimiter and use HashSets for delimiter checks + WordUtils.initials support for UTF-16 surrogate pairs + WordUtils should treat an empty delimiter array as no delimiters + Update RandomStringGenerator to accept a list of valid characters + Add CharacterPredicates for ASCII letters (uppercase/lowercase) and arabic numerals + Added CaseUtils class with camel case conversion support + RandomStringGenerator should be able to generate a String with a random length + Update commons-lang dependency to version 3.6 + Document that commons-csv should be used in preference to CsvTranslators + NumericEntityUnescaper.options - fix TODO + RandomStringGenerator claims to be immutable, but isn't + Add StrLookup.resourceBundleLookup(ResourceBundle) + Typo in LongestCommonSubsequence#logestCommonSubsequence + + + WordUtils should use toXxxxCase(int) rather than toXxxxCase(char) + WordUtils.abbreviate support + Putting WordUtils back in to the codebase + Add RandomStringGenerator + RandomStringGenerator: allow users to provide source of randomness + Correct round issue in Jaro Winkler implementation + Similar to LANG-1025, clirr fails site build. + + - Investigate locale issue in ExtendedMessageFormatTest - Resolve PMD/CMD Violations - Escape HTML characters only once: revert - Fixing the 200 checkstyle errors present in 1.0-beta-1 - Mutable fields should be private - - - Incorporate suggestions from RC2 into 1.0 release - Naming packages org.apache.commons.text.beta - Upgrading Jacoco for Java 9-ea compatibility. - Refactor EntityArrays to have unmodifiableMaps in leu of String[][] - Prepare site for 1.0 release - Move CvsTranslators out of StringEscapeUtils and make them DRY - Remove WordUtils to be added back in an upcoming 1.X release - Possible attacks through StringEscapeUtils.escapeEcmaScrip better javadoc - Remove RandomStringGenerator to be added back in the 1.1 release - Upgrade from commons-parent version 41 to version 42 - Escape HTML characters only once - Global vs local source of randomness - Fluent API in "RandomStringBuilder" - Fix JaroWinklerDistance in the manner of LUCENE-1297 - Add LCS similarity and distance - Add class to generate random strings - Unfinished class Javadoc for CosineDistance - Consolidating since tags at 1.0, removing deprecated methods - Add a builder to StringEscapeUtils - Add shell/XSI escape/unescape support - LevenshteinDistance reduce memory consumption - Remove org.apache.commons.text.names, for later release than 1.0 - Add Jaccard Index and Jaccard Distance - Move org.apache.commons.lang3.StringEscapeUtils.java into text - Moving from commons-lang, the package org.apache.commons.lang3.text - A more complex Levenshtein distance - Add coveralls and Travis.ci integration - Add alphabet converter - Create Commons Text logo - Improve HumanNameParser - IP clearance for the names package - Write user guide - Work on the string metric, distance, and similarity definitions for the project - Human name parser - Create StringDistanceFrom class that contains a StringMetric and the "left" side string. This would have a method that accepts the "right" side string to test. - Add Cosine Similarity and Cosine Distance - Change (R) StringMetric.compare(CS left, CS right) to "apply" so that it is consistent with BiFunction. - Allow extra information (e.g. Levenshtein threshold) to be stored as (final) fields in the StringMetric instance. - Port Myers algorithm from [collections] - Add Hamming distance - Incorporate String algorithms from Commons Lang - + Investigate locale issue in ExtendedMessageFormatTest + Resolve PMD/CMD Violations + Escape HTML characters only once: revert + Fixing the 200 checkstyle errors present in 1.0-beta-1 + Mutable fields should be private + + + Incorporate suggestions from RC2 into 1.0 release + Naming packages org.apache.commons.text.beta + Upgrading Jacoco for Java 9-ea compatibility. + Refactor EntityArrays to have unmodifiableMaps in leu of String[][] + Prepare site for 1.0 release + Move CvsTranslators out of StringEscapeUtils and make them DRY + Remove WordUtils to be added back in an upcoming 1.X release + Possible attacks through StringEscapeUtils.escapeEcmaScrip better javadoc + Remove RandomStringGenerator to be added back in the 1.1 release + Upgrade from commons-parent version 41 to version 42 + Escape HTML characters only once + Global vs local source of randomness + Fluent API in "RandomStringBuilder" + Fix JaroWinklerDistance in the manner of LUCENE-1297 + Add LCS similarity and distance + Add class to generate random strings + Unfinished class Javadoc for CosineDistance + Consolidating since tags at 1.0, removing deprecated methods + Add a builder to StringEscapeUtils + Add shell/XSI escape/unescape support + LevenshteinDistance reduce memory consumption + Remove org.apache.commons.text.names, for later release than 1.0 + Add Jaccard Index and Jaccard Distance + Move org.apache.commons.lang3.StringEscapeUtils.java into text + Moving from commons-lang, the package org.apache.commons.lang3.text + A more complex Levenshtein distance + Add coveralls and Travis.ci integration + Add alphabet converter + Create Commons Text logo + Improve HumanNameParser + IP clearance for the names package + Write user guide + Work on the string metric, distance, and similarity definitions for the project + Human name parser + Create StringDistanceFrom class that contains a StringMetric and the "left" side string. This would have a method that accepts the "right" side string to test. + Add Cosine Similarity and Cosine Distance + Change (R) StringMetric.compare(CS left, CS right) to "apply" so that it is consistent with BiFunction. + Allow extra information (e.g. Levenshtein threshold) to be stored as (final) fields in the StringMetric instance. + Port Myers algorithm from [collections] + Add Hamming distance + Incorporate String algorithms from Commons Lang + From 708d06f6ddadbe97a25edf25a7380122eae117a0 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 2 Jan 2026 17:39:34 -0500 Subject: [PATCH 236/265] Bump org.apache.commons:commons-parent from 93 to 94 --- pom.xml | 2 +- src/changes/changes.xml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index d79a4eeb05..7840ddf8bc 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 93 + 94 commons-text 1.15.1-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index b45a1061c8..aa3adb90ec 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,8 +48,9 @@ The type attribute can be add,update,fix,remove. Improve test coverage #732. - Bump the level of test coverage checks. - Bump commons.bytebuddy.version from 1.18.2 to 1.18.3 #734. + Bump org.apache.commons:commons-parent from 93 to 94. + Bump the level of test coverage checks. + Bump commons.bytebuddy.version from 1.18.2 to 1.18.3 #734. From ee55227521be8d45c3f9782392ea797d2ed1a1c5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 2 Jan 2026 18:22:08 -0500 Subject: [PATCH 237/265] Javadoc --- src/main/java/org/apache/commons/text/diff/EditCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/diff/EditCommand.java b/src/main/java/org/apache/commons/text/diff/EditCommand.java index ddcfbedec3..247f5c0bcd 100644 --- a/src/main/java/org/apache/commons/text/diff/EditCommand.java +++ b/src/main/java/org/apache/commons/text/diff/EditCommand.java @@ -17,7 +17,7 @@ package org.apache.commons.text.diff; /** - * Abstract base class for all commands used to transform an objects sequence + * Abstrac class for all commands used to transform an objects sequence * into another one. *

    * When two objects sequences are compared through the From 57e2298100e616f3a8833e7c3761f5e3bd4e5e26 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 2 Jan 2026 18:36:22 -0500 Subject: [PATCH 238/265] Javadoc --- src/main/java/org/apache/commons/text/diff/EditCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/diff/EditCommand.java b/src/main/java/org/apache/commons/text/diff/EditCommand.java index 247f5c0bcd..30cb38c4c2 100644 --- a/src/main/java/org/apache/commons/text/diff/EditCommand.java +++ b/src/main/java/org/apache/commons/text/diff/EditCommand.java @@ -17,7 +17,7 @@ package org.apache.commons.text.diff; /** - * Abstrac class for all commands used to transform an objects sequence + * Abstract class for all commands used to transform an objects sequence * into another one. *

    * When two objects sequences are compared through the From 98a5115e8da7fabc7415e268a3a1d67cf512cf38 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 4 Jan 2026 15:27:05 -0500 Subject: [PATCH 239/265] Remove dead comments --- src/main/java/org/apache/commons/text/StringEscapeUtils.java | 2 -- src/main/java/org/apache/commons/text/StringSubstitutor.java | 1 - 2 files changed, 3 deletions(-) diff --git a/src/main/java/org/apache/commons/text/StringEscapeUtils.java b/src/main/java/org/apache/commons/text/StringEscapeUtils.java index b9ee6e0e75..dc9d544094 100644 --- a/src/main/java/org/apache/commons/text/StringEscapeUtils.java +++ b/src/main/java/org/apache/commons/text/StringEscapeUtils.java @@ -562,7 +562,6 @@ public static String escapeHtml3(final String input) { return ESCAPE_HTML3.translate(input); } - // HTML and XML /** * Escapes the characters in a {@code String} using HTML entities. * @@ -591,7 +590,6 @@ public static String escapeHtml4(final String input) { return ESCAPE_HTML4.translate(input); } - // Java and JavaScript /** * Escapes the characters in a {@code String} using Java String rules. * diff --git a/src/main/java/org/apache/commons/text/StringSubstitutor.java b/src/main/java/org/apache/commons/text/StringSubstitutor.java index d794c2999c..3667e91529 100644 --- a/src/main/java/org/apache/commons/text/StringSubstitutor.java +++ b/src/main/java/org/apache/commons/text/StringSubstitutor.java @@ -671,7 +671,6 @@ private void checkCyclicSubstitution(final String varName, final List pr throw new IllegalStateException(buf.toString()); } - // Escape /** * Returns the escape character. * From 0735a2159cbc1013cbff70a9ba8fd9c24e9022f4 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 4 Jan 2026 15:27:17 -0500 Subject: [PATCH 240/265] Javadoc Add an empty line before a Javadoc comment --- src/main/java/org/apache/commons/text/StringEscapeUtils.java | 2 ++ .../java/org/apache/commons/text/diff/StringsComparator.java | 3 +++ .../apache/commons/text/lookup/JavaPlatformStringLookup.java | 5 +++++ .../org/apache/commons/text/translate/CsvTranslators.java | 4 ++++ .../org/apache/commons/text/translate/LookupTranslator.java | 3 +++ .../org/apache/commons/text/translate/UnicodeEscaper.java | 2 ++ .../text/jmh/LongestCommonSubsequencePerformance.java | 1 + 7 files changed, 20 insertions(+) diff --git a/src/main/java/org/apache/commons/text/StringEscapeUtils.java b/src/main/java/org/apache/commons/text/StringEscapeUtils.java index dc9d544094..700ca95690 100644 --- a/src/main/java/org/apache/commons/text/StringEscapeUtils.java +++ b/src/main/java/org/apache/commons/text/StringEscapeUtils.java @@ -122,6 +122,7 @@ public String toString() { return sb.toString(); } } + /** * Translator object for unescaping backslash escaped entries. */ @@ -323,6 +324,7 @@ public int translate(final CharSequence input, final int index, final Writer wri new LookupTranslator(EntityArrays.ISO8859_1_ESCAPE), new LookupTranslator(EntityArrays.HTML40_EXTENDED_ESCAPE) ); + /** * Translator object for escaping individual Comma Separated Values. * diff --git a/src/main/java/org/apache/commons/text/diff/StringsComparator.java b/src/main/java/org/apache/commons/text/diff/StringsComparator.java index 9f9813a959..2f530650ac 100644 --- a/src/main/java/org/apache/commons/text/diff/StringsComparator.java +++ b/src/main/java/org/apache/commons/text/diff/StringsComparator.java @@ -106,14 +106,17 @@ public int getStart() { return start; } } + /** * First character sequence. */ private final String left; + /** * Second character sequence. */ private final String right; + /** * Temporary array. */ diff --git a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java index faf01ee9cb..2b280b9819 100644 --- a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java @@ -66,14 +66,19 @@ final class JavaPlatformStringLookup extends AbstractStringLookup { * Defines the singleton for this class. */ static final JavaPlatformStringLookup INSTANCE = new JavaPlatformStringLookup(); + /** {@code hardware} key for driving {@link JavaPlatformStringLookup#lookup(String)}. */ private static final String KEY_HARDWARE = "hardware"; + /** {@code locale} key for driving {@link JavaPlatformStringLookup#lookup(String)}. */ private static final String KEY_LOCALE = "locale"; + /** {@code os} key for driving {@link JavaPlatformStringLookup#lookup(String)}. */ private static final String KEY_OS = "os"; + /** {@code runtime} key for driving {@link JavaPlatformStringLookup#lookup(String)}. */ private static final String KEY_RUNTIME = "runtime"; + /** {@code version} key for driving {@link JavaPlatformStringLookup#lookup(String)}. */ private static final String KEY_VERSION = "version"; diff --git a/src/main/java/org/apache/commons/text/translate/CsvTranslators.java b/src/main/java/org/apache/commons/text/translate/CsvTranslators.java index 9a5f467136..b116e50eac 100644 --- a/src/main/java/org/apache/commons/text/translate/CsvTranslators.java +++ b/src/main/java/org/apache/commons/text/translate/CsvTranslators.java @@ -59,6 +59,7 @@ void translateWhole(final CharSequence input, final Writer writer) throws IOExce } } } + /** * Translator for unescaping escaped Comma Separated Value entries. */ @@ -90,10 +91,13 @@ void translateWhole(final CharSequence input, final Writer writer) throws IOExce } } } + /** Comma character. */ private static final char CSV_DELIMITER = ','; + /** Quote character. */ private static final char CSV_QUOTE = '"'; + /** Quote character converted to string. */ private static final String CSV_QUOTE_STR = String.valueOf(CSV_QUOTE); diff --git a/src/main/java/org/apache/commons/text/translate/LookupTranslator.java b/src/main/java/org/apache/commons/text/translate/LookupTranslator.java index 931344c55e..18f2f09287 100644 --- a/src/main/java/org/apache/commons/text/translate/LookupTranslator.java +++ b/src/main/java/org/apache/commons/text/translate/LookupTranslator.java @@ -33,10 +33,13 @@ public class LookupTranslator extends CharSequenceTranslator { /** The mapping to be used in translation. */ private final Map lookupMap; + /** The first character of each key in the lookupMap. */ private final BitSet prefixSet; + /** The length of the shortest key in the lookupMap. */ private final int shortest; + /** The length of the longest key in the lookupMap. */ private final int longest; diff --git a/src/main/java/org/apache/commons/text/translate/UnicodeEscaper.java b/src/main/java/org/apache/commons/text/translate/UnicodeEscaper.java index a2e2c75157..cea0dcbbaa 100644 --- a/src/main/java/org/apache/commons/text/translate/UnicodeEscaper.java +++ b/src/main/java/org/apache/commons/text/translate/UnicodeEscaper.java @@ -35,6 +35,7 @@ public class UnicodeEscaper extends CodePointTranslator { public static UnicodeEscaper above(final int codePoint) { return outsideOf(0, codePoint); } + /** * Constructs a {@code UnicodeEscaper} below the specified value (exclusive). * @@ -44,6 +45,7 @@ public static UnicodeEscaper above(final int codePoint) { public static UnicodeEscaper below(final int codePoint) { return outsideOf(codePoint, Integer.MAX_VALUE); } + /** * Constructs a {@code UnicodeEscaper} between the specified values (inclusive). * diff --git a/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java b/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java index 49d1318ed3..b726616519 100644 --- a/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java +++ b/src/test/java/org/apache/commons/text/jmh/LongestCommonSubsequencePerformance.java @@ -49,6 +49,7 @@ @Measurement(iterations = 5, time = 1) @Fork(value = 1, jvmArgs = {"-server", "-Xms512M", "-Xmx512M"}) public class LongestCommonSubsequencePerformance { + /** * Older implementation of LongestCommonSubsequence. * Code is copied from Apache Commons Text version 1.10.0-SNAPSHOT From 6a118b75111b30fce340498e9fc06d8bc3e6421d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 12 Jan 2026 10:50:05 -0500 Subject: [PATCH 241/265] Bump github/codeql-action from 4.31.9 to 4.31.10 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d7e8c4a82c..c4c4c67879 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 3c49b0d632..30e15985e1 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: sarif_file: results.sarif From 6f274fc9b935a489fb631b54e556088e0890e36d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 12 Jan 2026 11:07:45 -0500 Subject: [PATCH 242/265] Bump org.apache.commons:commons-parent from 94 to 95. --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7840ddf8bc..f0d5e42d05 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 94 + 95 commons-text 1.15.1-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index aa3adb90ec..8abc4c96cd 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,7 +48,7 @@ The type attribute can be add,update,fix,remove. Improve test coverage #732. - Bump org.apache.commons:commons-parent from 93 to 94. + Bump org.apache.commons:commons-parent from 93 to 95. Bump the level of test coverage checks. Bump commons.bytebuddy.version from 1.18.2 to 1.18.3 #734. From 111ae69d4ffd0f0847e64af53d0310a0e691b2d3 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 21 Jan 2026 07:20:45 -0500 Subject: [PATCH 243/265] Bump commons.bytebuddy.version from 1.18.3 to 1.18.4 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f0d5e42d05..0f80e4454a 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text site-content 3.20.0 - 1.18.3 + 1.18.4 1.6 false 1.37 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 8abc4c96cd..ed6b40c295 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,7 +50,7 @@ The type attribute can be add,update,fix,remove. Bump org.apache.commons:commons-parent from 93 to 95. Bump the level of test coverage checks. - Bump commons.bytebuddy.version from 1.18.2 to 1.18.3 #734. + Bump commons.bytebuddy.version from 1.18.2 to 1.18.4 #734. From c9e8e25c57ecc2a36523f8886ecdaeca1320d933 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 21 Jan 2026 17:19:28 -0500 Subject: [PATCH 244/265] Bump org.apache.commons:commons-parent from 95 to 96 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0f80e4454a..f2049d7fde 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 95 + 96 commons-text 1.15.1-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ed6b40c295..9ce69c483b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,7 +48,7 @@ The type attribute can be add,update,fix,remove. Improve test coverage #732. - Bump org.apache.commons:commons-parent from 93 to 95. + Bump org.apache.commons:commons-parent from 93 to 96. Bump the level of test coverage checks. Bump commons.bytebuddy.version from 1.18.2 to 1.18.4 #734. From 9eb7dd84ed38c22d18b098cfadfdfc9a12f0eb38 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 22 Jan 2026 15:40:19 +0000 Subject: [PATCH 245/265] Bump actions/setup-java from 5.1.0 to 5.2.0 --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 30ddf451ed..b9b04ad5cf 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -38,7 +38,7 @@ jobs: with: persist-credentials: false - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} From da6c6cdfdc10df43ae0efe1678cf1cfd81b9e982 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 23 Jan 2026 07:44:40 -0500 Subject: [PATCH 246/265] Bump actions/checkout from 6.0.1 to 6.0.2 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/maven.yml | 2 +- .github/workflows/scorecards-analysis.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c4c4c67879..cc69f53340 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 1df8666044..a04da50909 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 'Dependency Review PR' uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index b9b04ad5cf..5a77f4db9d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -34,7 +34,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Set up JDK ${{ matrix.java }} diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 30e15985e1..966de08b57 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -40,7 +40,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false From 71f75f212c081e160e9937287e4cb0a93ef280f2 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 26 Jan 2026 09:37:42 -0500 Subject: [PATCH 247/265] Bump github/codeql-action from 4.31.10 to 4.31.11 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cc69f53340..17321f5dd1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/init@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/autobuild@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/analyze@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 966de08b57..73762bb58c 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/upload-sarif@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 with: sarif_file: results.sarif From a0b89c079b3af0da7bd6bdc3a8a3421182e14aa4 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 27 Jan 2026 20:41:25 -0500 Subject: [PATCH 248/265] Add Checkstyle FinalLocalVariable --- src/conf/checkstyle.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/conf/checkstyle.xml b/src/conf/checkstyle.xml index 7ae6627aff..0158804daa 100644 --- a/src/conf/checkstyle.xml +++ b/src/conf/checkstyle.xml @@ -85,6 +85,7 @@ + From a3e4306d56481d039d19bbb020fcffde4a5d91ce Mon Sep 17 00:00:00 2001 From: Ivan Ponomarev Date: Wed, 28 Jan 2026 11:15:12 +0000 Subject: [PATCH 249/265] TEXT-239: TextStringBuilder.append(char[], int, int) uses wrong variable in exception message (#735) * fix text-239 * fix for StrBuilder * fix checkstyle issues --- .../org/apache/commons/text/StrBuilder.java | 2 +- .../apache/commons/text/TextStringBuilder.java | 2 +- .../org/apache/commons/text/StrBuilderTest.java | 17 +++++++++++++++++ .../commons/text/TextStringBuilderTest.java | 17 +++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/text/StrBuilder.java b/src/main/java/org/apache/commons/text/StrBuilder.java index fce069d001..f1df60a2a2 100644 --- a/src/main/java/org/apache/commons/text/StrBuilder.java +++ b/src/main/java/org/apache/commons/text/StrBuilder.java @@ -376,7 +376,7 @@ public StrBuilder append(final char[] chars, final int startIndex, final int len return appendNull(); } if (startIndex < 0 || startIndex > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length); + throw new StringIndexOutOfBoundsException("Invalid startIndex: " + startIndex); } if (length < 0 || startIndex + length > chars.length) { throw new StringIndexOutOfBoundsException("Invalid length: " + length); diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java index b3ea8585f7..2977fa3232 100644 --- a/src/main/java/org/apache/commons/text/TextStringBuilder.java +++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java @@ -483,7 +483,7 @@ public TextStringBuilder append(final char[] chars, final int startIndex, final return appendNull(); } if (startIndex < 0 || startIndex > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length); + throw new StringIndexOutOfBoundsException("Invalid startIndex: " + startIndex); } if (length < 0 || startIndex + length > chars.length) { throw new StringIndexOutOfBoundsException("Invalid length: " + length); diff --git a/src/test/java/org/apache/commons/text/StrBuilderTest.java b/src/test/java/org/apache/commons/text/StrBuilderTest.java index 6ae331e931..5edfec6fc6 100644 --- a/src/test/java/org/apache/commons/text/StrBuilderTest.java +++ b/src/test/java/org/apache/commons/text/StrBuilderTest.java @@ -2017,4 +2017,21 @@ void testTrim() { assertEquals("a b c", sb.trim().toString()); } + @Test + void testErrorMessageShowsCorrectVariable() { + final StrBuilder sb = new StrBuilder("Hello"); + final char[] chars = {'a', 'b', 'c'}; + + StringIndexOutOfBoundsException ex = assertThrows( + StringIndexOutOfBoundsException.class, + () -> sb.append(chars, 1, 4) + ); + assertTrue(ex.getMessage().contains("length: 4")); + + ex = assertThrows( + StringIndexOutOfBoundsException.class, + () -> sb.append(chars, 7, 3) + ); + assertTrue(ex.getMessage().contains("startIndex: 7")); + } } diff --git a/src/test/java/org/apache/commons/text/TextStringBuilderTest.java b/src/test/java/org/apache/commons/text/TextStringBuilderTest.java index 1900c19d68..1efbf25113 100644 --- a/src/test/java/org/apache/commons/text/TextStringBuilderTest.java +++ b/src/test/java/org/apache/commons/text/TextStringBuilderTest.java @@ -2393,4 +2393,21 @@ void testWrap_CharArray_Int_Exceptions() { assertThrows(IllegalArgumentException.class, () -> TextStringBuilder.wrap(ArrayUtils.EMPTY_CHAR_ARRAY, 1)); } + @Test + void testErrorMessageShowsCorrectVariable() { + final TextStringBuilder sb = new TextStringBuilder("Hello"); + final char[] chars = {'a', 'b', 'c'}; + + StringIndexOutOfBoundsException ex = assertThrows( + StringIndexOutOfBoundsException.class, + () -> sb.append(chars, 1, 4) + ); + assertTrue(ex.getMessage().contains("length: 4")); + + ex = assertThrows( + StringIndexOutOfBoundsException.class, + () -> sb.append(chars, 7, 3) + ); + assertTrue(ex.getMessage().contains("startIndex: 7")); + } } From aa7ce204885d80b5c8d66e2b7f81401e9b2883e8 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 28 Jan 2026 06:18:09 -0500 Subject: [PATCH 250/265] [TEXT-239] TextStringBuilder.append(char[], int, int) uses wrong variable in exception message #735 Use longer lines Keep test methods in AB order --- src/changes/changes.xml | 1 + .../apache/commons/text/StrBuilderTest.java | 28 +++++++------------ .../commons/text/TextStringBuilderTest.java | 28 +++++++------------ 3 files changed, 21 insertions(+), 36 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 9ce69c483b..4bfbe4f854 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,6 +46,7 @@ The type attribute can be add,update,fix,remove. Improve test coverage #732. + TextStringBuilder.append(char[], int, int) uses wrong variable in exception message #735. Bump org.apache.commons:commons-parent from 93 to 96. diff --git a/src/test/java/org/apache/commons/text/StrBuilderTest.java b/src/test/java/org/apache/commons/text/StrBuilderTest.java index 5edfec6fc6..6d7de7e527 100644 --- a/src/test/java/org/apache/commons/text/StrBuilderTest.java +++ b/src/test/java/org/apache/commons/text/StrBuilderTest.java @@ -834,6 +834,16 @@ void testEqualsIgnoreCase() { assertTrue(sb1.equalsIgnoreCase(sb2)); } + @Test + void testErrorMessageShowsCorrectVariable() { + final StrBuilder sb = new StrBuilder("Hello"); + final char[] chars = { 'a', 'b', 'c' }; + StringIndexOutOfBoundsException ex = assertThrows(StringIndexOutOfBoundsException.class, () -> sb.append(chars, 1, 4)); + assertTrue(ex.getMessage().contains("length: 4")); + ex = assertThrows(StringIndexOutOfBoundsException.class, () -> sb.append(chars, 7, 3)); + assertTrue(ex.getMessage().contains("startIndex: 7")); + } + @Test void testGetChars() { final StrBuilder sb = new StrBuilder(); @@ -2016,22 +2026,4 @@ void testTrim() { sb.clear().append("a b c"); assertEquals("a b c", sb.trim().toString()); } - - @Test - void testErrorMessageShowsCorrectVariable() { - final StrBuilder sb = new StrBuilder("Hello"); - final char[] chars = {'a', 'b', 'c'}; - - StringIndexOutOfBoundsException ex = assertThrows( - StringIndexOutOfBoundsException.class, - () -> sb.append(chars, 1, 4) - ); - assertTrue(ex.getMessage().contains("length: 4")); - - ex = assertThrows( - StringIndexOutOfBoundsException.class, - () -> sb.append(chars, 7, 3) - ); - assertTrue(ex.getMessage().contains("startIndex: 7")); - } } diff --git a/src/test/java/org/apache/commons/text/TextStringBuilderTest.java b/src/test/java/org/apache/commons/text/TextStringBuilderTest.java index 1efbf25113..649fc4ea71 100644 --- a/src/test/java/org/apache/commons/text/TextStringBuilderTest.java +++ b/src/test/java/org/apache/commons/text/TextStringBuilderTest.java @@ -989,6 +989,16 @@ void testEqualsIgnoreCase() { // TextStringBuilder("title".toUpperCase(turkish)))); } + @Test + void testErrorMessageShowsCorrectVariable() { + final TextStringBuilder sb = new TextStringBuilder("Hello"); + final char[] chars = { 'a', 'b', 'c' }; + StringIndexOutOfBoundsException ex = assertThrows(StringIndexOutOfBoundsException.class, () -> sb.append(chars, 1, 4)); + assertTrue(ex.getMessage().contains("length: 4")); + ex = assertThrows(StringIndexOutOfBoundsException.class, () -> sb.append(chars, 7, 3)); + assertTrue(ex.getMessage().contains("startIndex: 7")); + } + @Test void testGetChars() { final TextStringBuilder sb = new TextStringBuilder(); @@ -2392,22 +2402,4 @@ void testWrap_CharArray_Int_Exceptions() { assertThrows(IllegalArgumentException.class, () -> TextStringBuilder.wrap("abc".toCharArray(), -1)); assertThrows(IllegalArgumentException.class, () -> TextStringBuilder.wrap(ArrayUtils.EMPTY_CHAR_ARRAY, 1)); } - - @Test - void testErrorMessageShowsCorrectVariable() { - final TextStringBuilder sb = new TextStringBuilder("Hello"); - final char[] chars = {'a', 'b', 'c'}; - - StringIndexOutOfBoundsException ex = assertThrows( - StringIndexOutOfBoundsException.class, - () -> sb.append(chars, 1, 4) - ); - assertTrue(ex.getMessage().contains("length: 4")); - - ex = assertThrows( - StringIndexOutOfBoundsException.class, - () -> sb.append(chars, 7, 3) - ); - assertTrue(ex.getMessage().contains("startIndex: 7")); - } } From 428759d708570efb146d1a8352b79517201c65f0 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 28 Jan 2026 15:45:59 -0500 Subject: [PATCH 251/265] Bump github/codeql-action from 4.31.11 to 4.32.0 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 17321f5dd1..658b44aef9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/autobuild@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 73762bb58c..4ca0930497 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: sarif_file: results.sarif From 38f06344985d89648ec15ae4cfddc6b426eb73ae Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 1 Feb 2026 07:52:00 -0500 Subject: [PATCH 252/265] Javadoc --- .../apache/commons/text/ExtendedMessageFormat.java | 9 +++++++-- .../text/similarity/LevenshteinDetailedDistance.java | 12 +++++++++--- .../commons/text/similarity/LevenshteinDistance.java | 4 +++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java b/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java index 2baac548f0..4dcd957fe5 100644 --- a/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java +++ b/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java @@ -33,15 +33,20 @@ /** * Extends {@link java.text.MessageFormat} to allow pluggable/additional formatting - * options for embedded format elements. Client code should specify a registry + * options for embedded format elements. + *

    + * Client code should specify a registry * of {@code FormatFactory} instances associated with {@code String} * format names. This registry will be consulted when the format elements are * parsed from the message pattern. In this way custom patterns can be specified, * and the formats supported by {@link java.text.MessageFormat} can be overridden * at the format and/or format style level (see MessageFormat). A "format element" - * embedded in the message pattern is specified (()? signifies optionality):
    + * embedded in the message pattern is specified (()? signifies optionality): + *

    + *

    * {@code {}argument-number({@code ,}format-name * ({@code ,}format-style)?)?{@code }} + *

    * *

    * format-name and format-style values are trimmed of surrounding whitespace diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java index ac7b4018aa..4b4740ea9a 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java @@ -277,7 +277,9 @@ private static LevenshteinResults limitedCompare(SimilarityInput left, Si * *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large - * strings.
    + * strings. + *

    + *

    * This implementation of the Levenshtein distance algorithm is from * http://www.merriampark.com/ldjava.htm *

    @@ -420,7 +422,9 @@ public LevenshteinDetailedDistance(final Integer threshold) { * *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large - * strings.
    + * strings. + *

    + *

    * This implementation of the Levenshtein distance algorithm is from * http://www.merriampark.com/ldjava.htm *

    @@ -463,7 +467,9 @@ public LevenshteinResults apply(final CharSequence left, final CharSequence righ * *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large - * strings.
    + * strings. + *

    + *

    * This implementation of the Levenshtein distance algorithm is from * http://www.merriampark.com/ldjava.htm *

    diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java index 8ab60eeec8..d8b9e121ae 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java @@ -326,7 +326,9 @@ public LevenshteinDistance(final Integer threshold) { * *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large - * strings.
    + * strings. + *

    + *

    * This implementation of the Levenshtein distance algorithm is from * http://www.merriampark.com/ldjava.htm *

    From ae57a01a6828fcb7c803fadd4c7ad7747603b7e4 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Feb 2026 12:35:37 +0000 Subject: [PATCH 253/265] Bump github/codeql-action from 4.32.0 to 4.32.2 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 658b44aef9..3fb81ad790 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 4ca0930497..7503f5e6b7 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/upload-sarif@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 with: sarif_file: results.sarif From 272be85f7b3919c639c589cb390456e0f0bcf250 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Feb 2026 09:42:24 -0500 Subject: [PATCH 254/265] Use max-parallel: 20 as asked by Apache Infra --- .github/workflows/codeql-analysis.yml | 1 + .github/workflows/maven.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3fb81ad790..858b59d146 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -37,6 +37,7 @@ jobs: security-events: write strategy: + max-parallel: 20 fail-fast: false matrix: language: [ 'java' ] diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 5a77f4db9d..ca5362ba4e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -26,6 +26,7 @@ jobs: runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental }} strategy: + max-parallel: 20 matrix: java: [ 8, 11, 17, 21, 25 ] experimental: [false] From 8a89e0dd6cdae74a92a1622bfbcd52097a738be7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 9 Feb 2026 13:12:21 +0000 Subject: [PATCH 255/265] Bump actions/cache from 5.0.2 to 5.0.3 --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 858b59d146..9ccfb03278 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,7 +49,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 #v5.0.3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From 267ec52890ae636cb758f3a032751ac6bdc8084a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 20 Feb 2026 07:42:44 -0500 Subject: [PATCH 256/265] Bump github/codeql-action from 4.32.2 to 4.32.3 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9ccfb03278..b1f4f562df 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/autobuild@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 7503f5e6b7..5bed385874 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 with: sarif_file: results.sarif From 21a016cec7ff2ea8a54a3af06d844ed152c6e5f2 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 23 Feb 2026 10:59:18 -0500 Subject: [PATCH 257/265] Bump github/codeql-action from 4.32.0 to 4.32.4 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b1f4f562df..6c4aa3f571 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/autobuild@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 5bed385874..edcfc60f64 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: sarif_file: results.sarif From 3b3d5d140c254096e0c57b315e02ef29c83793de Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 28 Feb 2026 07:54:37 -0500 Subject: [PATCH 258/265] Bump org.apache.commons:commons-parent from 96 to 97. --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f2049d7fde..9f9b598f9a 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 96 + 97 commons-text 1.15.1-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4bfbe4f854..55725d0208 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,7 +49,7 @@ The type attribute can be add,update,fix,remove. TextStringBuilder.append(char[], int, int) uses wrong variable in exception message #735. - Bump org.apache.commons:commons-parent from 93 to 96. + Bump org.apache.commons:commons-parent from 93 to 97. Bump the level of test coverage checks. Bump commons.bytebuddy.version from 1.18.2 to 1.18.4 #734. From 9a82768be95a3d39a547db1f77964e438b1d31b5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 2 Mar 2026 08:34:41 -0500 Subject: [PATCH 259/265] Bump github/codeql-action from 4.32.4 to 4.32.5 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6c4aa3f571..e2ee451b4e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/autobuild@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index edcfc60f64..326bbf4a43 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: sarif_file: results.sarif From f2929c201314e005a625fadfd887d595a092c9a9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Mar 2026 07:36:39 -0500 Subject: [PATCH 260/265] Bump github/codeql-action from 4.32.5 to 4.32.6 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e2ee451b4e..4c52d9d27d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/autobuild@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 326bbf4a43..81fbc1b5e8 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: sarif_file: results.sarif From 5cad5482def411bf07814ddc6e58949149e69e5f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 9 Mar 2026 08:44:19 -0400 Subject: [PATCH 261/265] Bump actions/upload-artifact from 6.0.0 to 7.0.0 --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 81fbc1b5e8..a35bf86eeb 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -57,7 +57,7 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: SARIF file path: results.sarif From a55f00858246e19a4dfd3fb0ddba0700b04dc978 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 11 Mar 2026 21:52:45 -0400 Subject: [PATCH 262/265] Remove link to now malicious site --- .../LevenshteinDetailedDistance.java | 29 +------------------ .../text/similarity/LevenshteinDistance.java | 17 +---------- 2 files changed, 2 insertions(+), 44 deletions(-) diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java index 4b4740ea9a..8ea040098d 100644 --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java @@ -132,7 +132,7 @@ public static LevenshteinDetailedDistance getDefaultInstance() { * *

    * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance - * algorithm from http://www.merriampark.com/ld.htm + * algorithm. *

    * *
    @@ -271,18 +271,9 @@ private static  LevenshteinResults limitedCompare(SimilarityInput left, Si
          * 

    * *

    - * The previous implementation of the Levenshtein distance algorithm was from - * http://www.merriampark.com/ld.htm - *

    - * - *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large * strings. *

    - *

    - * This implementation of the Levenshtein distance algorithm is from - * http://www.merriampark.com/ldjava.htm - *

    * *
          * unlimitedCompare(null, *)             = Throws {@link IllegalArgumentException}
    @@ -416,18 +407,9 @@ public LevenshteinDetailedDistance(final Integer threshold) {
          * 

    * *

    - * The previous implementation of the Levenshtein distance algorithm was from - * http://www.merriampark.com/ld.htm - *

    - * - *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large * strings. *

    - *

    - * This implementation of the Levenshtein distance algorithm is from - * http://www.merriampark.com/ldjava.htm - *

    * *
          * distance.apply(null, *)             = Throws {@link IllegalArgumentException}
    @@ -461,18 +443,9 @@ public LevenshteinResults apply(final CharSequence left, final CharSequence righ
          * 

    * *

    - * The previous implementation of the Levenshtein distance algorithm was from - * http://www.merriampark.com/ld.htm - *

    - * - *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large * strings. *

    - *

    - * This implementation of the Levenshtein distance algorithm is from - * http://www.merriampark.com/ldjava.htm - *

    * *
          * distance.apply(null, *)             = Throws {@link IllegalArgumentException}
    diff --git a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
    index d8b9e121ae..479b3fadea 100644
    --- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
    +++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
    @@ -55,7 +55,7 @@ public static LevenshteinDistance getDefaultInstance() {
          *
          * 

    * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance - * algorithm from http://www.merriampark.com/ld.htm + * algorithm. *

    * *
    @@ -204,12 +204,6 @@ private static  int limitedCompare(SimilarityInput left, SimilarityInput

    * *

    - * The previous implementation of the Levenshtein distance algorithm was from - * - * https://web.archive.org/web/20120526085419/http://www.merriampark.com/ldjava.htm - *

    - * - *

    * This implementation only need one single-dimensional arrays of length s.length() + 1 *

    * @@ -320,18 +314,9 @@ public LevenshteinDistance(final Integer threshold) { *

    * *

    - * The previous implementation of the Levenshtein distance algorithm was from - * http://www.merriampark.com/ld.htm - *

    - * - *

    * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError which can occur when my Java implementation is used with very large * strings. *

    - *

    - * This implementation of the Levenshtein distance algorithm is from - * http://www.merriampark.com/ldjava.htm - *

    * *
          * distance.apply(null, *)             = Throws {@link IllegalArgumentException}
    
    From 7b76a31ba0ff432df88b7c2b1f9a52401d45120c Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Fri, 13 Mar 2026 09:08:53 -0400
    Subject: [PATCH 263/265] Bump commons.bytebuddy.version from 1.18.4 to 1.18.7.
    
    ---
     pom.xml                 | 2 +-
     src/changes/changes.xml | 1 +
     2 files changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/pom.xml b/pom.xml
    index 9f9b598f9a..bc8e9a9200 100644
    --- a/pom.xml
    +++ b/pom.xml
    @@ -48,7 +48,7 @@
         https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-text
         site-content
         3.20.0
    -    1.18.4
    +    1.18.7
         1.6
         false
         1.37
    diff --git a/src/changes/changes.xml b/src/changes/changes.xml
    index 55725d0208..a3ae6cc2bc 100644
    --- a/src/changes/changes.xml
    +++ b/src/changes/changes.xml
    @@ -52,6 +52,7 @@ The  type attribute can be add,update,fix,remove.
           Bump org.apache.commons:commons-parent from 93 to 97.
           Bump the level of test coverage checks.
           Bump commons.bytebuddy.version from 1.18.2 to 1.18.4 #734.
    +      Bump commons.bytebuddy.version from 1.18.4 to 1.18.7.
         
         
           
    
    From 6e2b964ae83f0bf020b6236cb97fb85795ddfc4b Mon Sep 17 00:00:00 2001
    From: Gary Gregory 
    Date: Thu, 19 Mar 2026 23:46:54 +0000
    Subject: [PATCH 264/265] Add a reference to safe deserlialization
    
    ---
     src/site/xdoc/security.xml | 7 ++++++-
     1 file changed, 6 insertions(+), 1 deletion(-)
    
    diff --git a/src/site/xdoc/security.xml b/src/site/xdoc/security.xml
    index b211fd77bd..150584ad35 100644
    --- a/src/site/xdoc/security.xml
    +++ b/src/site/xdoc/security.xml
    @@ -114,5 +114,10 @@
                     

    - +
    +

    + For information about safe deserialization, please see Safe Deserialization. +

    +
    + From 040a75798ce48ce000ecc9af4e7e3a49690aff48 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 20 Mar 2026 17:33:07 -0700 Subject: [PATCH 265/265] Bump github/codeql-action from 4.32.6 to 4.34.0 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4c52d9d27d..e072e3dd79 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/init@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/autobuild@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/analyze@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index a35bf86eeb..7182c34001 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/upload-sarif@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 with: sarif_file: results.sarif