2 *******************************************************************************
3 * Copyright (C) 2001-2008, 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 // This factory does nothing
37 class LKFSubclass0
: public LocaleKeyFactory
{
40 : LocaleKeyFactory(VISIBLE
, "LKFSubclass0")
45 class LKFSubclass
: public LocaleKeyFactory
{
49 LKFSubclass(UBool visible
)
50 : LocaleKeyFactory(visible
? VISIBLE
: INVISIBLE
, "LKFSubclass")
52 UErrorCode status
= U_ZERO_ERROR
;
53 table
.put("en_US", this, status
);
57 virtual const Hashtable
* getSupportedIDs(UErrorCode
&/*status*/) const {
62 class Integer
: public UObject
{
66 Integer(int32_t val
) : _val(val
) {
69 Integer(const Integer
& rhs
) : UObject(rhs
), _val(rhs
._val
) {
76 * UObject boilerplate.
78 static UClassID
getStaticClassID() {
79 return (UClassID
)&fgClassID
;
82 virtual UClassID
getDynamicClassID() const {
83 return getStaticClassID();
86 virtual UBool
operator==(const UObject
& other
) const
88 return other
.getDynamicClassID() == getStaticClassID() &&
89 _val
== ((Integer
&)other
)._val
;
93 virtual UnicodeString
& debug(UnicodeString
& result
) const {
95 result
.append(" val: ");
100 virtual UnicodeString
& debugClass(UnicodeString
& result
) const {
101 return result
.append("Integer");
105 static const char fgClassID
;
108 const char Integer::fgClassID
= '\0';
111 class TestIntegerService
: public ICUService
{
113 ICUServiceKey
* createKey(const UnicodeString
* id
, UErrorCode
& status
) const {
114 return LocaleKey::createWithCanonicalFallback(id
, NULL
, status
); // no fallback locale
117 virtual ICUServiceFactory
* createSimpleFactory(UObject
* obj
, const UnicodeString
& id
, UBool visible
, UErrorCode
& status
)
119 if (U_SUCCESS(status
) && obj
&& obj
->getDynamicClassID() == Integer::getStaticClassID()) {
120 return new SimpleFactory((Integer
*)obj
, id
, visible
);
125 virtual UObject
* cloneInstance(UObject
* instance
) const {
126 return instance
? new Integer(*(Integer
*)instance
) : NULL
;
131 ICUServiceTest::ICUServiceTest() {
134 ICUServiceTest::~ICUServiceTest() {
138 ICUServiceTest::runIndexedTest(int32_t index
, UBool exec
, const char* &name
,
142 TESTCASE(0,testAPI_One
);
143 TESTCASE(1,testAPI_Two
);
145 TESTCASE(3,testNotification
);
146 TESTCASE(4,testLocale
);
147 TESTCASE(5,testWrapFactory
);
148 TESTCASE(6,testCoverage
);
149 default: name
= ""; break;
153 UnicodeString
append(UnicodeString
& result
, const UObject
* obj
)
157 result
.append("NULL");
159 UClassID id
= obj
->getDynamicClassID();
160 if (id
== UnicodeString::getStaticClassID()) {
161 result
.append(*(UnicodeString
*)obj
);
162 } else if (id
== Locale::getStaticClassID()) {
163 result
.append(((Locale
*)obj
)->getName());
164 } else if (id
== Integer::getStaticClassID()) {
165 sprintf(buffer
, "%d", (int)((Integer
*)obj
)->_val
);
166 result
.append(buffer
);
168 sprintf(buffer
, "%p", (const void*)obj
);
169 result
.append(buffer
);
176 ICUServiceTest::lrmsg(UnicodeString
& result
, const UnicodeString
& message
, const UObject
* lhs
, const UObject
* rhs
) const
178 result
.append(message
);
179 result
.append(" lhs: ");
181 result
.append(", rhs: ");
187 ICUServiceTest::confirmBoolean(const UnicodeString
& message
, UBool val
)
198 ICUServiceTest::confirmEqual(const UnicodeString
& message
, const UObject
* lhs
, const UObject
* rhs
)
200 UBool equ
= (lhs
== NULL
)
202 : (rhs
!= NULL
&& lhs
->operator==(*rhs
));
205 lrmsg(temp
, message
, lhs
, rhs
);
215 ICUServiceTest::confirmEqual(const UnicodeString
& message
, const Integer
* lhs
, const Integer
* rhs
)
217 UBool equ
= (lhs
== NULL
)
219 : (rhs
!= NULL
&& lhs
->operator==(*rhs
));
222 lrmsg(temp
, message
, lhs
, rhs
);
232 ICUServiceTest::confirmEqual(const UnicodeString
& message
, const UnicodeString
* lhs
, const UnicodeString
* rhs
)
234 UBool equ
= (lhs
== NULL
)
236 : (rhs
!= NULL
&& lhs
->operator==(*rhs
));
239 lrmsg(temp
, message
, lhs
, rhs
);
249 ICUServiceTest::confirmEqual(const UnicodeString
& message
, const Locale
* lhs
, const Locale
* rhs
)
251 UBool equ
= (lhs
== NULL
)
253 : (rhs
!= NULL
&& lhs
->operator==(*rhs
));
256 lrmsg(temp
, message
, lhs
, rhs
);
268 ICUServiceTest::confirmStringsEqual(const UnicodeString
& message
, const UnicodeString
& lhs
, const UnicodeString
& rhs
)
270 UBool equ
= lhs
== rhs
;
272 UnicodeString temp
= message
;
273 temp
.append(" lhs: ");
275 temp
.append(" rhs: ");
287 ICUServiceTest::confirmIdentical(const UnicodeString
& message
, const UObject
* lhs
, const UObject
*rhs
)
290 lrmsg(temp
, message
, lhs
, rhs
);
299 ICUServiceTest::confirmIdentical(const UnicodeString
& message
, int32_t lhs
, int32_t rhs
)
302 logln(message
+ " lhs: " + lhs
+ " rhs: " + rhs
);
304 errln(message
+ " lhs: " + lhs
+ " rhs: " + rhs
);
309 ICUServiceTest::msgstr(const UnicodeString
& message
, UObject
* obj
, UBool err
)
312 UnicodeString
* str
= (UnicodeString
*)obj
;
313 logln(message
+ *str
);
316 errln("Error " + message
+ "string is NULL");
321 ICUServiceTest::testAPI_One()
323 // create a service using locale keys,
324 TestIntegerService service
;
326 // register an object with one locale,
327 // search for an object with a more specific locale
328 // should return the original object
329 UErrorCode status
= U_ZERO_ERROR
;
330 Integer
* singleton0
= new Integer(0);
331 service
.registerInstance(singleton0
, "en_US", status
);
333 UErrorCode status
= U_ZERO_ERROR
;
334 Integer
* result
= (Integer
*)service
.get("en_US_FOO", status
);
335 confirmEqual("1) en_US_FOO -> en_US", result
, singleton0
);
339 // register a new object with the more specific locale
340 // search for an object with that locale
341 // should return the new object
342 Integer
* singleton1
= new Integer(1);
343 service
.registerInstance(singleton1
, "en_US_FOO", status
);
345 UErrorCode status
= U_ZERO_ERROR
;
346 Integer
* result
= (Integer
*)service
.get("en_US_FOO", status
);
347 confirmEqual("2) en_US_FOO -> en_US_FOO", result
, singleton1
);
351 // search for an object that falls back to the first registered locale
353 UErrorCode status
= U_ZERO_ERROR
;
354 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
355 confirmEqual("3) en_US_BAR -> en_US", result
, singleton0
);
359 // get a list of the factories, should be two
361 confirmIdentical("4) factory size", service
.countFactories(), 2);
364 // register a new object with yet another locale
365 Integer
* singleton2
= new Integer(2);
366 service
.registerInstance(singleton2
, "en", status
);
368 confirmIdentical("5) factory size", service
.countFactories(), 3);
371 // search for an object with the new locale
372 // stack of factories is now en, en_US_FOO, en_US
373 // search for en_US should still find en_US object
375 UErrorCode status
= U_ZERO_ERROR
;
376 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
377 confirmEqual("6) en_US_BAR -> en_US", result
, singleton0
);
381 // register a new object with an old id, should hide earlier factory using this id, but leave it there
382 Integer
* singleton3
= new Integer(3);
383 URegistryKey s3key
= service
.registerInstance(singleton3
, "en_US", status
);
385 confirmIdentical("9) factory size", service
.countFactories(), 4);
388 // should get data from that new factory
390 UErrorCode status
= U_ZERO_ERROR
;
391 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
392 confirmEqual("10) en_US_BAR -> (3)", result
, singleton3
);
396 // remove new factory
397 // should have fewer factories again
400 UErrorCode status
= U_ZERO_ERROR
;
401 service
.unregister(s3key
, status
);
402 confirmIdentical("11) factory size", service
.countFactories(), 3);
405 // should get original data again after remove factory
407 UErrorCode status
= U_ZERO_ERROR
;
408 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
409 confirmEqual("12) en_US_BAR -> (3)", result
, singleton0
);
413 // shouldn't find unregistered ids
415 UErrorCode status
= U_ZERO_ERROR
;
416 Integer
* result
= (Integer
*)service
.get("foo", status
);
417 confirmIdentical("13) foo -> null", result
, NULL
);
421 // should find non-canonical strings
423 UnicodeString resultID
;
424 UErrorCode status
= U_ZERO_ERROR
;
425 Integer
* result
= (Integer
*)service
.get("EN_us_fOo", &resultID
, status
);
426 confirmEqual("14a) find-non-canonical", result
, singleton1
);
427 confirmStringsEqual("14b) find non-canonical", resultID
, "en_US_FOO");
431 // should be able to register non-canonical strings and get them canonicalized
432 Integer
* singleton4
= new Integer(4);
433 service
.registerInstance(singleton4
, "eN_ca_dUde", status
);
435 UnicodeString resultID
;
436 UErrorCode status
= U_ZERO_ERROR
;
437 Integer
* result
= (Integer
*)service
.get("En_Ca_DuDe", &resultID
, status
);
438 confirmEqual("15a) find-non-canonical", result
, singleton4
);
439 confirmStringsEqual("15b) register non-canonical", resultID
, "en_CA_DUDE");
443 // should be able to register invisible factories, these will not
444 // be visible by default, but if you know the secret password you
445 // can still access these services...
446 Integer
* singleton5
= new Integer(5);
447 service
.registerInstance(singleton5
, "en_US_BAR", FALSE
, status
);
449 UErrorCode status
= U_ZERO_ERROR
;
450 Integer
* result
= (Integer
*)service
.get("en_US_BAR", status
);
451 confirmEqual("17) get invisible", result
, singleton5
);
455 // should not be able to locate invisible services
457 UErrorCode status
= U_ZERO_ERROR
;
458 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, status
);
459 service
.getVisibleIDs(ids
, status
);
460 UnicodeString target
= "en_US_BAR";
461 confirmBoolean("18) find invisible", !ids
.contains(&target
));
464 // clear factory and caches
466 confirmBoolean("19) is default", service
.isDefault());
470 ******************************************************************
472 class TestStringSimpleKeyService
: public ICUService
{
475 virtual ICUServiceFactory
* createSimpleFactory(UObject
* obj
, const UnicodeString
& id
, UBool visible
, UErrorCode
& status
)
477 // We could put this type check into ICUService itself, but we'd still
478 // have to implement cloneInstance. Otherwise we could just tell the service
479 // what the object type is when we create it, and the default implementation
480 // could handle everything for us. Phooey.
481 if (obj
&& obj
->getDynamicClassID() == UnicodeString::getStaticClassID()) {
482 return ICUService::createSimpleFactory(obj
, id
, visible
, status
);
487 virtual UObject
* cloneInstance(UObject
* instance
) const {
488 return instance
? new UnicodeString(*(UnicodeString
*)instance
) : NULL
;
492 class TestStringService
: public ICUService
{
494 ICUServiceKey
* createKey(const UnicodeString
* id
, UErrorCode
& status
) const {
495 return LocaleKey::createWithCanonicalFallback(id
, NULL
, status
); // no fallback locale
498 virtual ICUServiceFactory
* createSimpleFactory(UObject
* obj
, const UnicodeString
& id
, UBool visible
, UErrorCode
& /* status */)
500 if (obj
&& obj
->getDynamicClassID() == UnicodeString::getStaticClassID()) {
501 return new SimpleFactory((UnicodeString
*)obj
, id
, visible
);
506 virtual UObject
* cloneInstance(UObject
* instance
) const {
507 return instance
? new UnicodeString(*(UnicodeString
*)instance
) : NULL
;
511 // this creates a string for any id, but doesn't report anything
512 class AnonymousStringFactory
: public ICUServiceFactory
515 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* /* service */, UErrorCode
& /* status */) const {
516 return new UnicodeString(key
.getID());
519 virtual void updateVisibleIDs(Hashtable
& /*result*/, UErrorCode
& /*status*/) const {
523 virtual UnicodeString
& getDisplayName(const UnicodeString
& /*id*/, const Locale
& /*locale*/, UnicodeString
& result
) const {
528 static UClassID
getStaticClassID() {
529 return (UClassID
)&fgClassID
;
532 virtual UClassID
getDynamicClassID() const {
533 return getStaticClassID();
537 static const char fgClassID
;
540 const char AnonymousStringFactory::fgClassID
= '\0';
542 class TestMultipleKeyStringFactory
: public ICUServiceFactory
{
545 UnicodeString _factoryID
;
548 TestMultipleKeyStringFactory(const UnicodeString ids
[], int32_t count
, const UnicodeString
& factoryID
)
549 : _status(U_ZERO_ERROR
)
550 , _ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, count
, _status
)
551 , _factoryID(factoryID
+ ": ")
553 for (int i
= 0; i
< count
; ++i
) {
554 _ids
.addElement(new UnicodeString(ids
[i
]), _status
);
558 ~TestMultipleKeyStringFactory() {
561 UObject
* create(const ICUServiceKey
& key
, const ICUService
* /* service */, UErrorCode
& status
) const {
562 if (U_FAILURE(status
)) {
567 if (U_SUCCESS(_status
)) {
568 if (_ids
.contains(&temp
)) {
569 return new UnicodeString(_factoryID
+ temp
);
577 void updateVisibleIDs(Hashtable
& result
, UErrorCode
& status
) const {
578 if (U_SUCCESS(_status
)) {
579 for (int32_t i
= 0; i
< _ids
.size(); ++i
) {
580 result
.put(*(UnicodeString
*)_ids
[i
], (void*)this, status
);
585 UnicodeString
& getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const {
586 if (U_SUCCESS(_status
) && _ids
.contains((void*)&id
)) {
588 UErrorCode status
= U_ZERO_ERROR
;
589 int32_t len
= id
.extract(buffer
, sizeof(buffer
), NULL
, status
);
590 if (U_SUCCESS(status
)) {
591 if (len
== sizeof(buffer
)) {
595 Locale loc
= Locale::createFromName(buffer
);
596 loc
.getDisplayName(locale
, result
);
600 result
.setToBogus(); // shouldn't happen
604 static UClassID
getStaticClassID() {
605 return (UClassID
)&fgClassID
;
608 virtual UClassID
getDynamicClassID() const {
609 return getStaticClassID();
613 static const char fgClassID
;
616 const char TestMultipleKeyStringFactory::fgClassID
= '\0';
619 ICUServiceTest::testAPI_Two()
621 UErrorCode status
= U_ZERO_ERROR
;
622 TestStringService service
;
623 service
.registerFactory(new AnonymousStringFactory(), status
);
625 // anonymous factory will still handle the id
627 UErrorCode status
= U_ZERO_ERROR
;
628 const UnicodeString en_US
= "en_US";
629 UnicodeString
* result
= (UnicodeString
*)service
.get(en_US
, status
);
630 confirmEqual("21) locale", result
, &en_US
);
634 // still normalizes id
636 UErrorCode status
= U_ZERO_ERROR
;
637 const UnicodeString en_US_BAR
= "en_US_BAR";
638 UnicodeString resultID
;
639 UnicodeString
* result
= (UnicodeString
*)service
.get("EN_us_bar", &resultID
, status
);
640 confirmEqual("22) locale", &resultID
, &en_US_BAR
);
644 // we can override for particular ids
645 UnicodeString
* singleton0
= new UnicodeString("Zero");
646 service
.registerInstance(singleton0
, "en_US_BAR", status
);
648 UErrorCode status
= U_ZERO_ERROR
;
649 UnicodeString
* result
= (UnicodeString
*)service
.get("en_US_BAR", status
);
650 confirmEqual("23) override super", result
, singleton0
);
654 // empty service should not recognize anything
657 UErrorCode status
= U_ZERO_ERROR
;
658 UnicodeString
* result
= (UnicodeString
*)service
.get("en_US", status
);
659 confirmIdentical("24) empty", result
, NULL
);
662 // create a custom multiple key factory
664 UnicodeString xids
[] = {
670 int32_t count
= sizeof(xids
)/sizeof(UnicodeString
);
672 ICUServiceFactory
* f
= new TestMultipleKeyStringFactory(xids
, count
, "Later");
673 service
.registerFactory(f
, status
);
676 // iterate over the visual ids returned by the multiple factory
678 UErrorCode status
= U_ZERO_ERROR
;
679 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
680 service
.getVisibleIDs(ids
, status
);
681 for (int i
= 0; i
< ids
.size(); ++i
) {
682 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
683 UnicodeString
* result
= (UnicodeString
*)service
.get(*id
, status
);
685 logln(" " + *id
+ " --> " + *result
);
688 errln("could not find " + *id
);
692 confirmIdentical("25) visible ids", ids
.size(), 4);
695 // iterate over the display names
697 UErrorCode status
= U_ZERO_ERROR
;
698 UVector
names(status
);
699 service
.getDisplayNames(names
, status
);
700 for (int i
= 0; i
< names
.size(); ++i
) {
701 const StringPair
* pair
= (const StringPair
*)names
[i
];
702 logln(" " + pair
->displayName
+ " --> " + pair
->id
);
704 confirmIdentical("26) display names", names
.size(), 4);
707 // no valid display name
710 service
.getDisplayName("en_US_VALLEY_GEEK", name
);
711 confirmBoolean("27) get display name", name
.isBogus());
716 service
.getDisplayName("en_US_SURFER_DUDE", name
, Locale::getEnglish());
717 confirmStringsEqual("28) get display name", name
, "English (United States, SURFER_DUDE)");
720 // register another multiple factory
722 UnicodeString xids
[] = {
726 "en_US_SILICON_GEEK",
728 int32_t count
= sizeof(xids
)/sizeof(UnicodeString
);
730 ICUServiceFactory
* f
= new TestMultipleKeyStringFactory(xids
, count
, "Rad dude");
731 service
.registerFactory(f
, status
);
734 // this time, we have seven display names
735 // Rad dude's surfer gal 'replaces' Later's surfer gal
737 UErrorCode status
= U_ZERO_ERROR
;
738 UVector
names(status
);
739 service
.getDisplayNames(names
, Locale("es"), status
);
740 for (int i
= 0; i
< names
.size(); ++i
) {
741 const StringPair
* pair
= (const StringPair
*)names
[i
];
742 logln(" " + pair
->displayName
+ " --> " + pair
->id
);
744 confirmIdentical("29) display names", names
.size(), 7);
747 // we should get the display name corresponding to the actual id
748 // returned by the id we used.
750 UErrorCode status
= U_ZERO_ERROR
;
751 UnicodeString actualID
;
752 UnicodeString id
= "en_us_surfer_gal";
753 UnicodeString
* gal
= (UnicodeString
*)service
.get(id
, &actualID
, status
);
755 UnicodeString displayName
;
756 logln("actual id: " + actualID
);
757 service
.getDisplayName(actualID
, displayName
, Locale::getEnglish());
758 logln("found actual: " + *gal
+ " with display name: " + displayName
);
759 confirmBoolean("30) found display name for actual", !displayName
.isBogus());
761 service
.getDisplayName(id
, displayName
, Locale::getEnglish());
762 logln("found actual: " + *gal
+ " with display name: " + displayName
);
763 confirmBoolean("31) found display name for query", displayName
.isBogus());
767 errln("30) service could not find entry for " + id
);
771 // this should be handled by the 'dude' factory, since it overrides en_US_SURFER.
773 UErrorCode status
= U_ZERO_ERROR
;
774 UnicodeString actualID
;
775 UnicodeString id
= "en_US_SURFER_BOZO";
776 UnicodeString
* bozo
= (UnicodeString
*)service
.get(id
, &actualID
, status
);
778 UnicodeString displayName
;
779 service
.getDisplayName(actualID
, displayName
, Locale::getEnglish());
780 logln("found actual: " + *bozo
+ " with display name: " + displayName
);
781 confirmBoolean("32) found display name for actual", !displayName
.isBogus());
783 service
.getDisplayName(id
, displayName
, Locale::getEnglish());
784 logln("found actual: " + *bozo
+ " with display name: " + displayName
);
785 confirmBoolean("33) found display name for query", displayName
.isBogus());
789 errln("32) service could not find entry for " + id
);
793 // certainly not default...
795 confirmBoolean("34) is default ", !service
.isDefault());
799 UErrorCode status
= U_ZERO_ERROR
;
800 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
801 service
.getVisibleIDs(ids
, status
);
802 for (int i
= 0; i
< ids
.size(); ++i
) {
803 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
804 msgstr(*id
+ "? ", service
.get(*id
, status
));
807 logstr("valleygirl? ", service
.get("en_US_VALLEY_GIRL", status
));
808 logstr("valleyboy? ", service
.get("en_US_VALLEY_BOY", status
));
809 logstr("valleydude? ", service
.get("en_US_VALLEY_DUDE", status
));
810 logstr("surfergirl? ", service
.get("en_US_SURFER_GIRL", status
));
815 class CalifornioLanguageFactory
: public ICUResourceBundleFactory
818 static const char* californio
; // = "en_US_CA";
819 static const char* valley
; // = californio ## "_VALLEY";
820 static const char* surfer
; // = californio ## "_SURFER";
821 static const char* geek
; // = californio ## "_GEEK";
822 static Hashtable
* supportedIDs
; // = NULL;
824 static void cleanup(void) {
829 const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
831 if (supportedIDs
== NULL
) {
832 Hashtable
* table
= new Hashtable();
833 table
->put(UnicodeString(californio
), (void*)table
, status
);
834 table
->put(UnicodeString(valley
), (void*)table
, status
);
835 table
->put(UnicodeString(surfer
), (void*)table
, status
);
836 table
->put(UnicodeString(geek
), (void*)table
, status
);
838 // not necessarily atomic, but this is a test...
839 supportedIDs
= table
;
844 UnicodeString
& getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const
846 UnicodeString prefix
= "";
847 UnicodeString suffix
= "";
848 UnicodeString ls
= locale
.getName();
849 if (LocaleUtility::isFallbackOf(californio
, ls
)) {
850 if (!ls
.caseCompare(valley
, 0)) {
851 prefix
= "Like, you know, it's so totally ";
852 } else if (!ls
.caseCompare(surfer
, 0)) {
853 prefix
= "Dude, it's ";
854 } else if (!ls
.caseCompare(geek
, 0)) {
855 prefix
= "I'd estimate it is approximately ";
857 prefix
= "Huh? Maybe ";
860 if (LocaleUtility::isFallbackOf(californio
, id
)) {
861 if (!id
.caseCompare(valley
, 0)) {
862 suffix
= "like the Valley, you know? Let's go to the mall!";
863 } else if (!id
.caseCompare(surfer
, 0)) {
864 suffix
= "time to hit those gnarly waves, Dude!!!";
865 } else if (!id
.caseCompare(geek
, 0)) {
866 suffix
= "all systems go. T-Minus 9, 8, 7...";
868 suffix
= "No Habla Englais";
871 suffix
= ICUResourceBundleFactory::getDisplayName(id
, locale
, result
);
874 result
= prefix
+ suffix
;
879 const char* CalifornioLanguageFactory::californio
= "en_US_CA";
880 const char* CalifornioLanguageFactory::valley
= "en_US_CA_VALLEY";
881 const char* CalifornioLanguageFactory::surfer
= "en_US_CA_SURFER";
882 const char* CalifornioLanguageFactory::geek
= "en_US_CA_GEEK";
883 Hashtable
* CalifornioLanguageFactory::supportedIDs
= NULL
;
886 ICUServiceTest::testRBF()
888 // resource bundle factory.
889 UErrorCode status
= U_ZERO_ERROR
;
890 TestStringService service
;
891 service
.registerFactory(new ICUResourceBundleFactory(), status
);
893 // list all of the resources
895 UErrorCode status
= U_ZERO_ERROR
;
896 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
897 service
.getVisibleIDs(ids
, status
);
898 logln("all visible ids:");
899 for (int i
= 0; i
< ids
.size(); ++i
) {
900 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
905 // get all the display names of these resources
906 // this should be fast since the display names were cached.
908 UErrorCode status
= U_ZERO_ERROR
;
909 UVector
names(status
);
910 service
.getDisplayNames(names
, Locale::getGermany(), status
);
911 logln("service display names for de_DE");
912 for (int i
= 0; i
< names
.size(); ++i
) {
913 const StringPair
* pair
= (const StringPair
*)names
[i
];
914 logln(" " + pair
->displayName
+ " --> " + pair
->id
);
918 service
.registerFactory(new CalifornioLanguageFactory(), status
);
920 // get all the display names of these resources
922 logln("californio language factory:");
923 const char* idNames
[] = {
924 CalifornioLanguageFactory::californio
,
925 CalifornioLanguageFactory::valley
,
926 CalifornioLanguageFactory::surfer
,
927 CalifornioLanguageFactory::geek
,
929 int32_t count
= sizeof(idNames
)/sizeof(idNames
[0]);
931 for (int i
= 0; i
< count
; ++i
) {
932 logln(UnicodeString("\n --- ") + idNames
[i
] + " ---");
934 UErrorCode status
= U_ZERO_ERROR
;
935 UVector
names(status
);
936 service
.getDisplayNames(names
, idNames
[i
], status
);
937 for (int i
= 0; i
< names
.size(); ++i
) {
938 const StringPair
* pair
= (const StringPair
*)names
[i
];
939 logln(" " + pair
->displayName
+ " --> " + pair
->id
);
944 CalifornioLanguageFactory::cleanup();
947 class SimpleListener
: public ServiceListener
{
948 ICUServiceTest
* _test
;
953 SimpleListener(ICUServiceTest
* test
, const UnicodeString
& name
) : _test(test
), _n(0), _name(name
) {}
955 virtual void serviceChanged(const ICUService
& service
) const {
956 UnicodeString serviceName
= "listener ";
957 serviceName
.append(_name
);
958 serviceName
.append(" n++");
959 serviceName
.append(" service changed: " );
960 service
.getName(serviceName
);
961 _test
->logln(serviceName
);
966 ICUServiceTest::testNotification()
968 SimpleListener
one(this, "one");
969 SimpleListener
two(this, "two");
971 UErrorCode status
= U_ZERO_ERROR
;
973 logln("simple registration notification");
974 TestStringService ls
;
975 ls
.addListener(&one
, status
);
976 ls
.addListener(&two
, status
);
978 logln("registering foo... ");
979 ls
.registerInstance(new UnicodeString("Foo"), "en_FOO", status
);
980 logln("registering bar... ");
981 ls
.registerInstance(new UnicodeString("Bar"), "en_BAR", status
);
982 logln("getting foo...");
983 UnicodeString
* result
= (UnicodeString
*)ls
.get("en_FOO", status
);
987 logln("removing listener 2...");
988 ls
.removeListener(&two
, status
);
989 logln("registering baz...");
990 ls
.registerInstance(new UnicodeString("Baz"), "en_BAZ", status
);
991 logln("removing listener 1");
992 ls
.removeListener(&one
, status
);
993 logln("registering burp...");
994 ls
.registerInstance(new UnicodeString("Burp"), "en_BURP", status
);
996 // should only get one notification even if register multiple times
997 logln("... trying multiple registration");
998 ls
.addListener(&one
, status
);
999 ls
.addListener(&one
, status
);
1000 ls
.addListener(&one
, status
);
1001 ls
.addListener(&two
, status
);
1002 ls
.registerInstance(new UnicodeString("Foo"), "en_FOO", status
);
1003 logln("... registered foo");
1006 // same thread, so we can't callback within notification, unlike Java
1007 ServiceListener l3
= new ServiceListener() {
1009 public void serviceChanged(ICUService s
) {
1010 logln("listener 3 report " + n
++ + " service changed...");
1011 if (s
.get("en_BOINK") == null
) { // don't recurse on ourselves!!!
1012 logln("registering boink...");
1013 s
.registerInstance("boink", "en_BOINK");
1018 logln("registering boo...");
1019 ls
.registerInstance("Boo", "en_BOO");
1025 class TestStringLocaleService
: public ICULocaleService
{
1027 virtual UObject
* cloneInstance(UObject
* instance
) const {
1028 return instance
? new UnicodeString(*(UnicodeString
*)instance
) : NULL
;
1032 void ICUServiceTest::testLocale() {
1033 UErrorCode status
= U_ZERO_ERROR
;
1034 TestStringLocaleService service
;
1036 UnicodeString
* root
= new UnicodeString("root");
1037 UnicodeString
* german
= new UnicodeString("german");
1038 UnicodeString
* germany
= new UnicodeString("german_Germany");
1039 UnicodeString
* japanese
= new UnicodeString("japanese");
1040 UnicodeString
* japan
= new UnicodeString("japanese_Japan");
1042 service
.registerInstance(root
, "", status
);
1043 service
.registerInstance(german
, "de", status
);
1044 service
.registerInstance(germany
, Locale::getGermany(), status
);
1045 service
.registerInstance(japanese
, (UnicodeString
)"ja", TRUE
, status
);
1046 service
.registerInstance(japan
, Locale::getJapan(), status
);
1049 UErrorCode status
= U_ZERO_ERROR
;
1050 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", status
);
1051 confirmEqual("test de_US", german
, target
);
1056 UErrorCode status
= U_ZERO_ERROR
;
1057 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", LocaleKey::KIND_ANY
, status
);
1058 confirmEqual("test de_US 2", german
, target
);
1063 UErrorCode status
= U_ZERO_ERROR
;
1064 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", 1234, status
);
1065 confirmEqual("test de_US 3", german
, target
);
1070 UErrorCode status
= U_ZERO_ERROR
;
1071 Locale actualReturn
;
1072 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", &actualReturn
, status
);
1073 confirmEqual("test de_US 5", german
, target
);
1074 confirmEqual("test de_US 6", &actualReturn
, &Locale::getGerman());
1079 UErrorCode status
= U_ZERO_ERROR
;
1080 Locale actualReturn
;
1081 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", LocaleKey::KIND_ANY
, &actualReturn
, status
);
1082 confirmEqual("test de_US 7", &actualReturn
, &Locale::getGerman());
1087 UErrorCode status
= U_ZERO_ERROR
;
1088 Locale actualReturn
;
1089 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", 1234, &actualReturn
, status
);
1090 confirmEqual("test de_US 8", german
, target
);
1091 confirmEqual("test de_US 9", &actualReturn
, &Locale::getGerman());
1095 UnicodeString
* one
= new UnicodeString("one/de_US");
1096 UnicodeString
* two
= new UnicodeString("two/de_US");
1098 service
.registerInstance(one
, Locale("de_US"), 1, status
);
1099 service
.registerInstance(two
, Locale("de_US"), 2, status
);
1102 UErrorCode status
= U_ZERO_ERROR
;
1103 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", 1, status
);
1104 confirmEqual("test de_US kind 1", one
, target
);
1109 UErrorCode status
= U_ZERO_ERROR
;
1110 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", 2, status
);
1111 confirmEqual("test de_US kind 2", two
, target
);
1116 UErrorCode status
= U_ZERO_ERROR
;
1117 UnicodeString
* target
= (UnicodeString
*)service
.get("de_US", status
);
1118 confirmEqual("test de_US kind 3", german
, target
);
1123 UErrorCode status
= U_ZERO_ERROR
;
1124 UnicodeString english
= "en";
1125 Locale localeResult
;
1126 UnicodeString result
;
1127 LocaleKey
* lkey
= LocaleKey::createWithCanonicalFallback(&english
, NULL
, 1234, status
);
1128 logln("lkey prefix: " + lkey
->prefix(result
));
1130 logln("lkey descriptor: " + lkey
->currentDescriptor(result
));
1132 logln(UnicodeString("lkey current locale: ") + lkey
->currentLocale(localeResult
).getName());
1136 logln("lkey descriptor 2: " + lkey
->currentDescriptor(result
));
1140 logln("lkey descriptor 3: " + lkey
->currentDescriptor(result
));
1142 delete lkey
; // tentatively weiv
1146 UErrorCode status
= U_ZERO_ERROR
;
1147 UnicodeString
* target
= (UnicodeString
*)service
.get("za_PPP", status
);
1148 confirmEqual("test zappp", root
, target
);
1152 Locale loc
= Locale::getDefault();
1153 Locale::setDefault(Locale::getJapanese(), status
);
1155 UErrorCode status
= U_ZERO_ERROR
;
1156 UnicodeString
* target
= (UnicodeString
*)service
.get("za_PPP", status
);
1157 confirmEqual("test with ja locale", japanese
, target
);
1162 UErrorCode status
= U_ZERO_ERROR
;
1163 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
1164 service
.getVisibleIDs(ids
, status
);
1165 logln("all visible ids:");
1166 for (int i
= 0; i
< ids
.size(); ++i
) {
1167 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
1172 Locale::setDefault(loc
, status
);
1174 UErrorCode status
= U_ZERO_ERROR
;
1175 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, 0, status
);
1176 service
.getVisibleIDs(ids
, status
);
1177 logln("all visible ids:");
1178 for (int i
= 0; i
< ids
.size(); ++i
) {
1179 const UnicodeString
* id
= (const UnicodeString
*)ids
[i
];
1185 UErrorCode status
= U_ZERO_ERROR
;
1186 UnicodeString
* target
= (UnicodeString
*)service
.get("za_PPP", status
);
1187 confirmEqual("test with en locale", root
, target
);
1192 UErrorCode status
= U_ZERO_ERROR
;
1193 StringEnumeration
* locales
= service
.getAvailableLocales();
1195 confirmIdentical("test available locales", locales
->count(status
), 6);
1199 while ((p
= locales
->next(NULL
, status
))) {
1206 errln("could not create available locales");
1211 class WrapFactory
: public ICUServiceFactory
{
1213 static const UnicodeString
& getGreetingID() {
1214 if (greetingID
== NULL
) {
1215 greetingID
= new UnicodeString("greeting");
1220 static void cleanup() {
1225 UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const {
1226 if (U_SUCCESS(status
)) {
1228 if (key
.currentID(temp
).compare(getGreetingID()) == 0) {
1229 UnicodeString
* previous
= (UnicodeString
*)service
->getKey((ICUServiceKey
&)key
, NULL
, this, status
);
1231 previous
->insert(0, "A different greeting: \"");
1232 previous
->append("\"");
1240 void updateVisibleIDs(Hashtable
& result
, UErrorCode
& status
) const {
1241 if (U_SUCCESS(status
)) {
1242 result
.put("greeting", (void*)this, status
);
1246 UnicodeString
& getDisplayName(const UnicodeString
& id
, const Locale
& /* locale */, UnicodeString
& result
) const {
1247 result
.append("wrap '");
1254 * UObject boilerplate.
1256 static UClassID
getStaticClassID() {
1257 return (UClassID
)&fgClassID
;
1260 virtual UClassID
getDynamicClassID() const {
1261 return getStaticClassID();
1265 static const char fgClassID
;
1266 static UnicodeString
* greetingID
;
1269 UnicodeString
* WrapFactory::greetingID
= NULL
;
1270 const char WrapFactory::fgClassID
= '\0';
1273 ICUServiceTest::testWrapFactory()
1275 UnicodeString
* greeting
= new UnicodeString("Hello There");
1276 UnicodeString greetingID
= "greeting";
1277 UErrorCode status
= U_ZERO_ERROR
;
1278 TestStringService service
;
1279 service
.registerInstance(greeting
, greetingID
, status
);
1282 UErrorCode status
= U_ZERO_ERROR
;
1283 UnicodeString
* result
= (UnicodeString
*)service
.get(greetingID
, status
);
1285 logln("test one: " + *result
);
1290 service
.registerFactory(new WrapFactory(), status
);
1292 UErrorCode status
= U_ZERO_ERROR
;
1293 UnicodeString
* result
= (UnicodeString
*)service
.get(greetingID
, status
);
1294 UnicodeString target
= "A different greeting: \"Hello There\"";
1295 confirmEqual("wrap test: ", result
, &target
);
1299 WrapFactory::cleanup();
1302 // misc coverage tests
1303 void ICUServiceTest::testCoverage()
1308 ICUServiceKey
key("foobar");
1309 logln("ID: " + key
.getID());
1310 logln("canonicalID: " + key
.canonicalID(temp
));
1311 logln("currentID: " + key
.currentID(temp
.remove()));
1312 logln("has fallback: " + UnicodeString(key
.fallback() ? "true" : "false"));
1314 if (key
.getDynamicClassID() != ICUServiceKey::getStaticClassID()) {
1315 errln("service key rtt failed.");
1321 UErrorCode status
= U_ZERO_ERROR
;
1323 UnicodeString
* obj
= new UnicodeString("An Object");
1324 SimpleFactory
* sf
= new SimpleFactory(obj
, "object");
1327 logln(sf
->getDisplayName("object", Locale::getDefault(), temp
));
1329 if (sf
->getDynamicClassID() != SimpleFactory::getStaticClassID()) {
1330 errln("simple factory rtti failed.");
1335 TestStringService service
;
1336 service
.registerFactory(sf
, status
);
1339 UnicodeString
* result
= (UnicodeString
*)service
.get("object", status
);
1341 logln("object is: " + *result
);
1344 errln("could not get object");
1352 UErrorCode status
= U_ZERO_ERROR
;
1353 UnicodeString
* howdy
= new UnicodeString("Howdy");
1355 TestStringSimpleKeyService service
;
1356 service
.registerInstance(howdy
, "Greetings", status
);
1358 UnicodeString
* result
= (UnicodeString
*)service
.get("Greetings", status
);
1360 logln("object is: " + *result
);
1363 errln("could not get object");
1367 UVector
ids(uhash_deleteUnicodeString
, uhash_compareUnicodeString
, status
);
1368 // yuck, this is awkward to use. All because we pass null in an overload.
1369 // TODO: change this.
1370 UnicodeString
str("Greet");
1371 service
.getVisibleIDs(ids
, &str
, status
);
1372 confirmIdentical("no fallback of greet", ids
.size(), 0);
1379 UnicodeString
primary("en_US");
1380 UnicodeString
fallback("ja_JP");
1381 UErrorCode status
= U_ZERO_ERROR
;
1382 LocaleKey
* key
= LocaleKey::createWithCanonicalFallback(&primary
, &fallback
, status
);
1384 if (key
->getDynamicClassID() != LocaleKey::getStaticClassID()) {
1385 errln("localekey rtti error");
1388 if (!key
->isFallbackOf("en_US_FOOBAR")) {
1389 errln("localekey should be fallback for en_US_FOOBAR");
1391 if (!key
->isFallbackOf("en_US")) {
1392 errln("localekey should be fallback for en_US");
1394 if (key
->isFallbackOf("en")) {
1395 errln("localekey should not be fallback for en");
1400 logln(UnicodeString("current locale: ") + key
->currentLocale(loc
).getName());
1401 logln(UnicodeString("canonical locale: ") + key
->canonicalLocale(loc
).getName());
1402 logln(UnicodeString("is fallback of en: ") + (key
->isFallbackOf("en") ? "true" : " false"));
1403 } while (key
->fallback());
1407 key
= LocaleKey::createWithCanonicalFallback(&primary
, &fallback
, status
);
1409 UnicodeString result
;
1410 LKFSubclass
lkf(TRUE
); // empty
1413 UObject
*obj
= lkf
.create(*key
, NULL
, status
);
1414 logln("obj: " + UnicodeString(obj
? "obj" : "null"));
1415 logln(lkf
.getDisplayName("en_US", Locale::getDefault(), result
));
1416 lkf
.updateVisibleIDs(table
, status
);
1418 if (table
.count() != 1) {
1419 errln("visible IDs does not contain en_US");
1422 LKFSubclass
invisibleLKF(FALSE
);
1423 obj
= lkf
.create(*key
, NULL
, status
);
1424 logln("obj: " + UnicodeString(obj
? "obj" : "null"));
1425 logln(invisibleLKF
.getDisplayName("en_US", Locale::getDefault(), result
.remove()));
1426 invisibleLKF
.updateVisibleIDs(table
, status
);
1427 if (table
.count() != 0) {
1428 errln("visible IDs contains en_US");
1433 key
= LocaleKey::createWithCanonicalFallback(&primary
, &fallback
, 123, status
);
1434 if (U_SUCCESS(status
)) {
1436 key
->currentDescriptor(str
);
1437 key
->parsePrefix(str
);
1439 errln("did not get expected prefix");
1444 // coverage, getSupportedIDs is either overridden or the calling method is
1445 LKFSubclass0 lkFactory
;
1447 lkFactory
.updateVisibleIDs(table0
, status
);
1448 if (table0
.count() != 0) {
1449 errln("LKF returned non-empty hashtable");
1453 // ResourceBundleFactory
1454 key
= LocaleKey::createWithCanonicalFallback(&primary
, &fallback
, status
);
1455 ICUResourceBundleFactory rbf
;
1456 UObject
* icurb
= rbf
.create(*key
, NULL
, status
);
1457 if (icurb
!= NULL
) {
1458 logln("got resource bundle for key");
1466 ICUNotifier nf
= new ICUNSubclass();
1468 nf
.addListener(null
);
1469 errln("added null listener");
1471 catch (NullPointerException e
) {
1472 logln(e
.getMessage());
1474 catch (Exception e
) {
1475 errln("got wrong exception");
1479 nf
.addListener(new WrongListener());
1480 errln("added wrong listener");
1482 catch (InternalError e
) {
1483 logln(e
.getMessage());
1485 catch (Exception e
) {
1486 errln("got wrong exception");
1490 nf
.removeListener(null
);
1491 errln("removed null listener");
1493 catch (NullPointerException e
) {
1494 logln(e
.getMessage());
1496 catch (Exception e
) {
1497 errln("got wrong exception");
1500 nf
.removeListener(new MyListener());
1502 nf
.addListener(new MyListener());
1503 nf
.removeListener(new MyListener());
1508 /* !UCONFIG_NO_SERVICE */