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]
