2 *******************************************************************************
3 * Copyright (C) 2001-2004, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
7 *******************************************************************************
10 #include "unicode/utypes.h"
12 #if !UCONFIG_NO_SERVICE
19 class MyListener
: public EventListener
{
22 class WrongListener
: public EventListener
{
25 class ICUNSubclass
: public ICUNotifier
{
27 UBool
acceptsListener(const EventListener
& l
) const {
29 // return l instanceof MyListener;
32 virtual void notifyListener(EventListener
& l
) const {
36 class LKFSubclass
: public LocaleKeyFactory
{
40 LKFSubclass(UBool visible
)
41 : LocaleKeyFactory(visible
? VISIBLE
: INVISIBLE
, "LKFSubclass")
43 UErrorCode status
= U_ZERO_ERROR
;
44 table
.put("en_US", this, status
);
48 virtual const Hashtable
* getSupportedIDs(UErrorCode
&/*status*/) const {
53 class Integer
: public UObject
{
57 Integer(int32_t val
) : _val(val
) {
60 Integer(const Integer
& rhs
) : UObject(rhs
), _val(rhs
._val
) {
65 virtual UBool
operator==(const UObject
& other
) const
67 return other
.getDynamicClassID() == getStaticClassID() &&
68 _val
== ((Integer
&)other
)._val
;
73 * UObject boilerplate.
75 virtual UClassID
getDynamicClassID() const {
76 return getStaticClassID();
79 static UClassID
getStaticClassID() {
80 return (UClassID
)&fgClassID
;
84 virtual UnicodeString
& debug(UnicodeString
& result
) const {
86 result
.append(" val: ");
91 virtual UnicodeString
& debugClass(UnicodeString
& result
) const {
92 return result
.append("Integer");
96 static const char fgClassID
;
99 const char Integer::fgClassID
= '\0';
102 class TestIntegerService
: public ICUService
{
104 ICUServiceKey
* createKey(const UnicodeString
* id
, UErrorCode
& status
) const {
105 return LocaleKey::createWithCanonicalFallback(id
, NULL
, status
); // no fallback locale
108 virtual ICUServiceFactory
* createSimpleFactory(UObject
* obj
, const UnicodeString
& id
, UBool visible
, UErrorCode
& status
)
110 if (U_SUCCESS(status
) && obj
&& obj
->getDynamicClassID() == Integer::getStaticClassID()) {
111 return new SimpleFactory((Integer
*)obj
, id
, visible
);
116 virtual UObject
* cloneInstance(UObject
* instance
) const {
117 return instance
? new Integer(*(Integer
*)instance
) : NULL
;
122 ICUServiceTest::ICUServiceTest() {
125 ICUServiceTest::~ICUServiceTest() {
129 ICUServiceTest::runIndexedTest(int32_t index
, UBool exec
, const char* &name
,
133 TESTCASE(0,testAPI_One
);
134 TESTCASE(1,testAPI_Two
);
136 TESTCASE(3,testNotification
);
137 TESTCASE(4,testLocale
);
138 TESTCASE(5,testWrapFactory
);
139 TESTCASE(6,testCoverage
);
140 default: name
= ""; break;
144 UnicodeString
append(UnicodeString
& result
, const UObject
* obj
)
148 result
.append("NULL");
150 UClassID id
= obj
->getDynamicClassID();
151 if (id
== UnicodeString::getStaticClassID()) {
152 result
.append(*(UnicodeString
*)obj
);
153 } else if (id
== Locale::getStaticClassID()) {
154 result
.append(((Locale
*)obj
)->getName());
155 } else if (id
== Integer::getStaticClassID()) {
156 sprintf(buffer
, "%d", (int)((Integer
*)obj
)->_val
);
157 result
.append(buffer
);
159 sprintf(buffer
, "%p", (const void*)obj
);
160 result
.append(buffer
);
167 ICUServiceTest::lrmsg(UnicodeString
& result
, const UnicodeString
& message
, const UObject
* lhs
, const UObject
* rhs
) const
169 result
.append(message
);
170 result
.append(" lhs: ");
172 result
.append(", rhs: ");
178 ICUServiceTest::confirmBoolean(const UnicodeString
& message
, UBool val
)
189 ICUServiceTest::confirmEqual(const UnicodeString
& message
, const UObject
* lhs
, const UObject
* rhs
)
191 UBool equ
= (lhs
== NULL
)
193 : (rhs
!= NULL
&& lhs
->operator==(*rhs
));
196 lrmsg(temp
, message
, lhs
, rhs
);
206 ICUServiceTest::confirmEqual(const UnicodeString
& message
, const Integer
* lhs
, const Integer
* rhs
)
208 UBool equ
= (lhs
== NULL
)
210 : (rhs
!= NULL
&& lhs
->operator==(*rhs
));
213 lrmsg(temp
, message
, lhs
, rhs
);
223 ICUServiceTest::confirmEqual(const UnicodeString
& message
, const UnicodeString
* lhs
, const UnicodeString
* rhs
)
225 UBool equ
= (lhs
== NULL
)
227 : (rhs
!= NULL
&& lhs
->operator==(*rhs
));
230 lrmsg(temp
, message
, lhs
, rhs
);
240 ICUServiceTest::confirmEqual(const UnicodeString
& message
, const Locale
* lhs
, const Locale
* rhs
)
242 UBool equ
= (lhs
== NULL
)
244 : (rhs
!= NULL
&& lhs
->operator==(*rhs
));
247 lrmsg(temp
, message
, lhs
, rhs
);
259 ICUServiceTest::confirmStringsEqual(const UnicodeString
& message
, const UnicodeString
& lhs
, const UnicodeString
& rhs
)
261 UBool equ
= lhs
== rhs
;
263 UnicodeString temp
= message
;
264 temp
.append(" lhs: ");
266 temp
.append(" rhs: ");
278 ICUServiceTest::confirmIdentical(const UnicodeString
& message
, const UObject
* lhs
, const UObject
*rhs
)
281 lrmsg(temp
, message
, lhs
, rhs
);
290 ICUServiceTest::confirmIdentical(const UnicodeString
& message
, int32_t lhs
, int32_t rhs
)
293 logln(message
+ " lhs: " + lhs
+ " rhs: " + rhs
);
295 errln(message
+ " lhs: " + lhs
+ " rhs: " + rhs
);
300 ICUServiceTest::msgstr(const UnicodeString
& message
, UObject
* obj
, UBool err
)
303 UnicodeString
* str
= (UnicodeString
*)obj
;
304 logln(message
+ *str
);
307 errln("Error " + message
+ "string is NULL");
312 ICUServiceTest::testAPI_One()
314 // create a service using locale keys,
315 TestIntegerService service
;
317 // register an object with one locale,
318 // search for an object with a more specific locale
319 // should return the original object
320 UErrorCode status
= U_ZERO_ERROR
;
321 Integer
* singleton0
= new Integer(0);
322 service
.registerInstance(singleton0
, "en_US", status
);
324 UErrorCode status
= U_ZERO_ERROR
;
325 Integer
* result
= (Integer
*)service
.get("en_US_FOO", status
);
326 confirmEqual("1) en_US_FOO -> en_US", result
, singleton0
);
330 // register a new object with the more specific locale
331 // search for an object with that locale
332 // should return the new object
333 Integer
* singleton1
= new Integer(1);
334 service
.registerInstance(singleton1
, "en_US_FOO", status
);
336 UErrorCode status
= U_ZERO_ERROR
;
337 Integer
* result
= (Integer
*)service
.get("en_US_FOO", status
);
338 confirmEqual("2) en_US_FOO -> en_US_FOO", result
, singleton1
);
342 // search for an object that falls back to the first registered locale
344 UErrorCode status
= U_ZERO_ERROR
;
345 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
346 confirmEqual("3) en_US_BAR -> en_US", result
, singleton0
);
350 // get a list of the factories, should be two
352 confirmIdentical("4) factory size", service
.countFactories(), 2);
355 // register a new object with yet another locale
356 Integer
* singleton2
= new Integer(2);
357 service
.registerInstance(singleton2
, "en", status
);
359 confirmIdentical("5) factory size", service
.countFactories(), 3);
362 // search for an object with the new locale
363 // stack of factories is now en, en_US_FOO, en_US
364 // search for en_US should still find en_US object
366 UErrorCode status
= U_ZERO_ERROR
;
367 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
368 confirmEqual("6) en_US_BAR -> en_US", result
, singleton0
);
372 // register a new object with an old id, should hide earlier factory using this id, but leave it there
373 Integer
* singleton3
= new Integer(3);
374 URegistryKey s3key
= service
.registerInstance(singleton3
, "en_US", status
);
376 confirmIdentical("9) factory size", service
.countFactories(), 4);
379 // should get data from that new factory
381 UErrorCode status
= U_ZERO_ERROR
;
382 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
383 confirmEqual("10) en_US_BAR -> (3)", result
, singleton3
);
387 // remove new factory
388 // should have fewer factories again
391 UErrorCode status
= U_ZERO_ERROR
;
392 service
.unregister(s3key
, status
);
393 confirmIdentical("11) factory size", service
.countFactories(), 3);
396 // should get original data again after remove factory
398 UErrorCode status
= U_ZERO_ERROR
;
399 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
400 confirmEqual("12) en_US_BAR -> (3)", result
, singleton0
);
404 // shouldn't find unregistered ids
406 UErrorCode status
= U_ZERO_ERROR
;
407 Integer
* result
= (Integer
*)service
.get("foo", status
);
408 confirmIdentical("13) foo -> null", result
, NULL
);
412 // should find non-canonical strings
414 UnicodeString resultID
;
415 UErrorCode status
= U_ZERO_ERROR
;
416 Integer
* result
= (Integer
*)service
.get("EN_us_fOo", &resultID
, status
);
417 confirmEqual("14a) find-non-canonical", result
, singleton1
);
418 confirmStringsEqual("14b) find non-canonical", resultID
, "en_US_FOO");
422 // should be able to register non-canonical strings and get them canonicalized
423 Integer
* singleton4
= new Integer(4);
424 service
.registerInstance(singleton4
, "eN_ca_dUde", status
);
426 UnicodeString resultID
;
427 UErrorCode status
= U_ZERO_ERROR
;
428 Integer
* result
= (Integer
*)service
.get("En_Ca_DuDe", &resultID
, status
);
429 confirmEqual("15a) find-non-canonical", result
, singleton4
);
430 confirmStringsEqual("15b) register non-canonical", resultID
, "en_CA_DUDE");
434 // should be able to register invisible factories, these will not
435 // be visible by default, but if you know the secret password you
436 // can still access these services...
437 Integer
* singleton5
= new Integer(5);
438 service
.registerInstance(singleton5
, "en_US_BAR", FALSE
, status
);
440 UErrorCode status
= U_ZERO_ERROR
;
441 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
442 confirmEqual("17) get invisible", result
, singleton5
);
446 // should not be able to locate invisible services
448 UErrorCode status
= U_ZERO_ERROR
;
449 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, status
);
450 service
.getVisibleIDs(ids
, status
);
451 UnicodeString target
= "en_US_BAR";
452 confirmBoolean("18) find invisible", !ids
.contains(&target
));
455 // clear factory and caches
457 confirmBoolean("19) is default", service
.isDefault());
461 ******************************************************************
464 class TestStringService
: public ICUService
{
466 ICUServiceKey
* createKey(const UnicodeString
* id
, UErrorCode
& status
) const {
467 return LocaleKey::createWithCanonicalFallback(id
, NULL
, status
); // no fallback locale
470 virtual ICUServiceFactory
* createSimpleFactory(UObject
* obj
, const UnicodeString
& id
, UBool visible
, UErrorCode
& /* status */)
472 if (obj
&& obj
->getDynamicClassID() == UnicodeString::getStaticClassID()) {
473 return new SimpleFactory((UnicodeString
*)obj
, id
, visible
);
478 virtual UObject
* cloneInstance(UObject
* instance
) const {
479 return instance
? new UnicodeString(*(UnicodeString
*)instance
) : NULL
;
483 // this creates a string for any id, but doesn't report anything
484 class AnonymousStringFactory
: public ICUServiceFactory
487 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* /* service */, UErrorCode
& /* status */) const {
488 return new UnicodeString(key
.getID());
491 virtual void updateVisibleIDs(Hashtable
& /*result*/, UErrorCode
& /*status*/) const {
495 virtual UnicodeString
& getDisplayName(const UnicodeString
& /*id*/, const Locale
& /*locale*/, UnicodeString
& result
) const {
500 virtual UClassID
getDynamicClassID() const {
501 return getStaticClassID();
504 static UClassID
getStaticClassID() {
505 return (UClassID
)&fgClassID
;
509 static const char fgClassID
;
512 const char AnonymousStringFactory::fgClassID
= '\0';
514 class TestMultipleKeyStringFactory
: public ICUServiceFactory
{
517 UnicodeString _factoryID
;
520 TestMultipleKeyStringFactory(const UnicodeString ids
[], int32_t count
, const UnicodeString
& factoryID
)
521 : _status(U_ZERO_ERROR
)
522 , _ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, count
, _status
)
523 , _factoryID(factoryID
+ ": ")
525 for (int i
= 0; i
< count
; ++i
) {
526 _ids
.addElement(new UnicodeString(ids
[i
]), _status
);
530 ~TestMultipleKeyStringFactory() {
533 UObject
* create(const ICUServiceKey
& key
, const ICUService
* /* service */, UErrorCode
& status
) const {
534 if (U_FAILURE(status
)) {
539 if (U_SUCCESS(_status
)) {
540 if (_ids
.contains(&temp
)) {
541 return new UnicodeString(_factoryID
+ temp
);
549 void updateVisibleIDs(Hashtable
& result
, UErrorCode
& status
) const {
550 if (U_SUCCESS(_status
)) {
551 for (int32_t i
= 0; i
< _ids
.size(); ++i
) {
552 result
.put(*(UnicodeString
*)_ids
[i
], (void*)this, status
);
557 UnicodeString
& getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const {
558 if (U_SUCCESS(_status
) && _ids
.contains((void*)&id
)) {
560 UErrorCode status
= U_ZERO_ERROR
;
561 int32_t len
= id
.extract(buffer
, sizeof(buffer
), NULL
, status
);
562 if (U_SUCCESS(status
)) {
563 if (len
== sizeof(buffer
)) {
567 Locale loc
= Locale::createFromName(buffer
);
568 loc
.getDisplayName(locale
, result
);
572 result
.setToBogus(); // shouldn't happen
576 virtual UClassID
getDynamicClassID() const {
577 return getStaticClassID();
580 static UClassID
getStaticClassID() {
581 return (UClassID
)&fgClassID
;
585 static const char fgClassID
;
588 const char TestMultipleKeyStringFactory::fgClassID
= '\0';
591 ICUServiceTest::testAPI_Two()
593 UErrorCode status
= U_ZERO_ERROR
;
594 TestStringService service
;
595 service
.registerFactory(new AnonymousStringFactory(), status
);
597 // anonymous factory will still handle the id
599 UErrorCode status
= U_ZERO_ERROR
;
600 const UnicodeString en_US
= "en_US";
601 UnicodeString
* result
= (UnicodeString
*)service
.get(en_US
, status
);
602 confirmEqual("21) locale", result
, &en_US
);
606 // still normalizes id
608 UErrorCode status
= U_ZERO_ERROR
;
609 const UnicodeString en_US_BAR
= "en_US_BAR";
610 UnicodeString resultID
;
611 UnicodeString
* result
= (UnicodeString
*)service
.get("EN_us_bar", &resultID
, status
);
612 confirmEqual("22) locale", &resultID
, &en_US_BAR
);
616 // we can override for particular ids
617 UnicodeString
* singleton0
= new UnicodeString("Zero");
618 service
.registerInstance(singleton0
, "en_US_BAR", status
);
620 UErrorCode status
= U_ZERO_ERROR
;
621 UnicodeString
* result
= (UnicodeString
*)service
.get("en_US_BAR", status
);
622 confirmEqual("23) override super", result
, singleton0
);
626 // empty service should not recognize anything
629 UErrorCode status
= U_ZERO_ERROR
;
630 UnicodeString
* result
= (UnicodeString
*)service
.get("en_US", status
);
631 confirmIdentical("24) empty", result
, NULL
);
634 // create a custom multiple key factory
636 UnicodeString xids
[] = {
642 int32_t count
= sizeof(xids
)/sizeof(UnicodeString
);
644 ICUServiceFactory
* f
= new TestMultipleKeyStringFactory(xids
, count
, "Later");
645 service
.registerFactory(f
, status
);
648 // iterate over the visual ids returned by the multiple factory
650 UErrorCode status
= U_ZERO_ERROR
;
651 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
652 service
.getVisibleIDs(ids
, status
);
653 for (int i
= 0; i
< ids
.size(); ++i
) {
654 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
655 UnicodeString
* result
= (UnicodeString
*)service
.get(*id
, status
);
657 logln(" " + *id
+ " --> " + *result
);
660 errln("could not find " + *id
);
664 confirmIdentical("25) visible ids", ids
.size(), 4);
667 // iterate over the display names
669 UErrorCode status
= U_ZERO_ERROR
;
670 UVector
names(userv_deleteStringPair
, NULL
, status
);
671 service
.getDisplayNames(names
, Locale::getGerman(), status
);
672 for (int i
= 0; i
< names
.size(); ++i
) {
673 const StringPair
* pair
= (const StringPair
*)names
[i
];
674 logln(" " + pair
->displayName
+ " --> " + pair
->id
);
676 confirmIdentical("26) display names", names
.size(), 4);
679 // no valid display name
682 service
.getDisplayName("en_US_VALLEY_GEEK", name
);
683 confirmBoolean("27) get display name", name
.isBogus());
688 service
.getDisplayName("en_US_SURFER_DUDE", name
, Locale::getEnglish());
689 confirmStringsEqual("28) get display name", name
, "English (United States, SURFER_DUDE)");
692 // register another multiple factory
694 UnicodeString xids
[] = {
698 "en_US_SILICON_GEEK",
700 int32_t count
= sizeof(xids
)/sizeof(UnicodeString
);
702 ICUServiceFactory
* f
= new TestMultipleKeyStringFactory(xids
, count
, "Rad dude");
703 service
.registerFactory(f
, status
);
706 // this time, we have seven display names
707 // Rad dude's surfer gal 'replaces' Later's surfer gal
709 UErrorCode status
= U_ZERO_ERROR
;
710 UVector
names(userv_deleteStringPair
, NULL
, status
);
711 service
.getDisplayNames(names
, Locale("es"), status
);
712 for (int i
= 0; i
< names
.size(); ++i
) {
713 const StringPair
* pair
= (const StringPair
*)names
[i
];
714 logln(" " + pair
->displayName
+ " --> " + pair
->id
);
716 confirmIdentical("26) display names", names
.size(), 7);
719 // we should get the display name corresponding to the actual id
720 // returned by the id we used.
722 UErrorCode status
= U_ZERO_ERROR
;
723 UnicodeString actualID
;
724 UnicodeString id
= "en_us_surfer_gal";
725 UnicodeString
* gal
= (UnicodeString
*)service
.get(id
, &actualID
, status
);
727 UnicodeString displayName
;
728 logln("actual id: " + actualID
);
729 service
.getDisplayName(actualID
, displayName
, Locale::getEnglish());
730 logln("found actual: " + *gal
+ " with display name: " + displayName
);
731 confirmBoolean("30) found display name for actual", !displayName
.isBogus());
733 service
.getDisplayName(id
, displayName
, Locale::getEnglish());
734 logln("found actual: " + *gal
+ " with display name: " + displayName
);
735 confirmBoolean("31) found display name for query", displayName
.isBogus());
739 errln("30) service could not find entry for " + id
);
743 // this should be handled by the 'dude' factory, since it overrides en_US_SURFER.
745 UErrorCode status
= U_ZERO_ERROR
;
746 UnicodeString actualID
;
747 UnicodeString id
= "en_US_SURFER_BOZO";
748 UnicodeString
* bozo
= (UnicodeString
*)service
.get(id
, &actualID
, status
);
750 UnicodeString displayName
;
751 service
.getDisplayName(actualID
, displayName
, Locale::getEnglish());
752 logln("found actual: " + *bozo
+ " with display name: " + displayName
);
753 confirmBoolean("32) found display name for actual", !displayName
.isBogus());
755 service
.getDisplayName(id
, displayName
, Locale::getEnglish());
756 logln("found actual: " + *bozo
+ " with display name: " + displayName
);
757 confirmBoolean("33) found display name for query", displayName
.isBogus());
761 errln("32) service could not find entry for " + id
);
765 // certainly not default...
767 confirmBoolean("34) is default ", !service
.isDefault());
771 UErrorCode status
= U_ZERO_ERROR
;
772 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
773 service
.getVisibleIDs(ids
, status
);
774 for (int i
= 0; i
< ids
.size(); ++i
) {
775 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
776 msgstr(*id
+ "? ", service
.get(*id
, status
));
779 logstr("valleygirl? ", service
.get("en_US_VALLEY_GIRL", status
));
780 logstr("valleyboy? ", service
.get("en_US_VALLEY_BOY", status
));
781 logstr("valleydude? ", service
.get("en_US_VALLEY_DUDE", status
));
782 logstr("surfergirl? ", service
.get("en_US_SURFER_GIRL", status
));
787 class CalifornioLanguageFactory
: public ICUResourceBundleFactory
790 static const char* californio
; // = "en_US_CA";
791 static const char* valley
; // = californio ## "_VALLEY";
792 static const char* surfer
; // = californio ## "_SURFER";
793 static const char* geek
; // = californio ## "_GEEK";
794 static Hashtable
* supportedIDs
; // = NULL;
796 static void cleanup(void) {
801 const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
803 if (supportedIDs
== NULL
) {
804 Hashtable
* table
= new Hashtable();
805 table
->put(UnicodeString(californio
), (void*)table
, status
);
806 table
->put(UnicodeString(valley
), (void*)table
, status
);
807 table
->put(UnicodeString(surfer
), (void*)table
, status
);
808 table
->put(UnicodeString(geek
), (void*)table
, status
);
810 // not necessarily atomic, but this is a test...
811 supportedIDs
= table
;
816 UnicodeString
& getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const
818 UnicodeString prefix
= "";
819 UnicodeString suffix
= "";
820 UnicodeString ls
= locale
.getName();
821 if (LocaleUtility::isFallbackOf(californio
, ls
)) {
822 if (!ls
.caseCompare(valley
, 0)) {
823 prefix
= "Like, you know, it's so totally ";
824 } else if (!ls
.caseCompare(surfer
, 0)) {
825 prefix
= "Dude, it's ";
826 } else if (!ls
.caseCompare(geek
, 0)) {
827 prefix
= "I'd estimate it is approximately ";
829 prefix
= "Huh? Maybe ";
832 if (LocaleUtility::isFallbackOf(californio
, id
)) {
833 if (!id
.caseCompare(valley
, 0)) {
834 suffix
= "like the Valley, you know? Let's go to the mall!";
835 } else if (!id
.caseCompare(surfer
, 0)) {
836 suffix
= "time to hit those gnarly waves, Dude!!!";
837 } else if (!id
.caseCompare(geek
, 0)) {
838 suffix
= "all systems go. T-Minus 9, 8, 7...";
840 suffix
= "No Habla Englais";
843 suffix
= ICUResourceBundleFactory::getDisplayName(id
, locale
, result
);
846 result
= prefix
+ suffix
;
851 const char* CalifornioLanguageFactory::californio
= "en_US_CA";
852 const char* CalifornioLanguageFactory::valley
= "en_US_CA_VALLEY";
853 const char* CalifornioLanguageFactory::surfer
= "en_US_CA_SURFER";
854 const char* CalifornioLanguageFactory::geek
= "en_US_CA_GEEK";
855 Hashtable
* CalifornioLanguageFactory::supportedIDs
= NULL
;
858 ICUServiceTest::testRBF()
860 // resource bundle factory.
861 UErrorCode status
= U_ZERO_ERROR
;
862 TestStringService service
;
863 service
.registerFactory(new ICUResourceBundleFactory(), status
);
865 // list all of the resources
867 UErrorCode status
= U_ZERO_ERROR
;
868 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
869 service
.getVisibleIDs(ids
, status
);
870 logln("all visible ids:");
871 for (int i
= 0; i
< ids
.size(); ++i
) {
872 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
877 // get all the display names of these resources
878 // this should be fast since the display names were cached.
880 UErrorCode status
= U_ZERO_ERROR
;
881 UVector
names(userv_deleteStringPair
, NULL
, status
);
882 service
.getDisplayNames(names
, Locale::getGermany(), status
);
883 logln("service display names for de_DE");
884 for (int i
= 0; i
< names
.size(); ++i
) {
885 const StringPair
* pair
= (const StringPair
*)names
[i
];
886 logln(" " + pair
->displayName
+ " --> " + pair
->id
);
890 service
.registerFactory(new CalifornioLanguageFactory(), status
);
892 // get all the display names of these resources
894 logln("californio language factory:");
895 const char* idNames
[] = {
896 CalifornioLanguageFactory::californio
,
897 CalifornioLanguageFactory::valley
,
898 CalifornioLanguageFactory::surfer
,
899 CalifornioLanguageFactory::geek
,
901 int32_t count
= sizeof(idNames
)/sizeof(idNames
[0]);
903 for (int i
= 0; i
< count
; ++i
) {
904 logln(UnicodeString("\n --- ") + idNames
[i
] + " ---");
906 UErrorCode status
= U_ZERO_ERROR
;
907 UVector
names(userv_deleteStringPair
, NULL
, status
);
908 service
.getDisplayNames(names
, idNames
[i
], status
);
909 for (int i
= 0; i
< names
.size(); ++i
) {
910 const StringPair
* pair
= (const StringPair
*)names
[i
];
911 logln(" " + pair
->displayName
+ " --> " + pair
->id
);
916 CalifornioLanguageFactory::cleanup();
919 class SimpleListener
: public ServiceListener
{
920 ICUServiceTest
* _test
;
925 SimpleListener(ICUServiceTest
* test
, const UnicodeString
& name
) : _test(test
), _n(0), _name(name
) {}
927 virtual void serviceChanged(const ICUService
& service
) const {
928 UnicodeString serviceName
= "listener ";
929 serviceName
.append(_name
);
930 serviceName
.append(" n++");
931 serviceName
.append(" service changed: " );
932 service
.getName(serviceName
);
933 _test
->logln(serviceName
);
938 ICUServiceTest::testNotification()
940 SimpleListener
one(this, "one");
941 SimpleListener
two(this, "two");
943 UErrorCode status
= U_ZERO_ERROR
;
945 logln("simple registration notification");
946 TestStringService ls
;
947 ls
.addListener(&one
, status
);
948 ls
.addListener(&two
, status
);
950 logln("registering foo... ");
951 ls
.registerInstance(new UnicodeString("Foo"), "en_FOO", status
);
952 logln("registering bar... ");
953 ls
.registerInstance(new UnicodeString("Bar"), "en_BAR", status
);
954 logln("getting foo...");
955 UnicodeString
* result
= (UnicodeString
*)ls
.get("en_FOO", status
);
959 logln("removing listener 2...");
960 ls
.removeListener(&two
, status
);
961 logln("registering baz...");
962 ls
.registerInstance(new UnicodeString("Baz"), "en_BAZ", status
);
963 logln("removing listener 1");
964 ls
.removeListener(&one
, status
);
965 logln("registering burp...");
966 ls
.registerInstance(new UnicodeString("Burp"), "en_BURP", status
);
968 // should only get one notification even if register multiple times
969 logln("... trying multiple registration");
970 ls
.addListener(&one
, status
);
971 ls
.addListener(&one
, status
);
972 ls
.addListener(&one
, status
);
973 ls
.addListener(&two
, status
);
974 ls
.registerInstance(new UnicodeString("Foo"), "en_FOO", status
);
975 logln("... registered foo");
978 // same thread, so we can't callback within notification, unlike Java
979 ServiceListener l3
= new ServiceListener() {
981 public void serviceChanged(ICUService s
) {
982 logln("listener 3 report " + n
++ + " service changed...");
983 if (s
.get("en_BOINK") == null
) { // don't recurse on ourselves!!!
984 logln("registering boink...");
985 s
.registerInstance("boink", "en_BOINK");
990 logln("registering boo...");
991 ls
.registerInstance("Boo", "en_BOO");
997 class TestStringLocaleService
: public ICULocaleService
{
999 virtual UObject
* cloneInstance(UObject
* instance
) const {
1000 return instance
? new UnicodeString(*(UnicodeString
*)instance
) : NULL
;
1004 void ICUServiceTest::testLocale() {
1005 UErrorCode status
= U_ZERO_ERROR
;
1006 TestStringLocaleService service
;
1008 UnicodeString
* root
= new UnicodeString("root");
1009 UnicodeString
* german
= new UnicodeString("german");
1010 UnicodeString
* germany
= new UnicodeString("german_Germany");
1011 UnicodeString
* japanese
= new UnicodeString("japanese");
1012 UnicodeString
* japan
= new UnicodeString("japanese_Japan");
1014 service
.registerInstance(root
, "", status
);
1015 service
.registerInstance(german
, "de", status
);
1016 service
.registerInstance(germany
, Locale::getGermany(), status
);
1017 service
.registerInstance(japanese
, "ja", status
);
1018 service
.registerInstance(japan
, Locale::getJapan(), status
);
1021 UErrorCode status
= U_ZERO_ERROR
;
1022 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", status
);
1023 confirmEqual("test de_US", german
, target
);
1028 UErrorCode status
= U_ZERO_ERROR
;
1029 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", LocaleKey::KIND_ANY
, status
);
1030 confirmEqual("test de_US 2", german
, target
);
1035 UErrorCode status
= U_ZERO_ERROR
;
1036 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", 1234, status
);
1037 confirmEqual("test de_US 3", german
, target
);
1042 UErrorCode status
= U_ZERO_ERROR
;
1043 Locale actualReturn
;
1044 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", &actualReturn
, status
);
1045 confirmEqual("test de_US 5", german
, target
);
1046 confirmEqual("test de_US 6", &actualReturn
, &Locale::getGerman());
1051 UErrorCode status
= U_ZERO_ERROR
;
1052 Locale actualReturn
;
1053 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", LocaleKey::KIND_ANY
, &actualReturn
, status
);
1054 confirmEqual("test de_US 7", &actualReturn
, &Locale::getGerman());
1059 UErrorCode status
= U_ZERO_ERROR
;
1060 Locale actualReturn
;
1061 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", 1234, &actualReturn
, status
);
1062 confirmEqual("test de_US 8", german
, target
);
1063 confirmEqual("test de_US 9", &actualReturn
, &Locale::getGerman());
1067 UnicodeString
* one
= new UnicodeString("one/de_US");
1068 UnicodeString
* two
= new UnicodeString("two/de_US");
1070 service
.registerInstance(one
, Locale("de_US"), 1, status
);
1071 service
.registerInstance(two
, Locale("de_US"), 2, status
);
1074 UErrorCode status
= U_ZERO_ERROR
;
1075 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", 1, status
);
1076 confirmEqual("test de_US kind 1", one
, target
);
1081 UErrorCode status
= U_ZERO_ERROR
;
1082 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", 2, status
);
1083 confirmEqual("test de_US kind 2", two
, target
);
1088 UErrorCode status
= U_ZERO_ERROR
;
1089 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", status
);
1090 confirmEqual("test de_US kind 3", german
, target
);
1095 UErrorCode status
= U_ZERO_ERROR
;
1096 UnicodeString english
= "en";
1097 Locale localeResult
;
1098 UnicodeString result
;
1099 LocaleKey
* lkey
= LocaleKey::createWithCanonicalFallback(&english
, NULL
, 1234, status
);
1100 logln("lkey prefix: " + lkey
->prefix(result
));
1102 logln("lkey descriptor: " + lkey
->currentDescriptor(result
));
1104 logln(UnicodeString("lkey current locale: ") + lkey
->currentLocale(localeResult
).getName());
1108 logln("lkey descriptor 2: " + lkey
->currentDescriptor(result
));
1112 logln("lkey descriptor 3: " + lkey
->currentDescriptor(result
));
1114 delete lkey
; // tentatively weiv
1118 UErrorCode status
= U_ZERO_ERROR
;
1119 UnicodeString
* target
= (UnicodeString
*)service
.get("za_PPP", status
);
1120 confirmEqual("test zappp", root
, target
);
1124 Locale loc
= Locale::getDefault();
1125 Locale::setDefault(Locale::getJapanese(), status
);
1127 UErrorCode status
= U_ZERO_ERROR
;
1128 UnicodeString
* target
= (UnicodeString
*)service
.get("za_PPP", status
);
1129 confirmEqual("test with ja locale", japanese
, target
);
1134 UErrorCode status
= U_ZERO_ERROR
;
1135 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
1136 service
.getVisibleIDs(ids
, status
);
1137 logln("all visible ids:");
1138 for (int i
= 0; i
< ids
.size(); ++i
) {
1139 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
1144 Locale::setDefault(loc
, status
);
1146 UErrorCode status
= U_ZERO_ERROR
;
1147 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
1148 service
.getVisibleIDs(ids
, status
);
1149 logln("all visible ids:");
1150 for (int i
= 0; i
< ids
.size(); ++i
) {
1151 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
1157 UErrorCode status
= U_ZERO_ERROR
;
1158 UnicodeString
* target
= (UnicodeString
*)service
.get("za_PPP", status
);
1159 confirmEqual("test with en locale", root
, target
);
1164 UErrorCode status
= U_ZERO_ERROR
;
1165 StringEnumeration
* locales
= service
.getAvailableLocales();
1167 confirmIdentical("test available locales", locales
->count(status
), 6);
1171 while ((p
= locales
->next(NULL
, status
))) {
1178 errln("could not create available locales");
1183 class WrapFactory
: public ICUServiceFactory
{
1185 static const UnicodeString
& getGreetingID() {
1186 if (greetingID
== NULL
) {
1187 greetingID
= new UnicodeString("greeting");
1192 static void cleanup() {
1197 UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const {
1198 if (U_SUCCESS(status
)) {
1200 if (key
.currentID(temp
).compare(getGreetingID()) == 0) {
1201 UnicodeString
* previous
= (UnicodeString
*)service
->getKey((ICUServiceKey
&)key
, NULL
, this, status
);
1203 previous
->insert(0, "A different greeting: \"");
1204 previous
->append("\"");
1212 void updateVisibleIDs(Hashtable
& result
, UErrorCode
& status
) const {
1213 if (U_SUCCESS(status
)) {
1214 result
.put("greeting", (void*)this, status
);
1218 UnicodeString
& getDisplayName(const UnicodeString
& id
, const Locale
& /* locale */, UnicodeString
& result
) const {
1219 result
.append("wrap '");
1226 * UObject boilerplate.
1228 virtual UClassID
getDynamicClassID() const {
1229 return getStaticClassID();
1232 static UClassID
getStaticClassID() {
1233 return (UClassID
)&fgClassID
;
1237 static const char fgClassID
;
1238 static UnicodeString
* greetingID
;
1241 UnicodeString
* WrapFactory::greetingID
= NULL
;
1242 const char WrapFactory::fgClassID
= '\0';
1245 ICUServiceTest::testWrapFactory()
1247 UnicodeString
* greeting
= new UnicodeString("Hello There");
1248 UnicodeString greetingID
= "greeting";
1249 UErrorCode status
= U_ZERO_ERROR
;
1250 TestStringService service
;
1251 service
.registerInstance(greeting
, greetingID
, status
);
1254 UErrorCode status
= U_ZERO_ERROR
;
1255 UnicodeString
* result
= (UnicodeString
*)service
.get(greetingID
, status
);
1257 logln("test one: " + *result
);
1262 service
.registerFactory(new WrapFactory(), status
);
1264 UErrorCode status
= U_ZERO_ERROR
;
1265 UnicodeString
* result
= (UnicodeString
*)service
.get(greetingID
, status
);
1266 UnicodeString target
= "A different greeting: \"Hello There\"";
1267 confirmEqual("wrap test: ", result
, &target
);
1271 WrapFactory::cleanup();
1274 // misc coverage tests
1275 void ICUServiceTest::testCoverage()
1280 ICUServiceKey
key("foobar");
1281 logln("ID: " + key
.getID());
1282 logln("canonicalID: " + key
.canonicalID(temp
));
1283 logln("currentID: " + key
.currentID(temp
.remove()));
1284 logln("has fallback: " + UnicodeString(key
.fallback() ? "true" : "false"));
1286 if (key
.getDynamicClassID() != ICUServiceKey::getStaticClassID()) {
1287 errln("service key rtt failed.");
1293 UErrorCode status
= U_ZERO_ERROR
;
1295 UnicodeString
* obj
= new UnicodeString("An Object");
1296 SimpleFactory
* sf
= new SimpleFactory(obj
, "object");
1299 logln(sf
->getDisplayName("object", Locale::getDefault(), temp
));
1301 if (sf
->getDynamicClassID() != SimpleFactory::getStaticClassID()) {
1302 errln("simple factory rtti failed.");
1306 TestStringService service
;
1307 service
.registerFactory(sf
, status
);
1310 UnicodeString
* result
= (UnicodeString
*)service
.get("object", status
);
1312 logln("object is: " + *result
);
1315 errln("could not get object");
1324 UnicodeString
primary("en_US");
1325 UnicodeString
fallback("ja_JP");
1326 UErrorCode status
= U_ZERO_ERROR
;
1327 LocaleKey
* key
= LocaleKey::createWithCanonicalFallback(&primary
, &fallback
, status
);
1329 if (key
->getDynamicClassID() != LocaleKey::getStaticClassID()) {
1330 errln("localekey rtti error");
1333 if (!key
->isFallbackOf("en_US_FOOBAR")) {
1334 errln("localekey should be fallback for en_US_FOOBAR");
1336 if (!key
->isFallbackOf("en_US")) {
1337 errln("localekey should be fallback for en_US");
1339 if (key
->isFallbackOf("en")) {
1340 errln("localekey should not be fallback for en");
1345 logln(UnicodeString("current locale: ") + key
->currentLocale(loc
).getName());
1346 logln(UnicodeString("canonical locale: ") + key
->canonicalLocale(loc
).getName());
1347 logln(UnicodeString("is fallback of en: ") + (key
->isFallbackOf("en") ? "true" : " false"));
1348 } while (key
->fallback());
1352 key
= LocaleKey::createWithCanonicalFallback(&primary
, &fallback
, status
);
1354 UnicodeString result
;
1355 LKFSubclass
lkf(TRUE
); // empty
1358 UObject
*obj
= lkf
.create(*key
, NULL
, status
);
1359 logln("obj: " + UnicodeString(obj
? "obj" : "null"));
1360 logln(lkf
.getDisplayName("en_US", Locale::getDefault(), result
));
1361 lkf
.updateVisibleIDs(table
, status
);
1363 if (table
.count() != 1) {
1364 errln("visible IDs does not contain en_US");
1367 LKFSubclass
invisibleLKF(FALSE
);
1368 obj
= lkf
.create(*key
, NULL
, status
);
1369 logln("obj: " + UnicodeString(obj
? "obj" : "null"));
1370 logln(invisibleLKF
.getDisplayName("en_US", Locale::getDefault(), result
.remove()));
1371 invisibleLKF
.updateVisibleIDs(table
, status
);
1372 if (table
.count() != 0) {
1373 errln("visible IDs contains en_US");
1381 // ResourceBundleFactory
1382 ICUResourceBundleFactory rbf
= new ICUResourceBundleFactory();
1383 logln("RB: " + rbf
.create(lkey
, null
));
1386 ICUNotifier nf
= new ICUNSubclass();
1388 nf
.addListener(null
);
1389 errln("added null listener");
1391 catch (NullPointerException e
) {
1392 logln(e
.getMessage());
1394 catch (Exception e
) {
1395 errln("got wrong exception");
1399 nf
.addListener(new WrongListener());
1400 errln("added wrong listener");
1402 catch (InternalError e
) {
1403 logln(e
.getMessage());
1405 catch (Exception e
) {
1406 errln("got wrong exception");
1410 nf
.removeListener(null
);
1411 errln("removed null listener");
1413 catch (NullPointerException e
) {
1414 logln(e
.getMessage());
1416 catch (Exception e
) {
1417 errln("got wrong exception");
1420 nf
.removeListener(new MyListener());
1422 nf
.addListener(new MyListener());
1423 nf
.removeListener(new MyListener());
1428 /* !UCONFIG_NO_SERVICE */