[
https://issues.apache.org/jira/browse/GEODE-10547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Jinwoo Hwang updated GEODE-10547:
---------------------------------
Description:
h1. Replace deprecated commons-lang3 methods with Java standard library
equivalents
h2. Summary
Replace deprecated Apache Commons Lang3 utility methods with Java standard
library equivalents to eliminate deprecation warnings and improve code
maintainability.
h2. Issue Type
* *Type:* Technical Debt / Code Improvement
* *Priority:* Medium
* *Component:* Code Quality
* *Related:* GEODE-10543 (commons-lang3 3.18.0 upgrade for CVE-2025-48924)
h2. Description
As part of upgrading to commons-lang3 3.18.0, several utility methods have been
deprecated. These methods have direct equivalents in the Java standard library
that provide the same functionality with better performance and no external
dependencies.
This task replaces all deprecated commons-lang3 method calls with their Java
standard library equivalents across the Apache Geode codebase.
h3. Deprecated Methods Being Replaced
# {{StringUtils.startsWith(String, String)}} → {{String.startsWith(String)}}
# {{StringUtils.containsIgnoreCase(String, String)}} →
{{String.toLowerCase().contains(String.toLowerCase())}}
# {{StringUtils.equals(String, String)}} → {{Objects.equals(Object, Object)}}
# {{StringUtils.removeStart(String, String)}} → {{startsWith() + substring()}}
# {{LineIterator.nextLine()}} → {{LineIterator.next()}}
h2. Benefits
* *Eliminates deprecation warnings* during compilation
* *Reduces external dependencies* by using Java standard library
* *Improves performance* - native Java methods are typically faster
* *Better null safety* - {{Objects.equals()}} handles null properly
* *Future-proof* - Java standard library methods won't be deprecated
* *Cleaner code* - removes unnecessary utility wrapper calls
h2. Implementation Details
h3. Method Replacement Details
h4. 1. StringUtils.startsWith() → String.startsWith()
*Before:*
{code:java}
if (StringUtils.startsWith(url, "https")) {
// ...
}
{code}
*After:*
{code:java}
if (url.startsWith("https")) {
// ...
}
{code}
*Considerations:* String.startsWith() throws NullPointerException if the string
is null. Ensure proper null checks exist.
h4. 2. StringUtils.containsIgnoreCase() → toLowerCase().contains()
*Before:*
{code:java}
if (StringUtils.containsIgnoreCase(query, "keyword")) {
// ...
}
{code}
*After:*
{code:java}
if (query.toLowerCase().contains("keyword".toLowerCase())) {
// ...
}
{code}
*Considerations:* Both strings need toLowerCase() for case-insensitive
comparison. Requires null check on the source string.
h4. 3. StringUtils.equals() → Objects.equals()
*Before:*
{code:java}
if (StringUtils.equals(value1, value2)) {
// ...
}
{code}
*After:*
{code:java}
if (Objects.equals(value1, value2)) {
// ...
}
{code}
*Benefits:* {{Objects.equals()}} is null-safe and works for any object type,
not just strings.
h4. 4. StringUtils.removeStart() → startsWith() + substring()
*Before:*
{code:java}
String result = StringUtils.removeStart(text, "prefix");
{code}
*After:*
{code:java}
String result = text.startsWith("prefix") ? text.substring("prefix".length()) :
text;
{code}
*Considerations:* Requires explicit logic to handle the case when prefix is not
present.
h4. 5. LineIterator.nextLine() → LineIterator.next()
*Before:*
{code:java}
while (iterator.hasNext()) {
String line = iterator.nextLine();
}
{code}
*After:*
{code:java}
while (iterator.hasNext()) {
String line = iterator.next();
}
{code}
*Note:* {{nextLine()}} is deprecated in commons-io 2.18.0. Use {{next()}} which
is the standard Iterator interface method.
h3. Files Affected
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java*
*
** Line ~126: {{StringUtils.startsWith()}} → {{String.startsWith()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java*
*
** {{StringUtils.containsIgnoreCase()}} → {{toLowerCase().contains()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/CreateIndexCommand.java*
*
** {{StringUtils.removeStart()}} → {{startsWith() + substring()}}
*geode-management/src/main/java/org/apache/geode/management/configuration/Index.java*
*
** {{StringUtils.removeStart()}} → {{startsWith() + substring()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/FixedPartitionAttributesInfo.java*
*
** {{StringUtils.equals()}} → {{Objects.equals()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/RegionAttributesInfo.java*
*
** {{StringUtils.equals()}} → {{Objects.equals()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/PartitionAttributesInfo.java*
*
** {{StringUtils.equals()}} → {{Objects.equals()}}
*geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/cli/commands/StartServerCommandAcceptanceTest.java*
*
** {{LineIterator.nextLine()}} → {{LineIterator.next()}}
h3. Required Imports
Add these imports where needed:
{code:java}
import java.util.Objects; // For Objects.equals()
{code}
Remove if no longer used:
{code:java}
import org.apache.commons.lang3.StringUtils;
{code}
h2. Testing Strategy
h3. Verification Steps
*Compilation:* Ensure no deprecation warnings remain
{code:bash}
./gradlew clean build -Werror
{code}
*Unit Tests:* All existing tests should pass
{code:bash}
./gradlew test
{code}
*Functionality:* Verify behavior is identical
*
** String comparisons work correctly
** Case-insensitive searches work
** Null handling is proper
** Edge cases are covered
h3. Risk Assessment
{panel:title=Low
Risk|borderStyle=solid|borderColor=#cccccc|titleBGColor=#dff0d8|bgColor=#dff0d8}
* *Low Risk:* These are straightforward method replacements with equivalent
functionality
* *Well-tested:* All modified code paths have existing unit tests
* *Standard library:* Using well-tested Java standard library methods{panel}
h4. Potential Issues
* *Null handling:* {{String}} methods throw {{NullPointerException}} on null,
while {{StringUtils}} returns false/empty
** *Mitigation:* Code analysis shows all call sites have proper null checks
* *Case sensitivity:* Must ensure {{toLowerCase()}} is applied to both strings
in comparisons
** *Mitigation:* Code review verified correct implementation
h2. Acceptance Criteria
* All deprecated commons-lang3 method calls replaced in production code
* All deprecated commons-io method calls replaced in test code
* No deprecation warnings during compilation
* All unit tests pass without modification
* Build succeeds with {{-Werror}} flag (warnings as errors)
* Code review confirms correct null handling
* No behavioral changes in functionality
h2. Related Changes
* Part of GEODE-10543: commons-lang3 3.18.0 upgrade
* Complements CVE-2025-48924 security fix
* Coordinates with:
** commons-io 2.18.0 upgrade
** slf4j-api 1.7.36 upgrade
** Log4j 2.25.3 upgrade
h2. Code Review Checklist
* All {{StringUtils}} methods replaced with Java equivalents
* Proper null checks exist before calling {{String}} instance methods
* Case-insensitive comparisons use {{toLowerCase()}} on both sides
* {{Objects.equals()}} imported and used correctly
* {{LineIterator.next()}} used instead of {{nextLine()}}
* No unused imports remaining
* Code formatting follows project standards (spotless check passes)
h2. Documentation
h4. Migration Guide for Developers
Future code should use:
* {{String.startsWith()}} instead of {{StringUtils.startsWith()}}
* {{String.toLowerCase().contains()}} instead of
{{StringUtils.containsIgnoreCase()}}
* {{Objects.equals()}} instead of {{StringUtils.equals()}}
* Ternary with {{startsWith() + substring()}} instead of
{{StringUtils.removeStart()}}
* {{Iterator.next()}} instead of {{LineIterator.nextLine()}}
h2. Estimated Effort
* Analysis: 2 - 3 days
* Implementation: 1 - 2 weeks
* Testing: 2 - 3 days
was:
h1. Replace deprecated commons-lang3 methods with Java standard library
equivalents
h2. Summary
Replace deprecated Apache Commons Lang3 utility methods with Java standard
library equivalents to eliminate deprecation warnings and improve code
maintainability.
h2. Issue Type
* *Type:* Technical Debt / Code Improvement
* *Priority:* Medium
* *Component:* Code Quality
* *Related:* GEODE-10543 (commons-lang3 3.18.0 upgrade for CVE-2025-48924)
h2. Description
As part of upgrading to commons-lang3 3.18.0, several utility methods have been
deprecated. These methods have direct equivalents in the Java standard library
that provide the same functionality with better performance and no external
dependencies.
This task replaces all deprecated commons-lang3 method calls with their Java
standard library equivalents across the Apache Geode codebase.
h3. Deprecated Methods Being Replaced
# {{StringUtils.startsWith(String, String)}} → {{String.startsWith(String)}}
# {{StringUtils.containsIgnoreCase(String, String)}} →
{{String.toLowerCase().contains(String.toLowerCase())}}
# {{StringUtils.equals(String, String)}} → {{Objects.equals(Object, Object)}}
# {{StringUtils.removeStart(String, String)}} → {{startsWith() + substring()}}
# {{LineIterator.nextLine()}} → {{LineIterator.next()}}
h2. Benefits
* *Eliminates deprecation warnings* during compilation
* *Reduces external dependencies* by using Java standard library
* *Improves performance* - native Java methods are typically faster
* *Better null safety* - {{Objects.equals()}} handles null properly
* *Future-proof* - Java standard library methods won't be deprecated
* *Cleaner code* - removes unnecessary utility wrapper calls
h2. Implementation Details
h3. Method Replacement Details
h4. 1. StringUtils.startsWith() → String.startsWith()
*Before:*
{code:java}
if (StringUtils.startsWith(url, "https")) {
// ...
}
{code}
*After:*
{code:java}
if (url.startsWith("https")) {
// ...
}
{code}
*Considerations:* String.startsWith() throws NullPointerException if the string
is null. Ensure proper null checks exist.
h4. 2. StringUtils.containsIgnoreCase() → toLowerCase().contains()
*Before:*
{code:java}
if (StringUtils.containsIgnoreCase(query, "keyword")) {
// ...
}
{code}
*After:*
{code:java}
if (query.toLowerCase().contains("keyword".toLowerCase())) {
// ...
}
{code}
*Considerations:* Both strings need toLowerCase() for case-insensitive
comparison. Requires null check on the source string.
h4. 3. StringUtils.equals() → Objects.equals()
*Before:*
{code:java}
if (StringUtils.equals(value1, value2)) {
// ...
}
{code}
*After:*
{code:java}
if (Objects.equals(value1, value2)) {
// ...
}
{code}
*Benefits:* {{Objects.equals()}} is null-safe and works for any object type,
not just strings.
h4. 4. StringUtils.removeStart() → startsWith() + substring()
*Before:*
{code:java}
String result = StringUtils.removeStart(text, "prefix");
{code}
*After:*
{code:java}
String result = text.startsWith("prefix") ? text.substring("prefix".length()) :
text;
{code}
*Considerations:* Requires explicit logic to handle the case when prefix is not
present.
h4. 5. LineIterator.nextLine() → LineIterator.next()
*Before:*
{code:java}
while (iterator.hasNext()) {
String line = iterator.nextLine();
}
{code}
*After:*
{code:java}
while (iterator.hasNext()) {
String line = iterator.next();
}
{code}
*Note:* {{nextLine()}} is deprecated in commons-io 2.18.0. Use {{next()}} which
is the standard Iterator interface method.
h3. Files Affected
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java*
*
** Line ~126: {{StringUtils.startsWith()}} → {{String.startsWith()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java*
*
** {{StringUtils.containsIgnoreCase()}} → {{toLowerCase().contains()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/CreateIndexCommand.java*
*
** {{StringUtils.removeStart()}} → {{startsWith() + substring()}}
*geode-management/src/main/java/org/apache/geode/management/configuration/Index.java*
*
** {{StringUtils.removeStart()}} → {{startsWith() + substring()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/FixedPartitionAttributesInfo.java*
*
** {{StringUtils.equals()}} → {{Objects.equals()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/RegionAttributesInfo.java*
*
** {{StringUtils.equals()}} → {{Objects.equals()}}
*geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/PartitionAttributesInfo.java*
*
** {{StringUtils.equals()}} → {{Objects.equals()}}
*geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/cli/commands/StartServerCommandAcceptanceTest.java*
*
** {{LineIterator.nextLine()}} → {{LineIterator.next()}}
h3. Required Imports
Add these imports where needed:
{code:java}
import java.util.Objects; // For Objects.equals()
{code}
Remove if no longer used:
{code:java}
import org.apache.commons.lang3.StringUtils;
{code}
h2. Testing Strategy
h3. Verification Steps
*Compilation:* Ensure no deprecation warnings remain
{code:bash}
./gradlew clean build -Werror
{code}
*Unit Tests:* All existing tests should pass
{code:bash}
./gradlew test
{code}
*Functionality:* Verify behavior is identical
*
** String comparisons work correctly
** Case-insensitive searches work
** Null handling is proper
** Edge cases are covered
h3. Risk Assessment
{panel:title=Low
Risk|borderStyle=solid|borderColor=#cccccc|titleBGColor=#dff0d8|bgColor=#dff0d8}
* *Low Risk:* These are straightforward method replacements with equivalent
functionality
* *Well-tested:* All modified code paths have existing unit tests
* *Standard library:* Using well-tested Java standard library methods{panel}
h4. Potential Issues
* *Null handling:* {{String}} methods throw {{NullPointerException}} on null,
while {{StringUtils}} returns false/empty
** *Mitigation:* Code analysis shows all call sites have proper null checks
* *Case sensitivity:* Must ensure {{toLowerCase()}} is applied to both strings
in comparisons
** *Mitigation:* Code review verified correct implementation
h2. Acceptance Criteria
* All deprecated commons-lang3 method calls replaced in production code
* All deprecated commons-io method calls replaced in test code
* No deprecation warnings during compilation
* All unit tests pass without modification
* Build succeeds with {{-Werror}} flag (warnings as errors)
* Code review confirms correct null handling
* No behavioral changes in functionality
h2. Build Verification
h4. Commands to Verify
{code:bash}
# Clean build with strict warnings
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
./gradlew clean build -Werror
# Verify no deprecation warnings
./gradlew compileJava 2>&1 | grep -i "deprecation"
# Run full test suite
./gradlew test
{code}
h2. Related Changes
* Part of GEODE-10543: commons-lang3 3.18.0 upgrade
* Complements CVE-2025-48924 security fix
* Coordinates with:
** commons-io 2.18.0 upgrade
** slf4j-api 1.7.36 upgrade
** Log4j 2.25.3 upgrade
h2. Code Review Checklist
* All {{StringUtils}} methods replaced with Java equivalents
* Proper null checks exist before calling {{String}} instance methods
* Case-insensitive comparisons use {{toLowerCase()}} on both sides
* {{Objects.equals()}} imported and used correctly
* {{LineIterator.next()}} used instead of {{nextLine()}}
* No unused imports remaining
* Code formatting follows project standards (spotless check passes)
h2. Documentation
h4. Migration Guide for Developers
Future code should use:
* {{String.startsWith()}} instead of {{StringUtils.startsWith()}}
* {{String.toLowerCase().contains()}} instead of
{{StringUtils.containsIgnoreCase()}}
* {{Objects.equals()}} instead of {{StringUtils.equals()}}
* Ternary with {{startsWith() + substring()}} instead of
{{StringUtils.removeStart()}}
* {{Iterator.next()}} instead of {{LineIterator.nextLine()}}
h2. Estimated Effort
* Analysis: 2 - 3 days
* Implementation: 1 - 2 weeks
* Testing: 2 - 3 days
> Migrate deprecated commons-lang3 methods with Java standard library
> equivalents
> -------------------------------------------------------------------------------
>
> Key: GEODE-10547
> URL: https://issues.apache.org/jira/browse/GEODE-10547
> Project: Geode
> Issue Type: Improvement
> Reporter: Jinwoo Hwang
> Assignee: Jinwoo Hwang
> Priority: Major
> Fix For: 2.1.0
>
>
> h1. Replace deprecated commons-lang3 methods with Java standard library
> equivalents
> h2. Summary
> Replace deprecated Apache Commons Lang3 utility methods with Java standard
> library equivalents to eliminate deprecation warnings and improve code
> maintainability.
> h2. Issue Type
> * *Type:* Technical Debt / Code Improvement
> * *Priority:* Medium
> * *Component:* Code Quality
> * *Related:* GEODE-10543 (commons-lang3 3.18.0 upgrade for CVE-2025-48924)
> h2. Description
> As part of upgrading to commons-lang3 3.18.0, several utility methods have
> been deprecated. These methods have direct equivalents in the Java standard
> library that provide the same functionality with better performance and no
> external dependencies.
> This task replaces all deprecated commons-lang3 method calls with their Java
> standard library equivalents across the Apache Geode codebase.
> h3. Deprecated Methods Being Replaced
> # {{StringUtils.startsWith(String, String)}} → {{String.startsWith(String)}}
> # {{StringUtils.containsIgnoreCase(String, String)}} →
> {{String.toLowerCase().contains(String.toLowerCase())}}
> # {{StringUtils.equals(String, String)}} → {{Objects.equals(Object, Object)}}
> # {{StringUtils.removeStart(String, String)}} → {{startsWith() +
> substring()}}
> # {{LineIterator.nextLine()}} → {{LineIterator.next()}}
> h2. Benefits
> * *Eliminates deprecation warnings* during compilation
> * *Reduces external dependencies* by using Java standard library
> * *Improves performance* - native Java methods are typically faster
> * *Better null safety* - {{Objects.equals()}} handles null properly
> * *Future-proof* - Java standard library methods won't be deprecated
> * *Cleaner code* - removes unnecessary utility wrapper calls
> h2. Implementation Details
> h3. Method Replacement Details
> h4. 1. StringUtils.startsWith() → String.startsWith()
> *Before:*
> {code:java}
> if (StringUtils.startsWith(url, "https")) {
> // ...
> }
> {code}
> *After:*
> {code:java}
> if (url.startsWith("https")) {
> // ...
> }
> {code}
> *Considerations:* String.startsWith() throws NullPointerException if the
> string is null. Ensure proper null checks exist.
> h4. 2. StringUtils.containsIgnoreCase() → toLowerCase().contains()
> *Before:*
> {code:java}
> if (StringUtils.containsIgnoreCase(query, "keyword")) {
> // ...
> }
> {code}
> *After:*
> {code:java}
> if (query.toLowerCase().contains("keyword".toLowerCase())) {
> // ...
> }
> {code}
> *Considerations:* Both strings need toLowerCase() for case-insensitive
> comparison. Requires null check on the source string.
> h4. 3. StringUtils.equals() → Objects.equals()
> *Before:*
> {code:java}
> if (StringUtils.equals(value1, value2)) {
> // ...
> }
> {code}
> *After:*
> {code:java}
> if (Objects.equals(value1, value2)) {
> // ...
> }
> {code}
> *Benefits:* {{Objects.equals()}} is null-safe and works for any object type,
> not just strings.
> h4. 4. StringUtils.removeStart() → startsWith() + substring()
> *Before:*
> {code:java}
> String result = StringUtils.removeStart(text, "prefix");
> {code}
> *After:*
> {code:java}
> String result = text.startsWith("prefix") ? text.substring("prefix".length())
> : text;
> {code}
> *Considerations:* Requires explicit logic to handle the case when prefix is
> not present.
> h4. 5. LineIterator.nextLine() → LineIterator.next()
> *Before:*
> {code:java}
> while (iterator.hasNext()) {
> String line = iterator.nextLine();
> }
> {code}
> *After:*
> {code:java}
> while (iterator.hasNext()) {
> String line = iterator.next();
> }
> {code}
> *Note:* {{nextLine()}} is deprecated in commons-io 2.18.0. Use {{next()}}
> which is the standard Iterator interface method.
> h3. Files Affected
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java*
> *
> ** Line ~126: {{StringUtils.startsWith()}} → {{String.startsWith()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java*
> *
> ** {{StringUtils.containsIgnoreCase()}} → {{toLowerCase().contains()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/CreateIndexCommand.java*
> *
> ** {{StringUtils.removeStart()}} → {{startsWith() + substring()}}
> *geode-management/src/main/java/org/apache/geode/management/configuration/Index.java*
> *
> ** {{StringUtils.removeStart()}} → {{startsWith() + substring()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/FixedPartitionAttributesInfo.java*
> *
> ** {{StringUtils.equals()}} → {{Objects.equals()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/RegionAttributesInfo.java*
> *
> ** {{StringUtils.equals()}} → {{Objects.equals()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/PartitionAttributesInfo.java*
> *
> ** {{StringUtils.equals()}} → {{Objects.equals()}}
> *geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/cli/commands/StartServerCommandAcceptanceTest.java*
> *
> ** {{LineIterator.nextLine()}} → {{LineIterator.next()}}
> h3. Required Imports
> Add these imports where needed:
> {code:java}
> import java.util.Objects; // For Objects.equals()
> {code}
> Remove if no longer used:
> {code:java}
> import org.apache.commons.lang3.StringUtils;
> {code}
> h2. Testing Strategy
> h3. Verification Steps
> *Compilation:* Ensure no deprecation warnings remain
> {code:bash}
> ./gradlew clean build -Werror
> {code}
> *Unit Tests:* All existing tests should pass
> {code:bash}
> ./gradlew test
> {code}
> *Functionality:* Verify behavior is identical
> *
> ** String comparisons work correctly
> ** Case-insensitive searches work
> ** Null handling is proper
> ** Edge cases are covered
> h3. Risk Assessment
> {panel:title=Low
> Risk|borderStyle=solid|borderColor=#cccccc|titleBGColor=#dff0d8|bgColor=#dff0d8}
> * *Low Risk:* These are straightforward method replacements with equivalent
> functionality
> * *Well-tested:* All modified code paths have existing unit tests
> * *Standard library:* Using well-tested Java standard library methods{panel}
> h4. Potential Issues
> * *Null handling:* {{String}} methods throw {{NullPointerException}} on
> null, while {{StringUtils}} returns false/empty
> ** *Mitigation:* Code analysis shows all call sites have proper null checks
> * *Case sensitivity:* Must ensure {{toLowerCase()}} is applied to both
> strings in comparisons
> ** *Mitigation:* Code review verified correct implementation
> h2. Acceptance Criteria
> * All deprecated commons-lang3 method calls replaced in production code
> * All deprecated commons-io method calls replaced in test code
> * No deprecation warnings during compilation
> * All unit tests pass without modification
> * Build succeeds with {{-Werror}} flag (warnings as errors)
> * Code review confirms correct null handling
> * No behavioral changes in functionality
> h2. Related Changes
> * Part of GEODE-10543: commons-lang3 3.18.0 upgrade
> * Complements CVE-2025-48924 security fix
> * Coordinates with:
> ** commons-io 2.18.0 upgrade
> ** slf4j-api 1.7.36 upgrade
> ** Log4j 2.25.3 upgrade
> h2. Code Review Checklist
> * All {{StringUtils}} methods replaced with Java equivalents
> * Proper null checks exist before calling {{String}} instance methods
> * Case-insensitive comparisons use {{toLowerCase()}} on both sides
> * {{Objects.equals()}} imported and used correctly
> * {{LineIterator.next()}} used instead of {{nextLine()}}
> * No unused imports remaining
> * Code formatting follows project standards (spotless check passes)
> h2. Documentation
> h4. Migration Guide for Developers
> Future code should use:
> * {{String.startsWith()}} instead of {{StringUtils.startsWith()}}
> * {{String.toLowerCase().contains()}} instead of
> {{StringUtils.containsIgnoreCase()}}
> * {{Objects.equals()}} instead of {{StringUtils.equals()}}
> * Ternary with {{startsWith() + substring()}} instead of
> {{StringUtils.removeStart()}}
> * {{Iterator.next()}} instead of {{LineIterator.nextLine()}}
> h2. Estimated Effort
> * Analysis: 2 - 3 days
> * Implementation: 1 - 2 weeks
> * Testing: 2 - 3 days
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)