sharanggupta opened a new pull request, #749:
URL: https://github.com/apache/commons-collections/pull/749

   Fixes 
[COLLECTIONS-899](https://issues.apache.org/jira/browse/COLLECTIONS-899), 
following the discussion there.
   
   **What**
   
   As discussed in the issue, `CaseInsensitiveMap` deliberately converts each 
character with `Character.toLowerCase(Character.toUpperCase(c))` since 
COLLECTIONS-294, which avoids the locale problems of `String.toLowerCase()`. 
Two things did not match that, though:
   
   - The class Javadoc says that keys are "converted to all lowercase", which 
suggests `String.toLowerCase()`. As the report shows, U+03D0 (GREEK BETA 
SYMBOL) and U+03B2 (GREEK SMALL LETTER BETA) give the same key, while 
`"\u03D0".toLowerCase(Locale.ROOT)` leaves U+03D0 unchanged.
   - As Bernd noted in the issue, `convertKey()` works on `char`s, so 
characters outside the Basic Multilingual Plane, which are surrogate pairs, are 
never converted. U+10400 and U+10428 (DESERET CAPITAL and SMALL LETTER LONG I) 
stay two different keys. On Java 17 and later, `String.equalsIgnoreCase()` 
compares code points and considers them equal (on Java 8 and 11 it does not).
   
   **How**
   
   - `convertKey()` now converts each code point with 
`Character.toLowerCase(Character.toUpperCase(int))` and appends it with 
`StringBuilder.appendCodePoint()`, so supplementary characters are converted 
like any other character. The result for strings in the Basic Multilingual 
Plane is unchanged, and unpaired surrogates are kept as they are, as before.
   - The class Javadoc and the Javadoc of `convertKey()` now say what the 
conversion does: the simple, one-to-one Unicode case mappings, independently of 
the locale, which is not the same as `String.toLowerCase(Locale)`. The example 
from the report is included.
   
   A map serialized by an older version that holds two keys differing only in 
the case of a supplementary character gets one entry for them when it is 
deserialized, since `doReadObject()` puts every entry again.
   
   **Tests**
   
   In `CaseInsensitiveMapTest`:
   
   - `testSupplementaryCharacters` puts keys with the Deseret capital letter, 
alone and inside a longer string. It gets them with the small letter and checks 
the stored lowercase keys. It checks that both spellings are one entry, also 
after serialization, and that a different Deseret letter is another entry. It 
fails on master (`expected: <value> but was: <null>`) and passes with this 
change.
   - `testUncasedSupplementaryCharactersAndUnpairedSurrogates` checks that an 
emoji and unpaired surrogates are kept as they are.
   - `testConversionIsIdempotent` checks, for every code point, that a 
converted key converts to itself, which deserialization relies on, since it 
converts the keys again.
   
   The tests do not depend on the Java version (`equalsIgnoreCase()` differs 
between Java 8/11 and 17+). `CaseInsensitiveMapTest` passes on Java 8 and 17, 
and the default Maven goal passes locally on Java 17.
   
   Before you push a pull request, review this list:
   
   - [x] Read the [contribution guidelines](CONTRIBUTING.md) for this project.
   - [x] Read the [ASF Generative Tooling 
Guidance](https://www.apache.org/legal/generative-tooling.html) if you use 
Artificial Intelligence (AI).
   - [x] 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? Claude (Anthropic) helped analyse the issue and draft the change 
and tests; I reviewed them against the code and ran the build.
   - [x] Run a successful build using the default 
[Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command 
line by itself.
   - [x] 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.
   - [x] Write a pull request description that is detailed enough to understand 
what the pull request does, how, and why.
   - [x] 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.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to