intl/icu/source/common/serv.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /**
michael@0 2 *******************************************************************************
michael@0 3 * Copyright (C) 2001-2011, International Business Machines Corporation. *
michael@0 4 * All Rights Reserved. *
michael@0 5 *******************************************************************************
michael@0 6 */
michael@0 7
michael@0 8 #ifndef ICUSERV_H
michael@0 9 #define ICUSERV_H
michael@0 10
michael@0 11 #include "unicode/utypes.h"
michael@0 12
michael@0 13 #if UCONFIG_NO_SERVICE
michael@0 14
michael@0 15 U_NAMESPACE_BEGIN
michael@0 16
michael@0 17 /*
michael@0 18 * Allow the declaration of APIs with pointers to ICUService
michael@0 19 * even when service is removed from the build.
michael@0 20 */
michael@0 21 class ICUService;
michael@0 22
michael@0 23 U_NAMESPACE_END
michael@0 24
michael@0 25 #else
michael@0 26
michael@0 27 #include "unicode/unistr.h"
michael@0 28 #include "unicode/locid.h"
michael@0 29 #include "unicode/umisc.h"
michael@0 30
michael@0 31 #include "hash.h"
michael@0 32 #include "uvector.h"
michael@0 33 #include "servnotf.h"
michael@0 34
michael@0 35 class ICUServiceTest;
michael@0 36
michael@0 37 U_NAMESPACE_BEGIN
michael@0 38
michael@0 39 class ICUServiceKey;
michael@0 40 class ICUServiceFactory;
michael@0 41 class SimpleFactory;
michael@0 42 class ServiceListener;
michael@0 43 class ICUService;
michael@0 44
michael@0 45 class DNCache;
michael@0 46
michael@0 47 /*******************************************************************
michael@0 48 * ICUServiceKey
michael@0 49 */
michael@0 50
michael@0 51 /**
michael@0 52 * <p>ICUServiceKeys are used to communicate with factories to
michael@0 53 * generate an instance of the service. ICUServiceKeys define how
michael@0 54 * ids are canonicalized, provide both a current id and a current
michael@0 55 * descriptor to use in querying the cache and factories, and
michael@0 56 * determine the fallback strategy.</p>
michael@0 57 *
michael@0 58 * <p>ICUServiceKeys provide both a currentDescriptor and a currentID.
michael@0 59 * The descriptor contains an optional prefix, followed by '/'
michael@0 60 * and the currentID. Factories that handle complex keys,
michael@0 61 * for example number format factories that generate multiple
michael@0 62 * kinds of formatters for the same locale, use the descriptor
michael@0 63 * to provide a fully unique identifier for the service object,
michael@0 64 * while using the currentID (in this case, the locale string),
michael@0 65 * as the visible IDs that can be localized.</p>
michael@0 66 *
michael@0 67 * <p>The default implementation of ICUServiceKey has no fallbacks and
michael@0 68 * has no custom descriptors.</p>
michael@0 69 */
michael@0 70 class U_COMMON_API ICUServiceKey : public UObject {
michael@0 71 private:
michael@0 72 const UnicodeString _id;
michael@0 73
michael@0 74 protected:
michael@0 75 static const UChar PREFIX_DELIMITER;
michael@0 76
michael@0 77 public:
michael@0 78
michael@0 79 /**
michael@0 80 * <p>Construct a key from an id.</p>
michael@0 81 *
michael@0 82 * @param id the ID from which to construct the key.
michael@0 83 */
michael@0 84 ICUServiceKey(const UnicodeString& id);
michael@0 85
michael@0 86 /**
michael@0 87 * <p>Virtual destructor.</p>
michael@0 88 */
michael@0 89 virtual ~ICUServiceKey();
michael@0 90
michael@0 91 /**
michael@0 92 * <p>Return the original ID used to construct this key.</p>
michael@0 93 *
michael@0 94 * @return the ID used to construct this key.
michael@0 95 */
michael@0 96 virtual const UnicodeString& getID() const;
michael@0 97
michael@0 98 /**
michael@0 99 * <p>Return the canonical version of the original ID. This implementation
michael@0 100 * appends the original ID to result. Result is returned as a convenience.</p>
michael@0 101 *
michael@0 102 * @param result the output parameter to which the id will be appended.
michael@0 103 * @return the modified result.
michael@0 104 */
michael@0 105 virtual UnicodeString& canonicalID(UnicodeString& result) const;
michael@0 106
michael@0 107 /**
michael@0 108 * <p>Return the (canonical) current ID. This implementation appends
michael@0 109 * the canonical ID to result. Result is returned as a convenience.</p>
michael@0 110 *
michael@0 111 * @param result the output parameter to which the current id will be appended.
michael@0 112 * @return the modified result.
michael@0 113 */
michael@0 114 virtual UnicodeString& currentID(UnicodeString& result) const;
michael@0 115
michael@0 116 /**
michael@0 117 * <p>Return the current descriptor. This implementation appends
michael@0 118 * the current descriptor to result. Result is returned as a convenience.</p>
michael@0 119 *
michael@0 120 * <p>The current descriptor is used to fully
michael@0 121 * identify an instance of the service in the cache. A
michael@0 122 * factory may handle all descriptors for an ID, or just a
michael@0 123 * particular descriptor. The factory can either parse the
michael@0 124 * descriptor or use custom API on the key in order to
michael@0 125 * instantiate the service.</p>
michael@0 126 *
michael@0 127 * @param result the output parameter to which the current id will be appended.
michael@0 128 * @return the modified result.
michael@0 129 */
michael@0 130 virtual UnicodeString& currentDescriptor(UnicodeString& result) const;
michael@0 131
michael@0 132 /**
michael@0 133 * <p>If the key has a fallback, modify the key and return true,
michael@0 134 * otherwise return false. The current ID will change if there
michael@0 135 * is a fallback. No currentIDs should be repeated, and fallback
michael@0 136 * must eventually return false. This implementation has no fallbacks
michael@0 137 * and always returns false.</p>
michael@0 138 *
michael@0 139 * @return TRUE if the ICUServiceKey changed to a valid fallback value.
michael@0 140 */
michael@0 141 virtual UBool fallback();
michael@0 142
michael@0 143 /**
michael@0 144 * <p>Return TRUE if a key created from id matches, or would eventually
michael@0 145 * fallback to match, the canonical ID of this ICUServiceKey.</p>
michael@0 146 *
michael@0 147 * @param id the id to test.
michael@0 148 * @return TRUE if this ICUServiceKey's canonical ID is a fallback of id.
michael@0 149 */
michael@0 150 virtual UBool isFallbackOf(const UnicodeString& id) const;
michael@0 151
michael@0 152 /**
michael@0 153 * <p>Return the prefix. This implementation leaves result unchanged.
michael@0 154 * Result is returned as a convenience.</p>
michael@0 155 *
michael@0 156 * @param result the output parameter to which the prefix will be appended.
michael@0 157 * @return the modified result.
michael@0 158 */
michael@0 159 virtual UnicodeString& prefix(UnicodeString& result) const;
michael@0 160
michael@0 161 /**
michael@0 162 * <p>A utility to parse the prefix out of a descriptor string. Only
michael@0 163 * the (undelimited) prefix, if any, remains in result. Result is returned as a
michael@0 164 * convenience.</p>
michael@0 165 *
michael@0 166 * @param result an input/output parameter that on entry is a descriptor, and
michael@0 167 * on exit is the prefix of that descriptor.
michael@0 168 * @return the modified result.
michael@0 169 */
michael@0 170 static UnicodeString& parsePrefix(UnicodeString& result);
michael@0 171
michael@0 172 /**
michael@0 173 * <p>A utility to parse the suffix out of a descriptor string. Only
michael@0 174 * the (undelimited) suffix, if any, remains in result. Result is returned as a
michael@0 175 * convenience.</p>
michael@0 176 *
michael@0 177 * @param result an input/output parameter that on entry is a descriptor, and
michael@0 178 * on exit is the suffix of that descriptor.
michael@0 179 * @return the modified result.
michael@0 180 */
michael@0 181 static UnicodeString& parseSuffix(UnicodeString& result);
michael@0 182
michael@0 183 public:
michael@0 184 /**
michael@0 185 * UObject RTTI boilerplate.
michael@0 186 */
michael@0 187 static UClassID U_EXPORT2 getStaticClassID();
michael@0 188
michael@0 189 /**
michael@0 190 * UObject RTTI boilerplate.
michael@0 191 */
michael@0 192 virtual UClassID getDynamicClassID() const;
michael@0 193
michael@0 194 #ifdef SERVICE_DEBUG
michael@0 195 public:
michael@0 196 virtual UnicodeString& debug(UnicodeString& result) const;
michael@0 197 virtual UnicodeString& debugClass(UnicodeString& result) const;
michael@0 198 #endif
michael@0 199
michael@0 200 };
michael@0 201
michael@0 202 /*******************************************************************
michael@0 203 * ICUServiceFactory
michael@0 204 */
michael@0 205
michael@0 206 /**
michael@0 207 * <p>An implementing ICUServiceFactory generates the service objects maintained by the
michael@0 208 * service. A factory generates a service object from a key,
michael@0 209 * updates id->factory mappings, and returns the display name for
michael@0 210 * a supported id.</p>
michael@0 211 */
michael@0 212 class U_COMMON_API ICUServiceFactory : public UObject {
michael@0 213 public:
michael@0 214 virtual ~ICUServiceFactory();
michael@0 215
michael@0 216 /**
michael@0 217 * <p>Create a service object from the key, if this factory
michael@0 218 * supports the key. Otherwise, return NULL.</p>
michael@0 219 *
michael@0 220 * <p>If the factory supports the key, then it can call
michael@0 221 * the service's getKey(ICUServiceKey, String[], ICUServiceFactory) method
michael@0 222 * passing itself as the factory to get the object that
michael@0 223 * the service would have created prior to the factory's
michael@0 224 * registration with the service. This can change the
michael@0 225 * key, so any information required from the key should
michael@0 226 * be extracted before making such a callback.</p>
michael@0 227 *
michael@0 228 * @param key the service key.
michael@0 229 * @param service the service with which this factory is registered.
michael@0 230 * @param status the error code status.
michael@0 231 * @return the service object, or NULL if the factory does not support the key.
michael@0 232 */
michael@0 233 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const = 0;
michael@0 234
michael@0 235 /**
michael@0 236 * <p>Update result to reflect the IDs (not descriptors) that this
michael@0 237 * factory publicly handles. Result contains mappings from ID to
michael@0 238 * factory. On entry it will contain all (visible) mappings from
michael@0 239 * previously-registered factories.</p>
michael@0 240 *
michael@0 241 * <p>This function, together with getDisplayName, are used to
michael@0 242 * support ICUService::getDisplayNames. The factory determines
michael@0 243 * which IDs (of those it supports) it will make visible, and of
michael@0 244 * those, which it will provide localized display names for. In
michael@0 245 * most cases it will register mappings from all IDs it supports
michael@0 246 * to itself.</p>
michael@0 247 *
michael@0 248 * @param result the mapping table to update.
michael@0 249 * @param status the error code status.
michael@0 250 */
michael@0 251 virtual void updateVisibleIDs(Hashtable& result, UErrorCode& status) const = 0;
michael@0 252
michael@0 253 /**
michael@0 254 * <p>Return, in result, the display name of the id in the provided locale.
michael@0 255 * This is an id, not a descriptor. If the id is
michael@0 256 * not visible, sets result to bogus. If the
michael@0 257 * incoming result is bogus, it remains bogus. Result is returned as a
michael@0 258 * convenience. Results are not defined if id is not one supported by this
michael@0 259 * factory.</p>
michael@0 260 *
michael@0 261 * @param id a visible id supported by this factory.
michael@0 262 * @param locale the locale for which to generate the corresponding localized display name.
michael@0 263 * @param result output parameter to hold the display name.
michael@0 264 * @return result.
michael@0 265 */
michael@0 266 virtual UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const = 0;
michael@0 267 };
michael@0 268
michael@0 269 /*
michael@0 270 ******************************************************************
michael@0 271 */
michael@0 272
michael@0 273 /**
michael@0 274 * <p>A default implementation of factory. This provides default
michael@0 275 * implementations for subclasses, and implements a singleton
michael@0 276 * factory that matches a single ID and returns a single
michael@0 277 * (possibly deferred-initialized) instance. This implements
michael@0 278 * updateVisibleIDs to add a mapping from its ID to itself
michael@0 279 * if visible is true, or to remove any existing mapping
michael@0 280 * for its ID if visible is false. No localization of display
michael@0 281 * names is performed.</p>
michael@0 282 */
michael@0 283 class U_COMMON_API SimpleFactory : public ICUServiceFactory {
michael@0 284 protected:
michael@0 285 UObject* _instance;
michael@0 286 const UnicodeString _id;
michael@0 287 const UBool _visible;
michael@0 288
michael@0 289 public:
michael@0 290 /**
michael@0 291 * <p>Construct a SimpleFactory that maps a single ID to a single
michael@0 292 * service instance. If visible is TRUE, the ID will be visible.
michael@0 293 * The instance must not be NULL. The SimpleFactory will adopt
michael@0 294 * the instance, which must not be changed subsequent to this call.</p>
michael@0 295 *
michael@0 296 * @param instanceToAdopt the service instance to adopt.
michael@0 297 * @param id the ID to assign to this service instance.
michael@0 298 * @param visible if TRUE, the ID will be visible.
michael@0 299 */
michael@0 300 SimpleFactory(UObject* instanceToAdopt, const UnicodeString& id, UBool visible = TRUE);
michael@0 301
michael@0 302 /**
michael@0 303 * <p>Destructor.</p>
michael@0 304 */
michael@0 305 virtual ~SimpleFactory();
michael@0 306
michael@0 307 /**
michael@0 308 * <p>This implementation returns a clone of the service instance if the factory's ID is equal to
michael@0 309 * the key's currentID. Service and prefix are ignored.</p>
michael@0 310 *
michael@0 311 * @param key the service key.
michael@0 312 * @param service the service with which this factory is registered.
michael@0 313 * @param status the error code status.
michael@0 314 * @return the service object, or NULL if the factory does not support the key.
michael@0 315 */
michael@0 316 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
michael@0 317
michael@0 318 /**
michael@0 319 * <p>This implementation adds a mapping from ID -> this to result if visible is TRUE,
michael@0 320 * otherwise it removes ID from result.</p>
michael@0 321 *
michael@0 322 * @param result the mapping table to update.
michael@0 323 * @param status the error code status.
michael@0 324 */
michael@0 325 virtual void updateVisibleIDs(Hashtable& result, UErrorCode& status) const;
michael@0 326
michael@0 327 /**
michael@0 328 * <p>This implementation returns the factory ID if it equals id and visible is TRUE,
michael@0 329 * otherwise it returns the empty string. (This implementation provides
michael@0 330 * no localized id information.)</p>
michael@0 331 *
michael@0 332 * @param id a visible id supported by this factory.
michael@0 333 * @param locale the locale for which to generate the corresponding localized display name.
michael@0 334 * @param result output parameter to hold the display name.
michael@0 335 * @return result.
michael@0 336 */
michael@0 337 virtual UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const;
michael@0 338
michael@0 339 public:
michael@0 340 /**
michael@0 341 * UObject RTTI boilerplate.
michael@0 342 */
michael@0 343 static UClassID U_EXPORT2 getStaticClassID();
michael@0 344
michael@0 345 /**
michael@0 346 * UObject RTTI boilerplate.
michael@0 347 */
michael@0 348 virtual UClassID getDynamicClassID() const;
michael@0 349
michael@0 350 #ifdef SERVICE_DEBUG
michael@0 351 public:
michael@0 352 virtual UnicodeString& debug(UnicodeString& toAppendTo) const;
michael@0 353 virtual UnicodeString& debugClass(UnicodeString& toAppendTo) const;
michael@0 354 #endif
michael@0 355
michael@0 356 };
michael@0 357
michael@0 358 /*
michael@0 359 ******************************************************************
michael@0 360 */
michael@0 361
michael@0 362 /**
michael@0 363 * <p>ServiceListener is the listener that ICUService provides by default.
michael@0 364 * ICUService will notifiy this listener when factories are added to
michael@0 365 * or removed from the service. Subclasses can provide
michael@0 366 * different listener interfaces that extend EventListener, and modify
michael@0 367 * acceptsListener and notifyListener as appropriate.</p>
michael@0 368 */
michael@0 369 class U_COMMON_API ServiceListener : public EventListener {
michael@0 370 public:
michael@0 371 virtual ~ServiceListener();
michael@0 372
michael@0 373 /**
michael@0 374 * <p>This method is called when the service changes. At the time of the
michael@0 375 * call this listener is registered with the service. It must
michael@0 376 * not modify the notifier in the context of this call.</p>
michael@0 377 *
michael@0 378 * @param service the service that changed.
michael@0 379 */
michael@0 380 virtual void serviceChanged(const ICUService& service) const = 0;
michael@0 381
michael@0 382 public:
michael@0 383 /**
michael@0 384 * UObject RTTI boilerplate.
michael@0 385 */
michael@0 386 static UClassID U_EXPORT2 getStaticClassID();
michael@0 387
michael@0 388 /**
michael@0 389 * UObject RTTI boilerplate.
michael@0 390 */
michael@0 391 virtual UClassID getDynamicClassID() const;
michael@0 392
michael@0 393 };
michael@0 394
michael@0 395 /*
michael@0 396 ******************************************************************
michael@0 397 */
michael@0 398
michael@0 399 /**
michael@0 400 * <p>A StringPair holds a displayName/ID pair. ICUService uses it
michael@0 401 * as the array elements returned by getDisplayNames.
michael@0 402 */
michael@0 403 class U_COMMON_API StringPair : public UMemory {
michael@0 404 public:
michael@0 405 /**
michael@0 406 * <p>The display name of the pair.</p>
michael@0 407 */
michael@0 408 const UnicodeString displayName;
michael@0 409
michael@0 410 /**
michael@0 411 * <p>The ID of the pair.</p>
michael@0 412 */
michael@0 413 const UnicodeString id;
michael@0 414
michael@0 415 /**
michael@0 416 * <p>Creates a string pair from a displayName and an ID.</p>
michael@0 417 *
michael@0 418 * @param displayName the displayName.
michael@0 419 * @param id the ID.
michael@0 420 * @param status the error code status.
michael@0 421 * @return a StringPair if the creation was successful, otherwise NULL.
michael@0 422 */
michael@0 423 static StringPair* create(const UnicodeString& displayName,
michael@0 424 const UnicodeString& id,
michael@0 425 UErrorCode& status);
michael@0 426
michael@0 427 /**
michael@0 428 * <p>Return TRUE if either string of the pair is bogus.</p>
michael@0 429 * @return TRUE if either string of the pair is bogus.
michael@0 430 */
michael@0 431 UBool isBogus() const;
michael@0 432
michael@0 433 private:
michael@0 434 StringPair(const UnicodeString& displayName, const UnicodeString& id);
michael@0 435 };
michael@0 436
michael@0 437 /*******************************************************************
michael@0 438 * ICUService
michael@0 439 */
michael@0 440
michael@0 441 /**
michael@0 442 * <p>A Service provides access to service objects that implement a
michael@0 443 * particular service, e.g. transliterators. Users provide a String
michael@0 444 * id (for example, a locale string) to the service, and get back an
michael@0 445 * object for that id. Service objects can be any kind of object. A
michael@0 446 * new service object is returned for each query. The caller is
michael@0 447 * responsible for deleting it.</p>
michael@0 448 *
michael@0 449 * <p>Services 'canonicalize' the query ID and use the canonical ID to
michael@0 450 * query for the service. The service also defines a mechanism to
michael@0 451 * 'fallback' the ID multiple times. Clients can optionally request
michael@0 452 * the actual ID that was matched by a query when they use an ID to
michael@0 453 * retrieve a service object.</p>
michael@0 454 *
michael@0 455 * <p>Service objects are instantiated by ICUServiceFactory objects
michael@0 456 * registered with the service. The service queries each
michael@0 457 * ICUServiceFactory in turn, from most recently registered to
michael@0 458 * earliest registered, until one returns a service object. If none
michael@0 459 * responds with a service object, a fallback ID is generated, and the
michael@0 460 * process repeats until a service object is returned or until the ID
michael@0 461 * has no further fallbacks.</p>
michael@0 462 *
michael@0 463 * <p>In ICU 2.4, UObject (the base class of service instances) does
michael@0 464 * not define a polymorphic clone function. ICUService uses clones to
michael@0 465 * manage ownership. Thus, for now, ICUService defines an abstract
michael@0 466 * method, cloneInstance, that clients must implement to create clones
michael@0 467 * of the service instances. This may change in future releases of
michael@0 468 * ICU.</p>
michael@0 469 *
michael@0 470 * <p>ICUServiceFactories can be dynamically registered and
michael@0 471 * unregistered with the service. When registered, an
michael@0 472 * ICUServiceFactory is installed at the head of the factory list, and
michael@0 473 * so gets 'first crack' at any keys or fallback keys. When
michael@0 474 * unregistered, it is removed from the service and can no longer be
michael@0 475 * located through it. Service objects generated by this factory and
michael@0 476 * held by the client are unaffected.</p>
michael@0 477 *
michael@0 478 * <p>If a service has variants (e.g., the different variants of
michael@0 479 * BreakIterator) an ICUServiceFactory can use the prefix of the
michael@0 480 * ICUServiceKey to determine the variant of a service to generate.
michael@0 481 * If it does not support all variants, it can request
michael@0 482 * previously-registered factories to handle the ones it does not
michael@0 483 * support.</p>
michael@0 484 *
michael@0 485 * <p>ICUService uses ICUServiceKeys to query factories and perform
michael@0 486 * fallback. The ICUServiceKey defines the canonical form of the ID,
michael@0 487 * and implements the fallback strategy. Custom ICUServiceKeys can be
michael@0 488 * defined that parse complex IDs into components that
michael@0 489 * ICUServiceFactories can more easily use. The ICUServiceKey can
michael@0 490 * cache the results of this parsing to save repeated effort.
michael@0 491 * ICUService provides convenience APIs that take UnicodeStrings and
michael@0 492 * generate default ICUServiceKeys for use in querying.</p>
michael@0 493 *
michael@0 494 * <p>ICUService provides API to get the list of IDs publicly
michael@0 495 * supported by the service (although queries aren't restricted to
michael@0 496 * this list). This list contains only 'simple' IDs, and not fully
michael@0 497 * unique IDs. ICUServiceFactories are associated with each simple ID
michael@0 498 * and the responsible factory can also return a human-readable
michael@0 499 * localized version of the simple ID, for use in user interfaces.
michael@0 500 * ICUService can also provide an array of the all the localized
michael@0 501 * visible IDs and their corresponding internal IDs.</p>
michael@0 502 *
michael@0 503 * <p>ICUService implements ICUNotifier, so that clients can register
michael@0 504 * to receive notification when factories are added or removed from
michael@0 505 * the service. ICUService provides a default EventListener
michael@0 506 * subinterface, ServiceListener, which can be registered with the
michael@0 507 * service. When the service changes, the ServiceListener's
michael@0 508 * serviceChanged method is called with the service as the
michael@0 509 * argument.</p>
michael@0 510 *
michael@0 511 * <p>The ICUService API is both rich and generic, and it is expected
michael@0 512 * that most implementations will statically 'wrap' ICUService to
michael@0 513 * present a more appropriate API-- for example, to declare the type
michael@0 514 * of the objects returned from get, to limit the factories that can
michael@0 515 * be registered with the service, or to define their own listener
michael@0 516 * interface with a custom callback method. They might also customize
michael@0 517 * ICUService by overriding it, for example, to customize the
michael@0 518 * ICUServiceKey and fallback strategy. ICULocaleService is a
michael@0 519 * subclass of ICUService that uses Locale names as IDs and uses
michael@0 520 * ICUServiceKeys that implement the standard resource bundle fallback
michael@0 521 * strategy. Most clients will wish to subclass it instead of
michael@0 522 * ICUService.</p>
michael@0 523 */
michael@0 524 class U_COMMON_API ICUService : public ICUNotifier {
michael@0 525 protected:
michael@0 526 /**
michael@0 527 * Name useful for debugging.
michael@0 528 */
michael@0 529 const UnicodeString name;
michael@0 530
michael@0 531 private:
michael@0 532
michael@0 533 /**
michael@0 534 * Timestamp so iterators can be fail-fast.
michael@0 535 */
michael@0 536 uint32_t timestamp;
michael@0 537
michael@0 538 /**
michael@0 539 * All the factories registered with this service.
michael@0 540 */
michael@0 541 UVector* factories;
michael@0 542
michael@0 543 /**
michael@0 544 * The service cache.
michael@0 545 */
michael@0 546 Hashtable* serviceCache;
michael@0 547
michael@0 548 /**
michael@0 549 * The ID cache.
michael@0 550 */
michael@0 551 Hashtable* idCache;
michael@0 552
michael@0 553 /**
michael@0 554 * The name cache.
michael@0 555 */
michael@0 556 DNCache* dnCache;
michael@0 557
michael@0 558 /**
michael@0 559 * Constructor.
michael@0 560 */
michael@0 561 public:
michael@0 562 /**
michael@0 563 * <p>Construct a new ICUService.</p>
michael@0 564 */
michael@0 565 ICUService();
michael@0 566
michael@0 567 /**
michael@0 568 * <p>Construct with a name (useful for debugging).</p>
michael@0 569 *
michael@0 570 * @param name a name to use in debugging.
michael@0 571 */
michael@0 572 ICUService(const UnicodeString& name);
michael@0 573
michael@0 574 /**
michael@0 575 * <p>Destructor.</p>
michael@0 576 */
michael@0 577 virtual ~ICUService();
michael@0 578
michael@0 579 /**
michael@0 580 * <p>Return the name of this service. This will be the empty string if none was assigned.
michael@0 581 * Returns result as a convenience.</p>
michael@0 582 *
michael@0 583 * @param result an output parameter to contain the name of this service.
michael@0 584 * @return the name of this service.
michael@0 585 */
michael@0 586 UnicodeString& getName(UnicodeString& result) const;
michael@0 587
michael@0 588 /**
michael@0 589 * <p>Convenience override for get(ICUServiceKey&, UnicodeString*). This uses
michael@0 590 * createKey to create a key for the provided descriptor.</p>
michael@0 591 *
michael@0 592 * @param descriptor the descriptor.
michael@0 593 * @param status the error code status.
michael@0 594 * @return the service instance, or NULL.
michael@0 595 */
michael@0 596 UObject* get(const UnicodeString& descriptor, UErrorCode& status) const;
michael@0 597
michael@0 598 /**
michael@0 599 * <p>Convenience override for get(ICUServiceKey&, UnicodeString*). This uses
michael@0 600 * createKey to create a key from the provided descriptor.</p>
michael@0 601 *
michael@0 602 * @param descriptor the descriptor.
michael@0 603 * @param actualReturn a pointer to a UnicodeString to hold the matched descriptor, or NULL.
michael@0 604 * @param status the error code status.
michael@0 605 * @return the service instance, or NULL.
michael@0 606 */
michael@0 607 UObject* get(const UnicodeString& descriptor, UnicodeString* actualReturn, UErrorCode& status) const;
michael@0 608
michael@0 609 /**
michael@0 610 * <p>Convenience override for get(ICUServiceKey&, UnicodeString*).</p>
michael@0 611 *
michael@0 612 * @param key the key.
michael@0 613 * @param status the error code status.
michael@0 614 * @return the service instance, or NULL.
michael@0 615 */
michael@0 616 UObject* getKey(ICUServiceKey& key, UErrorCode& status) const;
michael@0 617
michael@0 618 /**
michael@0 619 * <p>Given a key, return a service object, and, if actualReturn
michael@0 620 * is not NULL, the descriptor with which it was found in the
michael@0 621 * first element of actualReturn. If no service object matches
michael@0 622 * this key, returns NULL and leaves actualReturn unchanged.</p>
michael@0 623 *
michael@0 624 * <p>This queries the cache using the key's descriptor, and if no
michael@0 625 * object in the cache matches, tries the key on each
michael@0 626 * registered factory, in order. If none generates a service
michael@0 627 * object for the key, repeats the process with each fallback of
michael@0 628 * the key, until either a factory returns a service object, or the key
michael@0 629 * has no fallback. If no object is found, the result of handleDefault
michael@0 630 * is returned.</p>
michael@0 631 *
michael@0 632 * <p>Subclasses can override this method to further customize the
michael@0 633 * result before returning it.
michael@0 634 *
michael@0 635 * @param key the key.
michael@0 636 * @param actualReturn a pointer to a UnicodeString to hold the matched descriptor, or NULL.
michael@0 637 * @param status the error code status.
michael@0 638 * @return the service instance, or NULL.
michael@0 639 */
michael@0 640 virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const;
michael@0 641
michael@0 642 /**
michael@0 643 * <p>This version of getKey is only called by ICUServiceFactories within the scope
michael@0 644 * of a previous getKey call, to determine what previously-registered factories would
michael@0 645 * have returned. For details, see getKey(ICUServiceKey&, UErrorCode&). Subclasses
michael@0 646 * should not call it directly, but call through one of the other get functions.</p>
michael@0 647 *
michael@0 648 * @param key the key.
michael@0 649 * @param actualReturn a pointer to a UnicodeString to hold the matched descriptor, or NULL.
michael@0 650 * @param factory the factory making the recursive call.
michael@0 651 * @param status the error code status.
michael@0 652 * @return the service instance, or NULL.
michael@0 653 */
michael@0 654 UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUServiceFactory* factory, UErrorCode& status) const;
michael@0 655
michael@0 656 /**
michael@0 657 * <p>Convenience override for getVisibleIDs(String) that passes null
michael@0 658 * as the fallback, thus returning all visible IDs.</p>
michael@0 659 *
michael@0 660 * @param result a vector to hold the returned IDs.
michael@0 661 * @param status the error code status.
michael@0 662 * @return the result vector.
michael@0 663 */
michael@0 664 UVector& getVisibleIDs(UVector& result, UErrorCode& status) const;
michael@0 665
michael@0 666 /**
michael@0 667 * <p>Return a snapshot of the visible IDs for this service. This
michael@0 668 * list will not change as ICUServiceFactories are added or removed, but the
michael@0 669 * supported IDs will, so there is no guarantee that all and only
michael@0 670 * the IDs in the returned list will be visible and supported by the
michael@0 671 * service in subsequent calls.</p>
michael@0 672 *
michael@0 673 * <p>The IDs are returned as pointers to UnicodeStrings. The
michael@0 674 * caller owns the IDs. Previous contents of result are discarded before
michael@0 675 * new elements, if any, are added.</p>
michael@0 676 *
michael@0 677 * <p>matchID is passed to createKey to create a key. If the key
michael@0 678 * is not NULL, its isFallbackOf method is used to filter out IDs
michael@0 679 * that don't match the key or have it as a fallback.</p>
michael@0 680 *
michael@0 681 * @param result a vector to hold the returned IDs.
michael@0 682 * @param matchID an ID used to filter the result, or NULL if all IDs are desired.
michael@0 683 * @param status the error code status.
michael@0 684 * @return the result vector.
michael@0 685 */
michael@0 686 UVector& getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorCode& status) const;
michael@0 687
michael@0 688 /**
michael@0 689 * <p>Convenience override for getDisplayName(const UnicodeString&, const Locale&, UnicodeString&) that
michael@0 690 * uses the current default locale.</p>
michael@0 691 *
michael@0 692 * @param id the ID for which to retrieve the localized displayName.
michael@0 693 * @param result an output parameter to hold the display name.
michael@0 694 * @return the modified result.
michael@0 695 */
michael@0 696 UnicodeString& getDisplayName(const UnicodeString& id, UnicodeString& result) const;
michael@0 697
michael@0 698 /**
michael@0 699 * <p>Given a visible ID, return the display name in the requested locale.
michael@0 700 * If there is no directly supported ID corresponding to this ID, result is
michael@0 701 * set to bogus.</p>
michael@0 702 *
michael@0 703 * @param id the ID for which to retrieve the localized displayName.
michael@0 704 * @param result an output parameter to hold the display name.
michael@0 705 * @param locale the locale in which to localize the ID.
michael@0 706 * @return the modified result.
michael@0 707 */
michael@0 708 UnicodeString& getDisplayName(const UnicodeString& id, UnicodeString& result, const Locale& locale) const;
michael@0 709
michael@0 710 /**
michael@0 711 * <p>Convenience override of getDisplayNames(const Locale&, const UnicodeString*) that
michael@0 712 * uses the current default Locale as the locale and NULL for
michael@0 713 * the matchID.</p>
michael@0 714 *
michael@0 715 * @param result a vector to hold the returned displayName/id StringPairs.
michael@0 716 * @param status the error code status.
michael@0 717 * @return the modified result vector.
michael@0 718 */
michael@0 719 UVector& getDisplayNames(UVector& result, UErrorCode& status) const;
michael@0 720
michael@0 721 /**
michael@0 722 * <p>Convenience override of getDisplayNames(const Locale&, const UnicodeString*) that
michael@0 723 * uses NULL for the matchID.</p>
michael@0 724 *
michael@0 725 * @param result a vector to hold the returned displayName/id StringPairs.
michael@0 726 * @param locale the locale in which to localize the ID.
michael@0 727 * @param status the error code status.
michael@0 728 * @return the modified result vector.
michael@0 729 */
michael@0 730 UVector& getDisplayNames(UVector& result, const Locale& locale, UErrorCode& status) const;
michael@0 731
michael@0 732 /**
michael@0 733 * <p>Return a snapshot of the mapping from display names to visible
michael@0 734 * IDs for this service. This set will not change as factories
michael@0 735 * are added or removed, but the supported IDs will, so there is
michael@0 736 * no guarantee that all and only the IDs in the returned map will
michael@0 737 * be visible and supported by the service in subsequent calls,
michael@0 738 * nor is there any guarantee that the current display names match
michael@0 739 * those in the result.</p>
michael@0 740 *
michael@0 741 * <p>The names are returned as pointers to StringPairs, which
michael@0 742 * contain both the displayName and the corresponding ID. The
michael@0 743 * caller owns the StringPairs. Previous contents of result are
michael@0 744 * discarded before new elements, if any, are added.</p>
michael@0 745 *
michael@0 746 * <p>matchID is passed to createKey to create a key. If the key
michael@0 747 * is not NULL, its isFallbackOf method is used to filter out IDs
michael@0 748 * that don't match the key or have it as a fallback.</p>
michael@0 749 *
michael@0 750 * @param result a vector to hold the returned displayName/id StringPairs.
michael@0 751 * @param locale the locale in which to localize the ID.
michael@0 752 * @param matchID an ID used to filter the result, or NULL if all IDs are desired.
michael@0 753 * @param status the error code status.
michael@0 754 * @return the result vector. */
michael@0 755 UVector& getDisplayNames(UVector& result,
michael@0 756 const Locale& locale,
michael@0 757 const UnicodeString* matchID,
michael@0 758 UErrorCode& status) const;
michael@0 759
michael@0 760 /**
michael@0 761 * <p>A convenience override of registerInstance(UObject*, const UnicodeString&, UBool)
michael@0 762 * that defaults visible to TRUE.</p>
michael@0 763 *
michael@0 764 * @param objToAdopt the object to register and adopt.
michael@0 765 * @param id the ID to assign to this object.
michael@0 766 * @param status the error code status.
michael@0 767 * @return a registry key that can be passed to unregister to unregister
michael@0 768 * (and discard) this instance.
michael@0 769 */
michael@0 770 URegistryKey registerInstance(UObject* objToAdopt, const UnicodeString& id, UErrorCode& status);
michael@0 771
michael@0 772 /**
michael@0 773 * <p>Register a service instance with the provided ID. The ID will be
michael@0 774 * canonicalized. The canonicalized ID will be returned by
michael@0 775 * getVisibleIDs if visible is TRUE. The service instance will be adopted and
michael@0 776 * must not be modified subsequent to this call.</p>
michael@0 777 *
michael@0 778 * <p>This issues a serviceChanged notification to registered listeners.</p>
michael@0 779 *
michael@0 780 * <p>This implementation wraps the object using
michael@0 781 * createSimpleFactory, and calls registerFactory.</p>
michael@0 782 *
michael@0 783 * @param objToAdopt the object to register and adopt.
michael@0 784 * @param id the ID to assign to this object.
michael@0 785 * @param visible TRUE if getVisibleIDs is to return this ID.
michael@0 786 * @param status the error code status.
michael@0 787 * @return a registry key that can be passed to unregister() to unregister
michael@0 788 * (and discard) this instance.
michael@0 789 */
michael@0 790 virtual URegistryKey registerInstance(UObject* objToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status);
michael@0 791
michael@0 792 /**
michael@0 793 * <p>Register an ICUServiceFactory. Returns a registry key that
michael@0 794 * can be used to unregister the factory. The factory
michael@0 795 * must not be modified subsequent to this call. The service owns
michael@0 796 * all registered factories. In case of an error, the factory is
michael@0 797 * deleted.</p>
michael@0 798 *
michael@0 799 * <p>This issues a serviceChanged notification to registered listeners.</p>
michael@0 800 *
michael@0 801 * <p>The default implementation accepts all factories.</p>
michael@0 802 *
michael@0 803 * @param factoryToAdopt the factory to register and adopt.
michael@0 804 * @param status the error code status.
michael@0 805 * @return a registry key that can be passed to unregister to unregister
michael@0 806 * (and discard) this factory.
michael@0 807 */
michael@0 808 virtual URegistryKey registerFactory(ICUServiceFactory* factoryToAdopt, UErrorCode& status);
michael@0 809
michael@0 810 /**
michael@0 811 * <p>Unregister a factory using a registry key returned by
michael@0 812 * registerInstance or registerFactory. After a successful call,
michael@0 813 * the factory will be removed from the service factory list and
michael@0 814 * deleted, and the key becomes invalid.</p>
michael@0 815 *
michael@0 816 * <p>This issues a serviceChanged notification to registered
michael@0 817 * listeners.</p>
michael@0 818 *
michael@0 819 * @param rkey the registry key.
michael@0 820 * @param status the error code status.
michael@0 821 * @return TRUE if the call successfully unregistered the factory.
michael@0 822 */
michael@0 823 virtual UBool unregister(URegistryKey rkey, UErrorCode& status);
michael@0 824
michael@0 825 /**
michael@0 826 * </p>Reset the service to the default factories. The factory
michael@0 827 * lock is acquired and then reInitializeFactories is called.</p>
michael@0 828 *
michael@0 829 * <p>This issues a serviceChanged notification to registered listeners.</p>
michael@0 830 */
michael@0 831 virtual void reset(void);
michael@0 832
michael@0 833 /**
michael@0 834 * <p>Return TRUE if the service is in its default state.</p>
michael@0 835 *
michael@0 836 * <p>The default implementation returns TRUE if there are no
michael@0 837 * factories registered.</p>
michael@0 838 */
michael@0 839 virtual UBool isDefault(void) const;
michael@0 840
michael@0 841 /**
michael@0 842 * <p>Create a key from an ID. If ID is NULL, returns NULL.</p>
michael@0 843 *
michael@0 844 * <p>The default implementation creates an ICUServiceKey instance.
michael@0 845 * Subclasses can override to define more useful keys appropriate
michael@0 846 * to the factories they accept.</p>
michael@0 847 *
michael@0 848 * @param a pointer to the ID for which to create a default ICUServiceKey.
michael@0 849 * @param status the error code status.
michael@0 850 * @return the ICUServiceKey corresponding to ID, or NULL.
michael@0 851 */
michael@0 852 virtual ICUServiceKey* createKey(const UnicodeString* id, UErrorCode& status) const;
michael@0 853
michael@0 854 /**
michael@0 855 * <p>Clone object so that caller can own the copy. In ICU2.4, UObject doesn't define
michael@0 856 * clone, so we need an instance-aware method that knows how to do this.
michael@0 857 * This is public so factories can call it, but should really be protected.</p>
michael@0 858 *
michael@0 859 * @param instance the service instance to clone.
michael@0 860 * @return a clone of the passed-in instance, or NULL if cloning was unsuccessful.
michael@0 861 */
michael@0 862 virtual UObject* cloneInstance(UObject* instance) const = 0;
michael@0 863
michael@0 864
michael@0 865 /************************************************************************
michael@0 866 * Subclassing API
michael@0 867 */
michael@0 868
michael@0 869 protected:
michael@0 870
michael@0 871 /**
michael@0 872 * <p>Create a factory that wraps a single service object. Called by registerInstance.</p>
michael@0 873 *
michael@0 874 * <p>The default implementation returns an instance of SimpleFactory.</p>
michael@0 875 *
michael@0 876 * @param instanceToAdopt the service instance to adopt.
michael@0 877 * @param id the ID to assign to this service instance.
michael@0 878 * @param visible if TRUE, the ID will be visible.
michael@0 879 * @param status the error code status.
michael@0 880 * @return an instance of ICUServiceFactory that maps this instance to the provided ID.
michael@0 881 */
michael@0 882 virtual ICUServiceFactory* createSimpleFactory(UObject* instanceToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status);
michael@0 883
michael@0 884 /**
michael@0 885 * <p>Reinitialize the factory list to its default state. After this call, isDefault()
michael@0 886 * must return TRUE.</p>
michael@0 887 *
michael@0 888 * <p>This issues a serviceChanged notification to registered listeners.</p>
michael@0 889 *
michael@0 890 * <p>The default implementation clears the factory list.
michael@0 891 * Subclasses can override to provide other default initialization
michael@0 892 * of the factory list. Subclasses must not call this method
michael@0 893 * directly, since it must only be called while holding write
michael@0 894 * access to the factory list.</p>
michael@0 895 */
michael@0 896 virtual void reInitializeFactories(void);
michael@0 897
michael@0 898 /**
michael@0 899 * <p>Default handler for this service if no factory in the factory list
michael@0 900 * handled the key passed to getKey.</p>
michael@0 901 *
michael@0 902 * <p>The default implementation returns NULL.</p>
michael@0 903 *
michael@0 904 * @param key the key.
michael@0 905 * @param actualReturn a pointer to a UnicodeString to hold the matched descriptor, or NULL.
michael@0 906 * @param status the error code status.
michael@0 907 * @return the service instance, or NULL.
michael@0 908 */
michael@0 909 virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const;
michael@0 910
michael@0 911 /**
michael@0 912 * <p>Clear caches maintained by this service.</p>
michael@0 913 *
michael@0 914 * <p>Subclasses can override if they implement additional caches
michael@0 915 * that need to be cleared when the service changes. Subclasses
michael@0 916 * should generally not call this method directly, as it must only
michael@0 917 * be called while synchronized on the factory lock.</p>
michael@0 918 */
michael@0 919 virtual void clearCaches(void);
michael@0 920
michael@0 921 /**
michael@0 922 * <p>Return true if the listener is accepted.</p>
michael@0 923 *
michael@0 924 * <p>The default implementation accepts the listener if it is
michael@0 925 * a ServiceListener. Subclasses can override this to accept
michael@0 926 * different listeners.</p>
michael@0 927 *
michael@0 928 * @param l the listener to test.
michael@0 929 * @return TRUE if the service accepts the listener.
michael@0 930 */
michael@0 931 virtual UBool acceptsListener(const EventListener& l) const;
michael@0 932
michael@0 933 /**
michael@0 934 * <p>Notify the listener of a service change.</p>
michael@0 935 *
michael@0 936 * <p>The default implementation assumes a ServiceListener.
michael@0 937 * If acceptsListener has been overridden to accept different
michael@0 938 * listeners, this should be overridden as well.</p>
michael@0 939 *
michael@0 940 * @param l the listener to notify.
michael@0 941 */
michael@0 942 virtual void notifyListener(EventListener& l) const;
michael@0 943
michael@0 944 /************************************************************************
michael@0 945 * Utilities for subclasses.
michael@0 946 */
michael@0 947
michael@0 948 /**
michael@0 949 * <p>Clear only the service cache.</p>
michael@0 950 *
michael@0 951 * <p>This can be called by subclasses when a change affects the service
michael@0 952 * cache but not the ID caches, e.g., when the default locale changes
michael@0 953 * the resolution of IDs also changes, requiring the cache to be
michael@0 954 * flushed, but not the visible IDs themselves.</p>
michael@0 955 */
michael@0 956 void clearServiceCache(void);
michael@0 957
michael@0 958 /**
michael@0 959 * <p>Return a map from visible IDs to factories.
michael@0 960 * This must only be called when the mutex is held.</p>
michael@0 961 *
michael@0 962 * @param status the error code status.
michael@0 963 * @return a Hashtable containing mappings from visible
michael@0 964 * IDs to factories.
michael@0 965 */
michael@0 966 const Hashtable* getVisibleIDMap(UErrorCode& status) const;
michael@0 967
michael@0 968 /**
michael@0 969 * <p>Allow subclasses to read the time stamp.</p>
michael@0 970 *
michael@0 971 * @return the timestamp.
michael@0 972 */
michael@0 973 int32_t getTimestamp(void) const;
michael@0 974
michael@0 975 /**
michael@0 976 * <p>Return the number of registered factories.</p>
michael@0 977 *
michael@0 978 * @return the number of factories registered at the time of the call.
michael@0 979 */
michael@0 980 int32_t countFactories(void) const;
michael@0 981
michael@0 982 private:
michael@0 983
michael@0 984 friend class ::ICUServiceTest; // give tests access to countFactories.
michael@0 985 };
michael@0 986
michael@0 987 U_NAMESPACE_END
michael@0 988
michael@0 989 /* UCONFIG_NO_SERVICE */
michael@0 990 #endif
michael@0 991
michael@0 992 /* ICUSERV_H */
michael@0 993 #endif
michael@0 994

mercurial