diff --git a/.asf.yaml b/.asf.yaml
index 4cc5f8aa67..b7e94937c1 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -5,7 +5,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,
@@ -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
diff --git a/.github/GH-ROBOTS.txt b/.github/GH-ROBOTS.txt
index e3329e55fb..64a88674fe 100644
--- a/.github/GH-ROBOTS.txt
+++ b/.github/GH-ROBOTS.txt
@@ -5,7 +5,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/.github/dependabot.yml b/.github/dependabot.yml
index 9ebcd0ebb1..90ec55f742 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -5,7 +5,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,
@@ -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"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index d126a970ce..9ff35c83e7 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -7,7 +7,7 @@
"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
@@ -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. 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 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.
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 8870d60ca5..e072e3dd79 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -5,7 +5,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,
@@ -37,6 +37,7 @@ jobs:
security-events: write
strategy:
+ max-parallel: 20
fail-fast: false
matrix:
language: [ 'java' ]
@@ -45,10 +46,10 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 #v5.0.3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
@@ -57,7 +58,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # 3.28.13
+ 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.
@@ -68,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@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # 3.28.13
+ uses: github/codeql-action/autobuild@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -82,4 +83,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # 3.28.13
+ uses: github/codeql-action/analyze@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index c6ece650e2..a04da50909 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -6,7 +6,7 @@
# "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
@@ -26,6 +26,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: 'Dependency Review PR'
- uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0
+ uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index b93e5ecfad..ca5362ba4e 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -5,7 +5,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,
@@ -26,19 +26,20 @@ jobs:
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.experimental }}
strategy:
+ max-parallel: 20
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:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up JDK ${{ matrix.java }}
- uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
index 81334c6824..7182c34001 100644
--- a/.github/workflows/scorecards-analysis.yml
+++ b/.github/workflows/scorecards-analysis.yml
@@ -5,7 +5,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,
@@ -40,12 +40,12 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: "Run analysis"
- uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # 2.4.1
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # 2.4.3
with:
results_file: results.sarif
results_format: sarif
@@ -57,13 +57,13 @@ jobs:
publish_results: true
- name: "Upload artifact"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # 3.28.13
+ uses: github/codeql-action/upload-sarif@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0
with:
sarif_file: results.sarif
diff --git a/.gitignore b/.gitignore
index 92a1b2a4a3..c5860d17e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,8 @@ site-content
.project
.externalToolBuilders
/.checkstyle
+/.DS_Store
+
+# NetBeans files
+nb-configuration.xml
+nbactions.xml
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 3ed501501d..b4342f33ca 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.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/CONTRIBUTING.md b/CONTRIBUTING.md
index 32f45c3390..9d1083cc5e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.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,
@@ -61,15 +61,15 @@ Making Changes
+ Create a _topic branch_ for your isolated work.
* Usually you should base your branch from the `master` branch.
- * A good topic branch name can be the JIRA bug ID plus a keyword, for example, `TEXT-123-InputStream`.
+ * A good topic branch name can be the JIRA bug ID plus a keyword, e.g. `TEXT-123-InputStream`.
* If you have submitted multiple JIRA issues, try to maintain separate branches and pull requests.
+ Make commits of logical units.
* Make sure your commit messages are meaningful and in the proper format. Your commit message should contain the key of the JIRA issue.
- * For example, `[TEXT-123] Close input stream earlier`
+ * For example, `[TEXT-123] Close input stream sooner`
+ 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.
diff --git a/LICENSE.txt b/LICENSE.txt
index d645695673..ff9ad4530f 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -193,7 +193,7 @@
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/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/).
diff --git a/README.md b/README.md
index 3110a06778..3cd07a15d7 100644
--- a/README.md
+++ b/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,
@@ -45,12 +45,12 @@ Apache Commons Text
[](https://github.com/apache/commons-text/actions/workflows/maven.yml)
[](https://search.maven.org/artifact/org.apache.commons/commons-text)
-[](https://javadoc.io/doc/org.apache.commons/commons-text/1.13.0)
+[](https://javadoc.io/doc/org.apache.commons/commons-text/1.15.0)
[](https://github.com/apache/commons-text/actions/workflows/codeql-analysis.yml)
[](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:
Duplicate letters in either original or encoding will be ignored.
+ * Duplicate letters in either original or encoding will be ignored.
+ *
+ * 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):
* {@code {}argument-number({@code ,}format-name
* ({@code ,}format-style)?)?{@code }}
+ *
* format-name and format-style values are trimmed of surrounding whitespace
@@ -75,15 +80,10 @@ public class ExtendedMessageFormat extends MessageFormat {
*/
private static final long serialVersionUID = -2362048321261811743L;
- /**
- * Our initial seed value for calculating hashes.
- */
- private static final int HASH_SEED = 31;
-
/**
* The empty string.
*/
- private static final String DUMMY_PATTERN = StringUtils.EMPTY;
+ private static final String EMPTY_PATTERN = StringUtils.EMPTY;
/**
* A comma.
@@ -91,12 +91,12 @@ public class ExtendedMessageFormat extends MessageFormat {
private static final char START_FMT = ',';
/**
- * A right side squiggly brace.
+ * A right curly bracket.
*/
private static final char END_FE = '}';
/**
- * A left side squiggly brace.
+ * A left curly bracket.
*/
private static final char START_FE = '{';
@@ -118,7 +118,7 @@ public class ExtendedMessageFormat extends MessageFormat {
/**
* Constructs a new ExtendedMessageFormat for the default locale.
*
- * @param pattern the pattern to use, not null
+ * @param pattern the pattern to use, not null.
* @throws IllegalArgumentException in case of a bad pattern.
*/
public ExtendedMessageFormat(final String pattern) {
@@ -128,8 +128,8 @@ public ExtendedMessageFormat(final String pattern) {
/**
* Constructs a new ExtendedMessageFormat.
*
- * @param pattern the pattern to use, not null
- * @param locale the locale to use, not null
+ * @param pattern the pattern to use, not null.
+ * @param locale the locale to use, not null.
* @throws IllegalArgumentException in case of a bad pattern.
*/
public ExtendedMessageFormat(final String pattern, final Locale locale) {
@@ -139,53 +139,43 @@ 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 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.
* @throws IllegalArgumentException in case of a bad pattern.
*/
- public ExtendedMessageFormat(final String pattern,
- final Locale locale,
- final Map The {@link Formattable} interface provides basic control over formatting
- * when using a {@code Formatter}. It is primarily concerned with numeric precision
- * and padding, and is not designed to allow generalized alternate formats.
+ * The {@link Formattable} interface provides basic control over formatting when using a {@code Formatter}. It is primarily concerned with numeric precision and
+ * padding, and is not designed to allow generalized alternate formats.
+ * 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.
+ *
- * {@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.
* 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.
- * 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.
*
- * 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.
*
+ * {@link TextRandomProvider} is a functional interface and need not be explicitly implemented:
+ *
+ * Passing {@code null} to this method will revert to the default source of randomness.
+ *
- * When using Java 8 or later, {@link TextRandomProvider} is a
- * functional interface and need not be explicitly implemented:
+ * {@link TextRandomProvider} is a functional interface and need not be explicitly implemented:
*
- * 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.
*
- * 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.
*
+ * embedded in the message pattern is specified (()? signifies optionality):
+ *
* // 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);
*
*
@@ -45,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 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.
+ *
+ *
+ * {@code
+ * UniformRandomProvider rng = RandomSource.create(...);
+ * RandomStringGenerator gen = RandomStringGenerator.builder()
+ * .usingRandom(rng::nextInt)
+ * // additional builder calls as needed
+ * .build();
+ * }
+ *
+ *
+ *
* {@code
* UniformRandomProvider rng = RandomSource.create(...);
@@ -230,13 +289,11 @@ public Builder selectFrom(final char... chars) {
*
*
*
* {@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' } };
* }
*
*
* @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");
@@ -268,39 +325,30 @@ 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);
+ characterSet.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} instance.
+ * @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;
@@ -309,6 +357,7 @@ public Builder withinRange(final int minimumCodePoint, final int maximumCodePoin
/**
* Constructs a new builder.
+ *
* @return a new builder.
* @since 1.11.0
*/
@@ -334,7 +383,7 @@ public static Builder builder() {
/**
* The source of randomness for this generator.
*/
- private final TextRandomProvider random;
+ private final IntUnaryOperator random;
/**
* The source of provided characters.
@@ -344,48 +393,35 @@ 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 characterSet list of predefined set of characters.
*/
- private RandomStringGenerator(final int minimumCodePoint, final int maximumCodePoint,
- final Set
- * 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; @@ -437,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; @@ -451,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; @@ -460,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; @@ -483,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() {
@@ -498,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) {
@@ -532,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) { @@ -555,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) { @@ -570,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) { @@ -593,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) { @@ -610,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) { @@ -627,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) { @@ -650,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) { @@ -668,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) { @@ -692,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) { @@ -709,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) { @@ -732,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) { @@ -746,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) { @@ -766,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) { @@ -781,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) { @@ -807,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) { @@ -822,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) { @@ -850,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, @@ -874,13 +843,13 @@ protected String resolveVariable(final String variableName, if (resolver == null) { return null; } - return resolver.lookup(variableName); + return resolver.apply(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) { @@ -888,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 */ @@ -929,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)); @@ -944,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()) { @@ -967,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; @@ -987,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)); @@ -1002,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!"); @@ -1018,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!"); @@ -1036,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; @@ -1045,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)); @@ -1060,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!"); @@ -1076,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!"); @@ -1094,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* 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(); @@ -149,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}. * @@ -172,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() { @@ -185,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) { @@ -198,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) { @@ -238,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)}. *
@@ -252,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) { @@ -265,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); @@ -277,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); @@ -289,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); @@ -300,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); @@ -312,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); @@ -325,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) { @@ -338,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); @@ -350,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); @@ -362,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); @@ -373,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); @@ -385,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); @@ -396,8 +389,9 @@ 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) { @@ -407,8 +401,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- * 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; @@ -509,12 +499,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; @@ -523,7 +511,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(); @@ -533,7 +521,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- * 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; @@ -560,7 +546,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() { @@ -571,7 +557,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() { @@ -583,7 +569,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; @@ -593,7 +579,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; @@ -603,12 +589,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, @@ -626,8 +612,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() { @@ -640,7 +626,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() { @@ -648,11 +634,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()) { @@ -664,7 +649,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() { @@ -677,7 +662,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() { @@ -687,7 +672,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()) { @@ -699,13 +684,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, @@ -750,16 +734,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* 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; @@ -866,12 +849,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(); @@ -884,12 +865,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(); @@ -903,8 +882,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) { @@ -914,8 +894,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)); @@ -927,8 +907,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) { @@ -942,19 +922,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; @@ -964,12 +943,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)); @@ -978,12 +956,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) { @@ -993,11 +970,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; @@ -1007,12 +983,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)); @@ -1021,12 +996,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) { @@ -1038,12 +1012,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) { @@ -1055,7 +1028,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(); @@ -1065,25 +1038,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 ListIf 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 +514,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. + *
* - * 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,14 +557,13 @@ 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); } - // HTML and XML /** * Escapes the characters in a {@code String} using HTML entities. * @@ -573,38 +580,44 @@ public static String escapeHtml3(final String input) { * Note that the commonly used apostrophe escape character (') * 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 - * @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); } - // Java and JavaScript /** * 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 f092bd2572..3667e91529 100644 --- a/src/main/java/org/apache/commons/text/StringSubstitutor.java +++ b/src/main/java/org/apache/commons/text/StringSubstitutor.java @@ -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, @@ -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))); } /** @@ -506,8 +505,8 @@ public StringSubstitutor() { * Constructs a new initialized instance. Uses defaults for variable prefix and suffix and the escaping * character. * - * @param* 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; @@ -752,7 +750,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; @@ -761,7 +759,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; @@ -770,7 +768,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; @@ -779,7 +777,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; @@ -789,9 +787,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) { @@ -803,22 +801,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) { @@ -833,9 +829,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) { @@ -852,11 +848,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) { @@ -871,9 +867,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) { @@ -888,9 +884,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) { @@ -904,22 +900,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) { @@ -936,9 +929,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) { @@ -957,11 +950,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) { @@ -976,9 +969,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) { @@ -997,11 +990,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) { @@ -1016,7 +1009,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) { @@ -1034,11 +1027,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) { @@ -1056,8 +1049,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) { @@ -1074,11 +1067,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) { @@ -1096,9 +1089,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) { @@ -1115,11 +1108,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) { @@ -1140,11 +1133,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) { @@ -1152,14 +1145,14 @@ protected String resolveVariable(final String variableName, final TextStringBuil if (resolver == null) { return null; } - return resolver.lookup(variableName); + return resolver.apply(variableName); } /** * 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; @@ -1171,8 +1164,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; @@ -1182,8 +1175,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; @@ -1194,8 +1187,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; @@ -1208,8 +1201,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; @@ -1223,8 +1216,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)); @@ -1241,8 +1234,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()) { @@ -1263,8 +1256,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; @@ -1278,8 +1271,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)); @@ -1292,9 +1285,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!"); @@ -1308,9 +1301,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!"); @@ -1321,8 +1314,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; @@ -1336,8 +1329,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)); @@ -1350,9 +1343,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!"); @@ -1366,9 +1359,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!"); @@ -1387,10 +1380,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; @@ -1400,12 +1393,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 andisEnableUndefinedVariableException()==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 bb7bd7479c..83b1c12fbb 100644
--- a/src/main/java/org/apache/commons/text/StringTokenizer.java
+++ b/src/main/java/org/apache/commons/text/StringTokenizer.java
@@ -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,
@@ -94,28 +94,26 @@
public class StringTokenizer implements ListIterator* This constructor is normally used with {@link #reset(String)}. *
@@ -253,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; @@ -263,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); @@ -274,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); @@ -292,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); @@ -305,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); @@ -316,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); @@ -334,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; @@ -344,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); @@ -355,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); @@ -373,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); @@ -386,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); @@ -397,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); @@ -415,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) { @@ -428,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- * 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; @@ -531,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; @@ -544,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(); @@ -554,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- * 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; @@ -577,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() { @@ -588,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() { @@ -599,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; @@ -608,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; @@ -617,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; @@ -642,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() { @@ -657,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() { @@ -665,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()) { @@ -680,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() { @@ -693,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() { @@ -703,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()) { @@ -715,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* 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) { @@ -1071,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(); @@ -1081,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- * When using Java 8 or later, TextRandomProvider is a functional interface and - * need not be explicitly implemented. For example: + * {@code TextRandomProvider} is a functional interface and need not be explicitly implemented. + *
+ *+ * For example: *
*
* {@code
@@ -35,15 +39,30 @@
* .build();
* }
*
+ *
* @since 1.1
*/
-public interface TextRandomProvider {
+public interface TextRandomProvider extends IntUnaryOperator {
+
+ /**
+ * Generates an int value between 0 (inclusive) and the specified value (exclusive).
+ *
+ * @param max Bound on the random number to be returned. Must be positive.
+ * @return a random int value between 0 (inclusive) and max (exclusive).
+ * @since 1.14.0
+ */
+ @Override
+ default int applyAsInt(final int max) {
+ return nextInt(max);
+ }
/**
- * Generates an int value between 0 (inclusive) and the specified value
- * (exclusive).
- * @param max Bound on the random number to be returned. Must be positive.
- * @return a random int value between 0 (inclusive) and n (exclusive).
+ * Generates an int value between 0 (inclusive) and the specified value (exclusive).
+ *
+ * @param max Bound on the random number to be returned. Must be positive.
+ * @return a random int value between 0 (inclusive) and max (exclusive).
+ * @deprecated Use {@link #applyAsInt(int)}.
*/
+ @Deprecated
int nextInt(int max);
}
diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java
index 15d60c844a..2977fa3232 100644
--- a/src/main/java/org/apache/commons/text/TextStringBuilder.java
+++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java
@@ -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,
@@ -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} */
@@ -375,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) {
@@ -391,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) {
@@ -404,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];
@@ -413,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);
@@ -425,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) {
@@ -442,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) {
@@ -456,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) {
@@ -476,21 +470,20 @@ 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) {
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);
@@ -507,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));
@@ -517,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) {
@@ -547,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) {
@@ -573,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) {
@@ -595,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));
@@ -605,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));
@@ -615,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));
@@ -625,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));
@@ -635,8 +628,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 {@code this} instance.
*/
public TextStringBuilder append(final Object obj) {
if (obj == null) {
@@ -651,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));
@@ -661,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) {
@@ -692,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) {
@@ -704,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));
@@ -714,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) {
@@ -741,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));
@@ -751,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) {
@@ -778,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));
@@ -788,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) {
@@ -813,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) {
@@ -827,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) {
@@ -841,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 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) { - if (isEmpty()) { - append(defaultIfEmpty); - } else { - append(standard); - } - return this; + return append(isEmpty() ? defaultIfEmpty : standard); } /** @@ -1275,15 +1251,12 @@ 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) { - if (loopIndex > 0) { - append(separator); - } - return this; + return loopIndex > 0 ? append(separator) : this; } /** @@ -1304,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); @@ -1329,15 +1302,12 @@ 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) { - if (separator != null && loopIndex > 0) { - append(separator); - } - return this; + return separator != null && loopIndex > 0 ? append(separator) : this; } /** @@ -1363,16 +1333,13 @@ 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; - if (str != null) { - append(str); - } - return this; + return str != null ? append(str) : this; } /** @@ -1381,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) */ @@ -1412,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) { @@ -1427,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) { @@ -1448,17 +1415,16 @@ 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) { 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; @@ -1481,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(); @@ -1520,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(); @@ -1544,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(); @@ -1553,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()}. */ @@ -1566,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; @@ -1575,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) { @@ -1598,7 +1564,7 @@ public char charAt(final int index) { * Collections. * * - * @return this, to enable chaining + * @return {@code this} instance. */ public TextStringBuilder clear() { size = 0; @@ -1608,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; @@ -1624,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; @@ -1638,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; @@ -1648,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); @@ -1665,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++) { @@ -1688,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(); @@ -1710,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); @@ -1720,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); @@ -1735,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++) { @@ -1751,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(); @@ -1772,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); @@ -1782,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); @@ -1795,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); @@ -1837,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) { @@ -1869,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) { @@ -1889,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. @@ -1904,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) { @@ -1915,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) { @@ -1944,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) { @@ -1969,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 */ @@ -1988,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(); @@ -2035,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; @@ -2044,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() { @@ -2060,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); @@ -2070,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); @@ -2094,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); @@ -2108,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); @@ -2128,14 +2094,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; } @@ -2147,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); @@ -2161,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); @@ -2183,13 +2150,13 @@ 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) { - validateIndex(index); + validateRange(index, size); if (value) { ensureCapacityInternal(size + TRUE_STRING_SIZE); System.arraycopy(buffer, index, buffer, index + TRUE_STRING_SIZE, size - index); @@ -2205,13 +2172,13 @@ 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) { - validateIndex(index); + validateRange(index, size); ensureCapacityInternal(size + 1); System.arraycopy(buffer, index, buffer, index + 1, size - index); buffer[index] = value; @@ -2222,13 +2189,13 @@ 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) { - validateIndex(index); + validateRange(index, size); if (chars == null) { return insert(index, nullText); } @@ -2245,15 +2212,15 @@ 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) { - validateIndex(index); + validateRange(index, size); if (chars == null) { return insert(index, nullText); } @@ -2275,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)); @@ -2287,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)); @@ -2299,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)); @@ -2311,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)); @@ -2324,28 +2291,25 @@ 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 {@code this} instance. + * @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)); } /** * 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) { - validateIndex(index); + validateRange(index, size); if (str == null) { str = nullText; } @@ -2400,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); @@ -2410,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; @@ -2433,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); @@ -2447,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; @@ -2457,22 +2421,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; } @@ -2484,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); @@ -2498,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; @@ -2524,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) { @@ -2556,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) { @@ -2576,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) { @@ -2607,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) */ @@ -2658,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 @@ -2691,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); @@ -2699,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); @@ -2718,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) { @@ -2739,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) { @@ -2757,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(); @@ -2781,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); @@ -2792,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) { @@ -2811,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(); @@ -2834,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); @@ -2845,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) { @@ -2872,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) { @@ -2904,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. @@ -2923,13 +2885,12 @@ 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) { return this; } - final int half = size / 2; final char[] buf = buffer; for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++, rightIdx--) { @@ -2947,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) { @@ -2963,27 +2924,25 @@ 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) { - clear(); - append(str); - return this; + return clear().append(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); @@ -2994,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) { @@ -3017,7 +2976,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; @@ -3027,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()) { @@ -3044,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; @@ -3056,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) { @@ -3098,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); @@ -3113,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); @@ -3126,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); @@ -3135,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); @@ -3153,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() { @@ -3163,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); @@ -3172,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); @@ -3181,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) { @@ -3206,10 +3164,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) { @@ -3220,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 a52de8933b..720ca5f98c 100644 --- a/src/main/java/org/apache/commons/text/WordUtils.java +++ b/src/main/java/org/apache/commons/text/WordUtils.java @@ -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, @@ -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; /** @@ -73,8 +74,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) { @@ -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 @@ -129,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) */ @@ -161,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) */ @@ -213,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); @@ -241,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)) { @@ -270,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)) { @@ -295,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
* Users should implement this interface in order to walk through
* the {@link EditScript EditScript} object created by the comparison
@@ -126,21 +125,21 @@ public interface CommandVisitor
* When two objects sequences are compared through the
@@ -58,8 +58,7 @@ public abstract class EditCommand
- * 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
*
* An edit script is the most general view of the differences between two
@@ -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
* 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
@@ -72,19 +72,19 @@ public class ReplacementsFinder
- * 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.
*
- * 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.
*
* 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
@@ -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 {
@@ -70,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;
@@ -83,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;
@@ -92,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;
@@ -101,20 +100,23 @@ 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;
}
}
+
/**
* First character sequence.
*/
private final String left;
+
/**
* Second character sequence.
*/
private final String right;
+
/**
* Temporary array.
*/
@@ -128,15 +130,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.
*
- * 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.
*
- * 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.
*
+ * Public access is through {@link StringLookupFactory}.
+ * 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/BiStringLookup.java b/src/main/java/org/apache/commons/text/lookup/BiStringLookup.java
index 33cdd4a809..9852fc79ad 100644
--- a/src/main/java/org/apache/commons/text/lookup/BiStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/BiStringLookup.java
@@ -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,
@@ -68,7 +68,7 @@ public interface BiStringLookup extends StringLookup {
* @return The matching value, null if no match.
*/
default String lookup(final String key, final U object) {
- return lookup(key);
+ return apply(key);
}
}
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 c8ebe0182c..ddd95e0343 100644
--- a/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java
@@ -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,
@@ -58,7 +58,11 @@
*
* This class was adapted from Apache Commons Configuration.
*
+ * Public access is through {@link StringLookupFactory}.
+ *
* The above examples convert {@code "yyyy-MM-dd"} to today's date, for example, {@code "2019-08-04"}.
*
+ * Public access is through {@link StringLookupFactory}.
+ *
* 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}.
+ *
* 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}.
+ *
+ * Public access is through {@link StringLookupFactory}.
+ *
+ * Public access is through {@link StringLookupFactory}.
+ *
+ * Public access is through {@link StringLookupFactory}.
+ *
* Uses the {@link StringLookupFactory default lookups}.
*
+ * Public access is through {@link StringLookupFactory}.
+ *
+ * Public access is through {@link StringLookupFactory}.
+ *
* For example: "com/domain/document.properties:key".
*
+ * Public access is through {@link StringLookupFactory}.
+ *
* For example: "com.domain.messages:MyKey".
*
+ * Public access is through {@link StringLookupFactory}.
+ *
+ * Public access is through {@link StringLookupFactory}.
+ *
@@ -31,7 +33,38 @@
* @since 1.3
*/
@FunctionalInterface
-public interface StringLookup {
+public interface StringLookup extends UnaryOperator
+ * The internal implementation may use any mechanism to return the value. The simplest implementation is to use a
+ * Map. However, virtually any implementation is possible.
+ *
+ * For example, it would be possible to implement a lookup that used the key as a primary key, and looked up the
+ * value on demand from the database Or, a numeric based implementation could be created that treats the key as an
+ * integer, increments the value and return the result as a string - converting 1 to 2, 15 to 16 etc.
+ *
+ * This method always returns a String, regardless of the underlying data, by converting it as necessary. For
+ * example:
+ *
+ * The format of the property string is a comma-separated list of names from the {@link DefaultStringLookup} enum.
+ *
- * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
+ * The examples above convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
*
- * The above examples convert {@code "HelloWorld!"} to {@code "SGVsbG9Xb3JsZCE="}.
+ * The examples above convert {@code "HelloWorld!"} to {@code "SGVsbG9Xb3JsZCE="}.
*
- * 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.
*
+ * The format of the property string is a comma-separated list of names from the {@link DefaultStringLookup} enum.
+ *
- * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
+ * The examples above convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
*
- * The above examples convert {@code } to {@code "SGVsbG9Xb3JsZCE="}.
+ * The examples above convert {@code } to {@code "SGVsbG9Xb3JsZCE="}.
*
- * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
+ * The examples above convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
*
- * 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"}.
*
- * 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"}.
*
- * 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}.
*
- * 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.
*
- * 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.
*
- * 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.
*
- * 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"}.
*
- * 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"}.
*
- * 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"}.
*
- * 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"}.
*
@@ -1251,8 +1258,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"}.
*
- * 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"}.
*
- * The above examples convert {@code "javascript:3 + 4"} to {@code "7"}.
+ * The examples above convert {@code "javascript:3 + 4"} to {@code "7"}.
*
- * The above examples convert {@code "os.name"} to the operating system name.
+ * The examples above convert {@code "os.name"} to the operating system name.
*
- * The above examples convert {@code "Hello%20World%21"} to {@code "Hello World!"}.
+ * The examples above convert {@code "Hello%20World%21"} to {@code "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"}.
*
- * 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.
*
- * The above examples convert {@code "<element>"} to {@code "
- * The above examples convert {@code "
* 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);
@@ -101,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) {
@@ -137,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 a31bbc3946..a7dc0b7123 100644
--- a/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/DateStringLookup.java
@@ -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,
@@ -43,6 +43,11 @@
*
* StringSubstitutor.createInterpolator().replace("${script:javascript:3 + 4}"));
*
+ *
+ * Map<String, Object> map = new HashMap<String, Object>();
+ * map.put("number", Integer.valueOf(2));
+ * assertEquals("2", StringLookupFactory.mapStringLookup(map).lookup("number"));
+ *
+ *
+ * @param key the key to look up, may be null.
+ * @return The matching value, null if no match.
+ * @since 1.14.0
+ */
+ @Override
+ default String apply(final String key) {
+ return lookup(key);
+ }
/**
* Looks up a String key to provide a String value.
@@ -57,6 +90,8 @@ public interface StringLookup {
*
* @param key the key to look up, may be null.
* @return The matching value, null if no match.
+ * @deprecated Use {@link #apply(String)}.
*/
+ @Deprecated
String lookup(String key);
}
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 4916e8d833..699b7deab7 100644
--- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
+++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
@@ -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,
@@ -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;
@@ -277,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
- * 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 "DocumentPath:XPath"}. *
*- * For example: "com/domain/document.xml:/path/to/node". + * For example: + *
+ *+ * 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}: @@ -1631,14 +1645,14 @@ 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. * @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; } /** @@ -1648,10 +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 look up the value for the key in the format "DocumentPath:XPath". + * We looks up values in an XML document in the format {@code "]DocumentPath:XPath"}. *
*- * For example: "com/domain/document.xml:/path/to/node". + * For example: + *
+ *+ * 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}: @@ -1668,16 +1689,17 @@ 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. + * @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- * 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 "DocumentPath:XPath"}. + *
+ *+ * For example: *
+ *- * For example: "com/domain/document.xml:/path/to/node". + * 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:
@@ -1705,27 +1733,27 @@ public StringLookup xmlStringLookup(final Map
- * 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
* resolves in a fence.
*
+ * Public access is through {@link StringLookupFactory}.
+ *
+ * Public access is through {@link StringLookupFactory}.
+ *
* 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");
*
*
+ * Public access is through {@link StringLookupFactory}. + *
+ * + * @see StringLookupFactory * @since 1.5 */ final class UrlStringLookup extends AbstractStringLookup { @@ -55,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 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 1dd04115b8..f3c4e93c10 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlDecoderStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlDecoderStringLookup.java @@ -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, @@ -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 e7b65de98e..b70cd20c9e 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlEncoderStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlEncoderStringLookup.java @@ -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, @@ -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 27aada1486..ee33441993 100644 --- a/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java +++ b/src/main/java/org/apache/commons/text/lookup/XmlStringLookup.java @@ -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, @@ -26,38 +26,56 @@ 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 "DocumentPath:XPath"}. *- * Looks up the value for a given key in the format "Document:XPath". + * For example: *
+ *- * For example: "com/domain/document.xml:/path/to/node". + * Secure processing is enabled by default and can be overridden with {@link StringLookupFactory#xmlStringLookup(Map, Path...)}. *
* * @since 1.5 */ final class XmlStringLookup extends AbstractPathFencedLookup { + /** + * The number of key parts. + */ + private static final int KEY_PARTS_LEN = 2; + /** * Defines default XPath factory features. */ - static final Map+ * Secure processing is enabled by default and can be overridden with {@link StringLookupFactory#xmlStringLookup(Map, Path...)}. + *
*/ - 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 +83,37 @@ final class XmlStringLookup extends AbstractPathFencedLookup { private final Map- * For example: "com/domain/document.xml:/path/to/node". + * For example: + *
+ *+ * 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 + * @param key the key to be looked up, may be null. * @return The value associated with the key. */ @Override @@ -91,22 +123,26 @@ 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_LEN) { + throw IllegalArgumentExceptions.format("Bad XML key format '%s'; the expected format is '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 Entry10plainFormatMaxDecimalExponent + 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. - * @return this instance + * @return {@code this} instance * @see #plainFormatMinDecimalExponent(int) */ public Builder plainFormatMaxDecimalExponent(final int plainFormatMaxDecimalExponent) { @@ -658,21 +660,23 @@ 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 than10plainFormatMaxDecimalExponent + 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. - * @return this instance + * @return {@code this} instance * @see #plainFormatMinDecimalExponent(int) */ public Builder plainFormatMinDecimalExponent(final int plainFormatMinDecimalExponent) { 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 943845d7e2..d4541b0280 100644 --- a/src/main/java/org/apache/commons/text/numbers/ParsedDecimal.java +++ b/src/main/java/org/apache/commons/text/numbers/ParsedDecimal.java @@ -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, @@ -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 diff --git a/src/main/java/org/apache/commons/text/numbers/package-info.java b/src/main/java/org/apache/commons/text/numbers/package-info.java index 4c2233d7c8..89c208eb08 100644 --- a/src/main/java/org/apache/commons/text/numbers/package-info.java +++ b/src/main/java/org/apache/commons/text/numbers/package-info.java @@ -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/main/java/org/apache/commons/text/package-info.java b/src/main/java/org/apache/commons/text/package-info.java index 68f1c85d08..79f3626a24 100644 --- a/src/main/java/org/apache/commons/text/package-info.java +++ b/src/main/java/org/apache/commons/text/package-info.java @@ -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/main/java/org/apache/commons/text/similarity/CharSequenceTokenizer.java b/src/main/java/org/apache/commons/text/similarity/CharSequenceTokenizer.java index 3c85c38291..0bad0de966 100644 --- a/src/main/java/org/apache/commons/text/similarity/CharSequenceTokenizer.java +++ b/src/main/java/org/apache/commons/text/similarity/CharSequenceTokenizer.java @@ -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/main/java/org/apache/commons/text/similarity/CosineDistance.java b/src/main/java/org/apache/commons/text/similarity/CosineDistance.java index f31fe1e187..4d98ab4be8 100644 --- a/src/main/java/org/apache/commons/text/similarity/CosineDistance.java +++ b/src/main/java/org/apache/commons/text/similarity/CosineDistance.java @@ -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, @@ -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+ * 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+ * 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
- * 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
@@ -72,61 +69,48 @@ 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) {
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;
}
diff --git a/src/main/java/org/apache/commons/text/similarity/HammingDistance.java b/src/main/java/org/apache/commons/text/similarity/HammingDistance.java
index 6b5c46940c..fd1ad4641e 100644
--- a/src/main/java/org/apache/commons/text/similarity/HammingDistance.java
+++ b/src/main/java/org/apache/commons/text/similarity/HammingDistance.java
@@ -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/main/java/org/apache/commons/text/similarity/IntersectionResult.java b/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java
index ebdade170e..b55adb3921 100644
--- a/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java
+++ b/src/main/java/org/apache/commons/text/similarity/IntersectionResult.java
@@ -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,
@@ -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 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
+ * @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.
*/
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/IntersectionSimilarity.java b/src/main/java/org/apache/commons/text/similarity/IntersectionSimilarity.java
index 40e9f23f46..370b00a296 100644
--- a/src/main/java/org/apache/commons/text/similarity/IntersectionSimilarity.java
+++ b/src/main/java/org/apache/commons/text/similarity/IntersectionSimilarity.java
@@ -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,
@@ -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
- * 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
@@ -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) {
@@ -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 2ecbcc2b6d..5e67595875 100644
--- a/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java
+++ b/src/main/java/org/apache/commons/text/similarity/JaroWinklerSimilarity.java
@@ -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,
@@ -39,7 +39,7 @@
public class JaroWinklerSimilarity implements SimilarityScore {
/**
- * Singleton instance.
+ * The singleton instance.
*/
static final JaroWinklerSimilarity INSTANCE = new JaroWinklerSimilarity();
@@ -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 3ee9a662aa..8ea040098d 100644
--- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java
+++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDetailedDistance.java
@@ -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,
@@ -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
@@ -32,44 +32,34 @@
public class LevenshteinDetailedDistance implements EditDistance {
/**
- * Singleton instance.
+ * The singleton instance.
*/
private static final LevenshteinDetailedDistance INSTANCE = new LevenshteinDetailedDistance();
/**
- * Finds count for each of the three [insert, delete, substitute] operations
- * needed. This is based on the matrix formed based on the two character
- * sequence.
+ * Finds count for each of the three [insert, delete, substitute] operations needed. This is based on the matrix formed based on the two character sequence.
*
- * @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
+ * @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,21 +128,17 @@ 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.
*
*
*
- * 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
@@ -168,73 +149,45 @@ 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, 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 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 +195,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 +205,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 +225,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 +251,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,19 +266,18 @@ private static LevenshteinResults limitedCompare(SimilarityInput left, Si
/**
* Finds the Levenshtein distance between two Strings.
*
- * A higher score indicates a greater distance.
- *
- * The previous implementation of the Levenshtein distance algorithm
- * was from http://www.merriampark.com/ld.htm
+ *
+ * A higher score indicates a greater distance.
+ *
*
- * 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.
+ *
*
*
- * unlimitedCompare(null, *) = IllegalArgumentException
- * unlimitedCompare(*, null) = IllegalArgumentException
+ * unlimitedCompare(null, *) = Throws {@link IllegalArgumentException}
+ * unlimitedCompare(*, null) = Throws {@link IllegalArgumentException}
* unlimitedCompare("","") = 0
* unlimitedCompare("","a") = 1
* unlimitedCompare("aaapppp", "") = 7
@@ -349,37 +289,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 +328,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 +339,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;
@@ -447,10 +371,7 @@ allows us to retain the previous cost counts as required by the algorithm (takin
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()}.
@@ -461,9 +382,13 @@ 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.
+ *
+ *
+ * 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,19 +402,18 @@ public LevenshteinDetailedDistance(final Integer threshold) {
/**
* Computes the Levenshtein distance between two Strings.
*
- * A higher score indicates a greater distance.
- *
- * The previous implementation of the Levenshtein distance algorithm
- * was from http://www.merriampark.com/ld.htm
+ *
+ * A higher score indicates a greater distance.
+ *
*
- * 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.
+ *
*
*
- * 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
@@ -501,10 +425,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,19 +438,18 @@ public LevenshteinResults apply(final CharSequence left, final CharSequence righ
/**
* Computes the Levenshtein distance between two Strings.
*
- * A higher score indicates a greater distance.
- *
- * The previous implementation of the Levenshtein distance algorithm
- * was from http://www.merriampark.com/ld.htm
+ *
+ * A higher score indicates a greater distance.
+ *
*
- * 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.
+ *
*
*
- * 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
@@ -538,11 +461,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 +478,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;
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 34d65d134e..479b3fadea 100644
--- a/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
+++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinDistance.java
@@ -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,
@@ -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,35 +31,37 @@
*
*
* @since 1.0
+ * @see Levenshtein Distance on Wikipedia
+ * @see Levenshtein Distance on NIST
*/
public class LevenshteinDistance implements EditDistance {
/**
- * Singleton instance.
+ * The singleton instance.
*/
private static final LevenshteinDistance INSTANCE = new LevenshteinDistance();
/**
* Gets the default instance.
*
- * @return The default instance
+ * @return The default instance.
*/
public static LevenshteinDistance getDefaultInstance() {
return INSTANCE;
}
/**
- * 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
- * algorithm from http://www.merriampark.com/ld.htm
+ * algorithm.
*
*
*
- * 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
@@ -69,18 +72,15 @@ 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
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
@@ -88,7 +88,8 @@ private static int limitedCompare(SimilarityInput left, SimilarityInput 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
*
*
*
- * unlimitedCompare(null, *) = IllegalArgumentException
- * unlimitedCompare(*, null) = IllegalArgumentException
+ * unlimitedCompare(null, *) = Throws {@link IllegalArgumentException}
+ * unlimitedCompare(*, null) = Throws {@link IllegalArgumentException}
* unlimitedCompare("","") = 0
* unlimitedCompare("","a") = 1
* unlimitedCompare("aaapppp", "") = 7
@@ -226,10 +221,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) {
@@ -288,7 +283,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 +294,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.
*/
@@ -319,20 +314,13 @@ 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
+ * strings.
*
*
*
- * 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
@@ -344,10 +332,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) {
@@ -362,8 +350,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
@@ -392,7 +380,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;
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 a3632d7119..37b547798b 100644
--- a/src/main/java/org/apache/commons/text/similarity/LevenshteinResults.java
+++ b/src/main/java/org/apache/commons/text/similarity/LevenshteinResults.java
@@ -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,
@@ -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;
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 63701f5a48..ac6d8d36f0 100644
--- a/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java
+++ b/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequence.java
@@ -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,
@@ -52,7 +52,7 @@
public class LongestCommonSubsequence implements SimilarityScore {
/**
- * Singleton instance.
+ * The singleton instance.
*/
static final LongestCommonSubsequence INSTANCE = new LongestCommonSubsequence();
@@ -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.
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 4851554849..ed33437ac2 100644
--- a/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequenceDistance.java
+++ b/src/main/java/org/apache/commons/text/similarity/LongestCommonSubsequenceDistance.java
@@ -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,
@@ -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) {
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 6b348ffa59..21ce3afbcb 100644
--- a/src/main/java/org/apache/commons/text/similarity/ObjectSimilarityScore.java
+++ b/src/main/java/org/apache/commons/text/similarity/ObjectSimilarityScore.java
@@ -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,
@@ -30,15 +30,15 @@
* A similarity score is the function {@code d: [X * X] -> [0, INFINITY)} with the following properties:
*
*