ICU-10390 Implemented Comparable interface in ULocale class.

X-SVN-Rev: 34840
This commit is contained in:
Yoshito Umaoka 2014-01-08 21:07:09 +00:00
parent e38cc9f41b
commit e73ea7ab14
2 changed files with 197 additions and 3 deletions

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 2003-2013, International Business Machines Corporation and
* Copyright (C) 2003-2014, International Business Machines Corporation and
* others. All Rights Reserved.
******************************************************************************
*/
@ -107,7 +107,7 @@ import com.ibm.icu.text.LocaleDisplayNames.DialectHandling;
* @author Ram Viswanadha
* @stable ICU 2.8
*/
public final class ULocale implements Serializable {
public final class ULocale implements Serializable, Comparable<ULocale> {
// using serialver from jdk1.4.2_05
private static final long serialVersionUID = 3715177670352309217L;
@ -775,6 +775,85 @@ public final class ULocale implements Serializable {
return false;
}
/**
* Compares two ULocale for ordering.
* <p><b>Note:</b> The order might change in future.</p>
*
* @param other the ULocale to be compared.
* @return a negative integer, zero, or a positive integer as this ULocale is less than, equal to, or greater
* than the specified ULocale.
* @throws NullPointerException if <code>other</code> is null.
*
* @draft ICU 53
* @provisional This API might change or be removed in a future release.
*/
public int compareTo(ULocale other) {
if (this == other) {
return 0;
}
int cmp = 0;
// Language
cmp = getLanguage().compareTo(other.getLanguage());
if (cmp == 0) {
// Script
cmp = getScript().compareTo(other.getScript());
if (cmp == 0) {
// Region
cmp = getCountry().compareTo(other.getCountry());
if (cmp == 0) {
// Variant
cmp = getVariant().compareTo(other.getVariant());
if (cmp == 0) {
// Keywords
Iterator<String> thisKwdItr = getKeywords();
Iterator<String> otherKwdItr = other.getKeywords();
if (thisKwdItr == null) {
cmp = otherKwdItr == null ? 0 : -1;
} else if (otherKwdItr == null) {
cmp = 1;
} else {
// Both have keywords
while (cmp == 0 && thisKwdItr.hasNext()) {
if (!otherKwdItr.hasNext()) {
cmp = 1;
break;
}
// Compare keyword keys
String thisKey = thisKwdItr.next();
String otherKey = otherKwdItr.next();
cmp = thisKey.compareTo(otherKey);
if (cmp == 0) {
// Compare keyword values
String thisVal = getKeywordValue(thisKey);
String otherVal = other.getKeywordValue(otherKey);
if (thisVal == null) {
cmp = otherVal == null ? 0 : -1;
} else if (otherVal == null) {
cmp = 1;
} else {
cmp = thisVal.compareTo(otherVal);
}
}
}
if (cmp == 0 && otherKwdItr.hasNext()) {
cmp = -1;
}
}
}
}
}
}
// Normalize the result value:
// Note: String.compareTo() may return value other than -1, 0, 1.
// A value other than those are OK by the definition, but we don't want
// associate any semantics other than negative/zero/positive.
return (cmp < 0) ? -1 : ((cmp > 0) ? 1 : 0);
}
/**
* {@icunote} Unlike the Locale API, this returns an array of <code>ULocale</code>,
* not <code>Locale</code>. Returns a list of all installed locales.

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (c) 2004-2013, International Business Machines
* Copyright (c) 2004-2014, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Alan Liu
@ -19,6 +19,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.lang.UCharacter;
@ -4328,4 +4329,118 @@ public class ULocaleTest extends TestFmwk {
// Restore back up
Locale.setDefault(backupDefault);
}
//
// Test case for the behavior of Comparable implementation.
//
public void TestComparable() {
// Test strings used for creating ULocale objects.
// This list contains multiple different strings creating
// multiple equivalent locales.
final String[] localeStrings = {
"en",
"EN",
"en_US",
"en_GB",
"en_US_POSIX",
"en_us_posix",
"ar_EG",
"zh_Hans_CN",
"zh_Hant_TW",
"zh_Hans",
"zh_CN",
"zh_TW",
"th_TH@calendar=buddhist;numbers=thai",
"TH_TH@NUMBERS=thai;CALENDAR=buddhist",
"th_TH@calendar=buddhist",
"th_TH@calendar=gergorian",
"th_TH@numbers=latn",
"abc_def_ghi_jkl_opq",
"abc_DEF_ghi_JKL_opq",
"",
"und",
"This is a bogus locale ID",
"This is a BOGUS locale ID",
"en_POSIX",
"en__POSIX",
};
ULocale[] locales = new ULocale[localeStrings.length];
for (int i = 0; i < locales.length; i++) {
locales[i] = new ULocale(localeStrings[i]);
}
// compares all permutations
for (int i = 0; i < locales.length; i++) {
for (int j = i /* including the locale itself */; j < locales.length; j++) {
boolean eqls1 = locales[i].equals(locales[j]);
boolean eqls2 = locales[i].equals(locales[j]);
if (eqls1 != eqls2) {
errln("FAILED: loc1.equals(loc2) and loc2.equals(loc1) return different results: loc1="
+ locales[i] + ", loc2=" + locales[j]);
}
int cmp1 = locales[i].compareTo(locales[j]);
int cmp2 = locales[j].compareTo(locales[i]);
if ((cmp1 == 0) != eqls1) {
errln("FAILED: inconsistent equals and compareTo: loc1="
+ locales[i] + ", loc2=" + locales[j]);
}
if (cmp1 < 0 && cmp2 <= 0 || cmp1 > 0 && cmp2 >= 0 || cmp1 == 0 && cmp2 != 0) {
errln("FAILED: loc1.compareTo(loc2) is inconsistent with loc2.compareTo(loc1): loc1="
+ locales[i] + ", loc2=" + locales[j]);
}
}
}
// Make sure ULocale objects can be sorted by the Java collection
// framework class without providing a Comparator, and equals/compareTo
// are consistent.
// The sorted locale list created from localeStrings above.
// Duplicated locales are removed and locale string is normalized
// (by the ULocale constructor).
final String[] sortedLocaleStrings = {
"",
"abc_DEF_GHI_JKL_OPQ",
"ar_EG",
"en",
"en__POSIX",
"en_GB",
"en_US",
"en_US_POSIX",
"th_TH@calendar=buddhist",
"th_TH@calendar=buddhist;numbers=thai",
"th_TH@calendar=gergorian",
"th_TH@numbers=latn",
"this is a bogus locale id",
"und",
"zh_CN",
"zh_TW",
"zh_Hans",
"zh_Hans_CN",
"zh_Hant_TW",
};
TreeSet<ULocale> sortedLocales = new TreeSet<ULocale>();
for (ULocale locale : locales) {
sortedLocales.add(locale);
}
// Check the number of unique locales
if (sortedLocales.size() != sortedLocaleStrings.length) {
errln("FAILED: Number of unique locales: " + sortedLocales.size() + ", expected: " + sortedLocaleStrings.length);
}
// Check the order
int i = 0;
for (ULocale loc : sortedLocales) {
if (!loc.toString().equals(sortedLocaleStrings[i++])) {
errln("FAILED: Sort order is incorrect for " + loc.toString());
break;
}
}
}
}