ICU-11434 Merged the fix for locale matcher problem (#11595 / r37295). All icu data jar files were regenerated from ICU4C maint-55 branch including the correponding data changes.
X-SVN-Rev: 37296
diff --git a/main/classes/core/src/com/ibm/icu/util/LocaleMatcher.java b/main/classes/core/src/com/ibm/icu/util/LocaleMatcher.java
index 6f3b306..55160a8 100644
--- a/main/classes/core/src/com/ibm/icu/util/LocaleMatcher.java
+++ b/main/classes/core/src/com/ibm/icu/util/LocaleMatcher.java
@@ -1,6 +1,6 @@
/*
****************************************************************************************
- * Copyright (C) 2009-2014, Google, Inc.; International Business Machines Corporation *
+ * Copyright (C) 2009-2015, Google, Inc.; International Business Machines Corporation *
* and others. All Rights Reserved. *
****************************************************************************************
*/
@@ -11,7 +11,6 @@
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
-import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -19,6 +18,7 @@
import com.ibm.icu.impl.Row;
import com.ibm.icu.impl.Row.R2;
import com.ibm.icu.impl.Row.R3;
+import com.ibm.icu.impl.Utility;
/**
* Provides a way to match the languages (locales) supported by a product to the
@@ -382,6 +382,29 @@
}
return result;
}
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ LocalePatternMatcher other = (LocalePatternMatcher) obj;
+ return Utility.objectEquals(level, other.level)
+ && Utility.objectEquals(lang, other.lang)
+ && Utility.objectEquals(script, other.script)
+ && Utility.objectEquals(region, other.region);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return level.ordinal()
+ ^ (lang == null ? 0 : lang.hashCode())
+ ^ (script == null ? 0 : script.hashCode())
+ ^ (region == null ? 0 : region.hashCode());
+ }
}
enum Level {
@@ -420,7 +443,10 @@
// lang_result.put(supported, result = new LinkedHashSet());
// }
// result.add(data);
- scores.add(data);
+ boolean added = scores.add(data);
+ if (!added) {
+ throw new ICUException("trying to add duplicate data: " + data);
+ }
}
double getScore(ULocale desiredLocale, ULocale dMax, String desiredRaw, String desiredMax,
@@ -605,6 +631,7 @@
* @internal
* @deprecated This API is ICU internal only.
*/
+ @SuppressWarnings("unused")
@Deprecated
private LanguageMatcherData addDistance(String desired, String supported, int percent) {
return addDistance(desired, supported, percent, false, null);
@@ -654,12 +681,13 @@
}
R3<LocalePatternMatcher,LocalePatternMatcher,Double> data = Row.of(desiredMatcher, supportedMatcher, score);
R3<LocalePatternMatcher,LocalePatternMatcher,Double> data2 = oneway ? null : Row.of(supportedMatcher, desiredMatcher, score);
+ boolean desiredEqualsSupported = desiredMatcher.equals(supportedMatcher);
switch (desiredLen) {
case language:
String dlanguage = desiredMatcher.getLanguage();
String slanguage = supportedMatcher.getLanguage();
languageScores.addDataToScores(dlanguage, slanguage, data);
- if (!oneway) {
+ if (!oneway && !desiredEqualsSupported) {
languageScores.addDataToScores(slanguage, dlanguage, data2);
}
break;
@@ -667,7 +695,7 @@
String dscript = desiredMatcher.getScript();
String sscript = supportedMatcher.getScript();
scriptScores.addDataToScores(dscript, sscript, data);
- if (!oneway) {
+ if (!oneway && !desiredEqualsSupported) {
scriptScores.addDataToScores(sscript, dscript, data2);
}
break;
@@ -675,7 +703,7 @@
String dregion = desiredMatcher.getRegion();
String sregion = supportedMatcher.getRegion();
regionScores.addDataToScores(dregion, sregion, data);
- if (!oneway) {
+ if (!oneway && !desiredEqualsSupported) {
regionScores.addDataToScores(sregion, dregion, data2);
}
break;
@@ -832,12 +860,12 @@
defaultWritten = new LanguageMatcherData();
// HACK
// The data coming from ICU may be old, and badly ordered.
- TreeSet<DataHack> hack = new TreeSet<DataHack>();
- defaultWritten.addDistance("en_*_US", "en_*_*", 97);
- defaultWritten.addDistance("en_*_GB", "en_*_*", 98);
- defaultWritten.addDistance("es_*_ES", "es_*_*", 97);
- defaultWritten.addDistance("es_*_419", "es_*_*", 99);
- defaultWritten.addDistance("es_*_*", "es_*_*", 98);
+ // TreeSet<DataHack> hack = new TreeSet<DataHack>();
+ // defaultWritten.addDistance("en_*_US", "en_*_*", 97);
+ // defaultWritten.addDistance("en_*_GB", "en_*_*", 98);
+ // defaultWritten.addDistance("es_*_ES", "es_*_*", 97);
+ // defaultWritten.addDistance("es_*_419", "es_*_*", 99);
+ // defaultWritten.addDistance("es_*_*", "es_*_*", 98);
for(UResourceBundleIterator iter = written.getIterator(); iter.hasNext();) {
ICUResourceBundle item = (ICUResourceBundle) iter.next();
@@ -846,11 +874,14 @@
"*_*_*",
"96",
*/
- hack.add(new DataHack(item.getString(0), item.getString(1), Integer.parseInt(item.getString(2))));
+ // <languageMatch desired="gsw" supported="de" percent="96" oneway="true" />
+ boolean oneway = item.getSize() > 3 && "1".equals(item.getString(3));
+ //hack.add(new DataHack(item.getString(0), item.getString(1), Integer.parseInt(item.getString(2))));
+ defaultWritten.addDistance(item.getString(0), item.getString(1), Integer.parseInt(item.getString(2)), oneway);
}
- for (DataHack dataHack : hack) {
- defaultWritten.addDistance(dataHack.source, dataHack.target, dataHack.percent);
- }
+ // for (DataHack dataHack : hack) {
+ // defaultWritten.addDistance(dataHack.source, dataHack.target, dataHack.percent);
+ // }
defaultWritten.freeze();
}
diff --git a/main/shared/data/icudata.jar b/main/shared/data/icudata.jar
index 0c0427c..52bffbb 100755
--- a/main/shared/data/icudata.jar
+++ b/main/shared/data/icudata.jar
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:92f57fe76358c19d7b39e415b85f047fb380bca03cd8e119c31284b90d7e73ce
-size 11844245
+oid sha256:3d908f3e3c78898225932228d32ecf77de3454c3a27a081474faf5a8e7d22f7e
+size 11844585
diff --git a/main/shared/data/icutzdata.jar b/main/shared/data/icutzdata.jar
index 007f1fe..ff9357e 100755
--- a/main/shared/data/icutzdata.jar
+++ b/main/shared/data/icutzdata.jar
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5d67e05e8112c7dade8c71febee6cf4d44d00f88ad64228fc84c00a28d258fed
+oid sha256:585048d23a9d38cbd65ac6fe4e72f50f9e1af76b1154495abee83b4578d43af6
size 90539
diff --git a/main/shared/data/testdata.jar b/main/shared/data/testdata.jar
index 433c0c3..b14b769 100755
--- a/main/shared/data/testdata.jar
+++ b/main/shared/data/testdata.jar
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:483fd47da6b6dfc63c5306139c2ac120a820f3b7024c89d5707c66581ab6d69d
-size 812499
+oid sha256:4682b21253c779a47c5fb00f3e38b9d3f2d832b3ae1afe71112e2355aa95d971
+size 812503
diff --git a/main/tests/core/src/com/ibm/icu/dev/test/util/LocaleMatcherTest.java b/main/tests/core/src/com/ibm/icu/dev/test/util/LocaleMatcherTest.java
index 8532d4a..aa5d8b9 100644
--- a/main/tests/core/src/com/ibm/icu/dev/test/util/LocaleMatcherTest.java
+++ b/main/tests/core/src/com/ibm/icu/dev/test/util/LocaleMatcherTest.java
@@ -1,6 +1,6 @@
/*
******************************************************************************************
- * Copyright (C) 2009-2014, Google, Inc.; International Business Machines Corporation and *
+ * Copyright (C) 2009-2015, Google, Inc.; International Business Machines Corporation and *
* others. All Rights Reserved. *
******************************************************************************************
*/
@@ -285,12 +285,29 @@
LocaleMatcher matcher = new LocaleMatcher("es_AR, es");
assertEquals("es_AR", matcher.getBestMatch("es_MX").toString());
- matcher = new LocaleMatcher("fr, en, en_CA");
- assertEquals("en_CA", matcher.getBestMatch("en_GB").toString());
+ matcher = new LocaleMatcher("fr, en, en_GB");
+ assertEquals("en_GB", matcher.getBestMatch("en_CA").toString());
matcher = new LocaleMatcher("de_AT, de_DE, de_CH");
assertEquals("de_DE", matcher.getBestMatch("de").toString());
+
+ showDistance(matcher, "en", "en_CA");
+ showDistance(matcher, "en_CA", "en");
+ showDistance(matcher, "en_US", "en_CA");
+ showDistance(matcher, "en_CA", "en_US");
+ showDistance(matcher, "en_GB", "en_CA");
+ showDistance(matcher, "en_CA", "en_GB");
+ showDistance(matcher, "en", "en_UM");
+ showDistance(matcher, "en_UM", "en");
}
+
+ private void showDistance(LocaleMatcher matcher, String desired, String supported) {
+ ULocale desired2 = new ULocale(desired);
+ ULocale supported2 = new ULocale(supported);
+ double distance = matcher.match(desired2, ULocale.addLikelySubtags(desired2), supported2, ULocale.addLikelySubtags(supported2));
+ logln(desired + " to " + supported + " :\t" + distance);
+ }
+
/**
* If all the base languages are the same, then each sublocale matches itself most closely
@@ -336,6 +353,15 @@
}
}
+ public void testAsymmetry() {
+ LocaleMatcher matcher;
+ matcher = new LocaleMatcher("mul, nl");
+ assertEquals("nl", matcher.getBestMatch("af").toString()); // af => nl
+
+ matcher = new LocaleMatcher("mul, af");
+ assertEquals("mul", matcher.getBestMatch("nl").toString()); // but nl !=> af
+ }
+
// public void testComputeDistance_monkeyTest() {
// RegionCode[] codes = RegionCode.values();