sl@0: /** sl@0: ******************************************************************************* sl@0: * Copyright (C) 2001-2005, International Business Machines Corporation. * sl@0: * All Rights Reserved. * sl@0: ******************************************************************************* sl@0: */ sl@0: sl@0: #ifndef ICUSERV_H sl@0: #define ICUSERV_H sl@0: sl@0: #include "unicode/utypes.h" sl@0: sl@0: #if UCONFIG_NO_SERVICE sl@0: sl@0: U_NAMESPACE_BEGIN sl@0: sl@0: /* sl@0: * Allow the declaration of APIs with pointers to ICUService sl@0: * even when service is removed from the build. sl@0: */ sl@0: class ICUService; sl@0: sl@0: U_NAMESPACE_END sl@0: sl@0: #else sl@0: sl@0: #include "unicode/unistr.h" sl@0: #include "unicode/locid.h" sl@0: sl@0: #include "hash.h" sl@0: #include "uvector.h" sl@0: #include "servnotf.h" sl@0: sl@0: class ICUServiceTest; sl@0: sl@0: U_NAMESPACE_BEGIN sl@0: sl@0: class ICUServiceKey; sl@0: class ICUServiceFactory; sl@0: class SimpleFactory; sl@0: class ServiceListener; sl@0: class ICUService; sl@0: sl@0: class DNCache; sl@0: sl@0: /******************************************************************* sl@0: * ICUServiceKey sl@0: */ sl@0: sl@0: /** sl@0: *

ICUServiceKeys are used to communicate with factories to sl@0: * generate an instance of the service. ICUServiceKeys define how sl@0: * ids are canonicalized, provide both a current id and a current sl@0: * descriptor to use in querying the cache and factories, and sl@0: * determine the fallback strategy.

sl@0: * sl@0: *

ICUServiceKeys provide both a currentDescriptor and a currentID. sl@0: * The descriptor contains an optional prefix, followed by '/' sl@0: * and the currentID. Factories that handle complex keys, sl@0: * for example number format factories that generate multiple sl@0: * kinds of formatters for the same locale, use the descriptor sl@0: * to provide a fully unique identifier for the service object, sl@0: * while using the currentID (in this case, the locale string), sl@0: * as the visible IDs that can be localized.

sl@0: * sl@0: *

The default implementation of ICUServiceKey has no fallbacks and sl@0: * has no custom descriptors.

sl@0: */ sl@0: class U_COMMON_API ICUServiceKey : public UObject { sl@0: private: sl@0: const UnicodeString _id; sl@0: sl@0: protected: sl@0: static const UChar PREFIX_DELIMITER; sl@0: sl@0: public: sl@0: sl@0: /** sl@0: *

Construct a key from an id.

sl@0: * sl@0: * @param id the ID from which to construct the key. sl@0: */ sl@0: ICUServiceKey(const UnicodeString& id); sl@0: sl@0: /** sl@0: *

Virtual destructor.

sl@0: */ sl@0: virtual ~ICUServiceKey(); sl@0: sl@0: /** sl@0: *

Return the original ID used to construct this key.

sl@0: * sl@0: * @return the ID used to construct this key. sl@0: */ sl@0: virtual const UnicodeString& getID() const; sl@0: sl@0: /** sl@0: *

Return the canonical version of the original ID. This implementation sl@0: * appends the original ID to result. Result is returned as a convenience.

sl@0: * sl@0: * @param result the output parameter to which the id will be appended. sl@0: * @return the modified result. sl@0: */ sl@0: virtual UnicodeString& canonicalID(UnicodeString& result) const; sl@0: sl@0: /** sl@0: *

Return the (canonical) current ID. This implementation appends sl@0: * the canonical ID to result. Result is returned as a convenience.

sl@0: * sl@0: * @param result the output parameter to which the current id will be appended. sl@0: * @return the modified result. sl@0: */ sl@0: virtual UnicodeString& currentID(UnicodeString& result) const; sl@0: sl@0: /** sl@0: *

Return the current descriptor. This implementation appends sl@0: * the current descriptor to result. Result is returned as a convenience.

sl@0: * sl@0: *

The current descriptor is used to fully sl@0: * identify an instance of the service in the cache. A sl@0: * factory may handle all descriptors for an ID, or just a sl@0: * particular descriptor. The factory can either parse the sl@0: * descriptor or use custom API on the key in order to sl@0: * instantiate the service.

sl@0: * sl@0: * @param result the output parameter to which the current id will be appended. sl@0: * @return the modified result. sl@0: */ sl@0: virtual UnicodeString& currentDescriptor(UnicodeString& result) const; sl@0: sl@0: /** sl@0: *

If the key has a fallback, modify the key and return true, sl@0: * otherwise return false. The current ID will change if there sl@0: * is a fallback. No currentIDs should be repeated, and fallback sl@0: * must eventually return false. This implementation has no fallbacks sl@0: * and always returns false.

sl@0: * sl@0: * @return TRUE if the ICUServiceKey changed to a valid fallback value. sl@0: */ sl@0: virtual UBool fallback(); sl@0: sl@0: /** sl@0: *

Return TRUE if a key created from id matches, or would eventually sl@0: * fallback to match, the canonical ID of this ICUServiceKey.

sl@0: * sl@0: * @param id the id to test. sl@0: * @return TRUE if this ICUServiceKey's canonical ID is a fallback of id. sl@0: */ sl@0: virtual UBool isFallbackOf(const UnicodeString& id) const; sl@0: sl@0: /** sl@0: *

Return the prefix. This implementation leaves result unchanged. sl@0: * Result is returned as a convenience.

sl@0: * sl@0: * @param result the output parameter to which the prefix will be appended. sl@0: * @return the modified result. sl@0: */ sl@0: virtual UnicodeString& prefix(UnicodeString& result) const; sl@0: sl@0: /** sl@0: *

A utility to parse the prefix out of a descriptor string. Only sl@0: * the (undelimited) prefix, if any, remains in result. Result is returned as a sl@0: * convenience.

sl@0: * sl@0: * @param result an input/output parameter that on entry is a descriptor, and sl@0: * on exit is the prefix of that descriptor. sl@0: * @return the modified result. sl@0: */ sl@0: static UnicodeString& parsePrefix(UnicodeString& result); sl@0: sl@0: /** sl@0: *

A utility to parse the suffix out of a descriptor string. Only sl@0: * the (undelimited) suffix, if any, remains in result. Result is returned as a sl@0: * convenience.

sl@0: * sl@0: * @param result an input/output parameter that on entry is a descriptor, and sl@0: * on exit is the suffix of that descriptor. sl@0: * @return the modified result. sl@0: */ sl@0: static UnicodeString& parseSuffix(UnicodeString& result); sl@0: sl@0: public: sl@0: /** sl@0: * UObject RTTI boilerplate. sl@0: */ sl@0: static UClassID U_EXPORT2 getStaticClassID(); sl@0: sl@0: /** sl@0: * UObject RTTI boilerplate. sl@0: */ sl@0: virtual UClassID getDynamicClassID() const; sl@0: sl@0: #ifdef SERVICE_DEBUG sl@0: public: sl@0: virtual UnicodeString& debug(UnicodeString& result) const; sl@0: virtual UnicodeString& debugClass(UnicodeString& result) const; sl@0: #endif sl@0: sl@0: }; sl@0: sl@0: /******************************************************************* sl@0: * ICUServiceFactory sl@0: */ sl@0: sl@0: /** sl@0: *

An implementing ICUServiceFactory generates the service objects maintained by the sl@0: * service. A factory generates a service object from a key, sl@0: * updates id->factory mappings, and returns the display name for sl@0: * a supported id.

sl@0: */ sl@0: class U_COMMON_API ICUServiceFactory : public UObject { sl@0: public: sl@0: sl@0: /** sl@0: *

Create a service object from the key, if this factory sl@0: * supports the key. Otherwise, return NULL.

sl@0: * sl@0: *

If the factory supports the key, then it can call sl@0: * the service's getKey(ICUServiceKey, String[], ICUServiceFactory) method sl@0: * passing itself as the factory to get the object that sl@0: * the service would have created prior to the factory's sl@0: * registration with the service. This can change the sl@0: * key, so any information required from the key should sl@0: * be extracted before making such a callback.

sl@0: * sl@0: * @param key the service key. sl@0: * @param service the service with which this factory is registered. sl@0: * @param status the error code status. sl@0: * @return the service object, or NULL if the factory does not support the key. sl@0: */ sl@0: virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const = 0; sl@0: sl@0: /** sl@0: *

Update result to reflect the IDs (not descriptors) that this sl@0: * factory publicly handles. Result contains mappings from ID to sl@0: * factory. On entry it will contain all (visible) mappings from sl@0: * previously-registered factories.

sl@0: * sl@0: *

This function, together with getDisplayName, are used to sl@0: * support ICUService::getDisplayNames. The factory determines sl@0: * which IDs (of those it supports) it will make visible, and of sl@0: * those, which it will provide localized display names for. In sl@0: * most cases it will register mappings from all IDs it supports sl@0: * to itself.

sl@0: * sl@0: * @param result the mapping table to update. sl@0: * @param status the error code status. sl@0: */ sl@0: virtual void updateVisibleIDs(Hashtable& result, UErrorCode& status) const = 0; sl@0: sl@0: /** sl@0: *

Return, in result, the display name of the id in the provided locale. sl@0: * This is an id, not a descriptor. If the id is sl@0: * not visible, sets result to bogus. If the sl@0: * incoming result is bogus, it remains bogus. Result is returned as a sl@0: * convenience. Results are not defined if id is not one supported by this sl@0: * factory.

sl@0: * sl@0: * @param id a visible id supported by this factory. sl@0: * @param locale the locale for which to generate the corresponding localized display name. sl@0: * @param result output parameter to hold the display name. sl@0: * @return result. sl@0: */ sl@0: virtual UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const = 0; sl@0: }; sl@0: sl@0: /* sl@0: ****************************************************************** sl@0: */ sl@0: sl@0: /** sl@0: *

A default implementation of factory. This provides default sl@0: * implementations for subclasses, and implements a singleton sl@0: * factory that matches a single ID and returns a single sl@0: * (possibly deferred-initialized) instance. This implements sl@0: * updateVisibleIDs to add a mapping from its ID to itself sl@0: * if visible is true, or to remove any existing mapping sl@0: * for its ID if visible is false. No localization of display sl@0: * names is performed.

sl@0: */ sl@0: class U_COMMON_API SimpleFactory : public ICUServiceFactory { sl@0: protected: sl@0: UObject* _instance; sl@0: const UnicodeString _id; sl@0: const UBool _visible; sl@0: sl@0: public: sl@0: /** sl@0: *

Construct a SimpleFactory that maps a single ID to a single sl@0: * service instance. If visible is TRUE, the ID will be visible. sl@0: * The instance must not be NULL. The SimpleFactory will adopt sl@0: * the instance, which must not be changed subsequent to this call.

sl@0: * sl@0: * @param instanceToAdopt the service instance to adopt. sl@0: * @param id the ID to assign to this service instance. sl@0: * @param visible if TRUE, the ID will be visible. sl@0: */ sl@0: SimpleFactory(UObject* instanceToAdopt, const UnicodeString& id, UBool visible = TRUE); sl@0: sl@0: /** sl@0: *

Destructor.

sl@0: */ sl@0: virtual ~SimpleFactory(); sl@0: sl@0: /** sl@0: *

This implementation returns a clone of the service instance if the factory's ID is equal to sl@0: * the key's currentID. Service and prefix are ignored.

sl@0: * sl@0: * @param key the service key. sl@0: * @param service the service with which this factory is registered. sl@0: * @param status the error code status. sl@0: * @return the service object, or NULL if the factory does not support the key. sl@0: */ sl@0: virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

This implementation adds a mapping from ID -> this to result if visible is TRUE, sl@0: * otherwise it removes ID from result.

sl@0: * sl@0: * @param result the mapping table to update. sl@0: * @param status the error code status. sl@0: */ sl@0: virtual void updateVisibleIDs(Hashtable& result, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

This implementation returns the factory ID if it equals id and visible is TRUE, sl@0: * otherwise it returns the empty string. (This implementation provides sl@0: * no localized id information.)

sl@0: * sl@0: * @param id a visible id supported by this factory. sl@0: * @param locale the locale for which to generate the corresponding localized display name. sl@0: * @param result output parameter to hold the display name. sl@0: * @return result. sl@0: */ sl@0: virtual UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const; sl@0: sl@0: public: sl@0: /** sl@0: * UObject RTTI boilerplate. sl@0: */ sl@0: static UClassID U_EXPORT2 getStaticClassID(); sl@0: sl@0: /** sl@0: * UObject RTTI boilerplate. sl@0: */ sl@0: virtual UClassID getDynamicClassID() const; sl@0: sl@0: #ifdef SERVICE_DEBUG sl@0: public: sl@0: virtual UnicodeString& debug(UnicodeString& toAppendTo) const; sl@0: virtual UnicodeString& debugClass(UnicodeString& toAppendTo) const; sl@0: #endif sl@0: sl@0: }; sl@0: sl@0: /* sl@0: ****************************************************************** sl@0: */ sl@0: sl@0: /** sl@0: *

ServiceListener is the listener that ICUService provides by default. sl@0: * ICUService will notifiy this listener when factories are added to sl@0: * or removed from the service. Subclasses can provide sl@0: * different listener interfaces that extend EventListener, and modify sl@0: * acceptsListener and notifyListener as appropriate.

sl@0: */ sl@0: class U_COMMON_API ServiceListener : public EventListener { sl@0: public: sl@0: /** sl@0: *

This method is called when the service changes. At the time of the sl@0: * call this listener is registered with the service. It must sl@0: * not modify the notifier in the context of this call.

sl@0: * sl@0: * @param service the service that changed. sl@0: */ sl@0: virtual void serviceChanged(const ICUService& service) const = 0; sl@0: sl@0: public: sl@0: /** sl@0: * UObject RTTI boilerplate. sl@0: */ sl@0: static UClassID U_EXPORT2 getStaticClassID(); sl@0: sl@0: /** sl@0: * UObject RTTI boilerplate. sl@0: */ sl@0: virtual UClassID getDynamicClassID() const; sl@0: sl@0: }; sl@0: sl@0: /* sl@0: ****************************************************************** sl@0: */ sl@0: sl@0: /** sl@0: *

A StringPair holds a displayName/ID pair. ICUService uses it sl@0: * as the array elements returned by getDisplayNames. sl@0: */ sl@0: class U_COMMON_API StringPair : public UMemory { sl@0: public: sl@0: /** sl@0: *

The display name of the pair.

sl@0: */ sl@0: const UnicodeString displayName; sl@0: sl@0: /** sl@0: *

The ID of the pair.

sl@0: */ sl@0: const UnicodeString id; sl@0: sl@0: /** sl@0: *

Creates a string pair from a displayName and an ID.

sl@0: * sl@0: * @param displayName the displayName. sl@0: * @param id the ID. sl@0: * @param status the error code status. sl@0: * @return a StringPair if the creation was successful, otherwise NULL. sl@0: */ sl@0: static StringPair* create(const UnicodeString& displayName, sl@0: const UnicodeString& id, sl@0: UErrorCode& status); sl@0: sl@0: /** sl@0: *

Return TRUE if either string of the pair is bogus.

sl@0: * @return TRUE if either string of the pair is bogus. sl@0: */ sl@0: UBool isBogus() const; sl@0: sl@0: private: sl@0: StringPair(const UnicodeString& displayName, const UnicodeString& id); sl@0: }; sl@0: sl@0: /** sl@0: * Deleter for StringPairs sl@0: */ sl@0: U_CAPI void U_EXPORT2 sl@0: userv_deleteStringPair(void *obj); sl@0: sl@0: /** sl@0: * Opaque type returned by registerInstance and registerFactory. sl@0: */ sl@0: typedef const void* URegistryKey; sl@0: sl@0: /******************************************************************* sl@0: * ICUService sl@0: */ sl@0: sl@0: /** sl@0: *

A Service provides access to service objects that implement a sl@0: * particular service, e.g. transliterators. Users provide a String sl@0: * id (for example, a locale string) to the service, and get back an sl@0: * object for that id. Service objects can be any kind of object. A sl@0: * new service object is returned for each query. The caller is sl@0: * responsible for deleting it.

sl@0: * sl@0: *

Services 'canonicalize' the query ID and use the canonical ID to sl@0: * query for the service. The service also defines a mechanism to sl@0: * 'fallback' the ID multiple times. Clients can optionally request sl@0: * the actual ID that was matched by a query when they use an ID to sl@0: * retrieve a service object.

sl@0: * sl@0: *

Service objects are instantiated by ICUServiceFactory objects sl@0: * registered with the service. The service queries each sl@0: * ICUServiceFactory in turn, from most recently registered to sl@0: * earliest registered, until one returns a service object. If none sl@0: * responds with a service object, a fallback ID is generated, and the sl@0: * process repeats until a service object is returned or until the ID sl@0: * has no further fallbacks.

sl@0: * sl@0: *

In ICU 2.4, UObject (the base class of service instances) does sl@0: * not define a polymorphic clone function. ICUService uses clones to sl@0: * manage ownership. Thus, for now, ICUService defines an abstract sl@0: * method, cloneInstance, that clients must implement to create clones sl@0: * of the service instances. This may change in future releases of sl@0: * ICU.

sl@0: * sl@0: *

ICUServiceFactories can be dynamically registered and sl@0: * unregistered with the service. When registered, an sl@0: * ICUServiceFactory is installed at the head of the factory list, and sl@0: * so gets 'first crack' at any keys or fallback keys. When sl@0: * unregistered, it is removed from the service and can no longer be sl@0: * located through it. Service objects generated by this factory and sl@0: * held by the client are unaffected.

sl@0: * sl@0: *

If a service has variants (e.g., the different variants of sl@0: * BreakIterator) an ICUServiceFactory can use the prefix of the sl@0: * ICUServiceKey to determine the variant of a service to generate. sl@0: * If it does not support all variants, it can request sl@0: * previously-registered factories to handle the ones it does not sl@0: * support.

sl@0: * sl@0: *

ICUService uses ICUServiceKeys to query factories and perform sl@0: * fallback. The ICUServiceKey defines the canonical form of the ID, sl@0: * and implements the fallback strategy. Custom ICUServiceKeys can be sl@0: * defined that parse complex IDs into components that sl@0: * ICUServiceFactories can more easily use. The ICUServiceKey can sl@0: * cache the results of this parsing to save repeated effort. sl@0: * ICUService provides convenience APIs that take UnicodeStrings and sl@0: * generate default ICUServiceKeys for use in querying.

sl@0: * sl@0: *

ICUService provides API to get the list of IDs publicly sl@0: * supported by the service (although queries aren't restricted to sl@0: * this list). This list contains only 'simple' IDs, and not fully sl@0: * unique IDs. ICUServiceFactories are associated with each simple ID sl@0: * and the responsible factory can also return a human-readable sl@0: * localized version of the simple ID, for use in user interfaces. sl@0: * ICUService can also provide an array of the all the localized sl@0: * visible IDs and their corresponding internal IDs.

sl@0: * sl@0: *

ICUService implements ICUNotifier, so that clients can register sl@0: * to receive notification when factories are added or removed from sl@0: * the service. ICUService provides a default EventListener sl@0: * subinterface, ServiceListener, which can be registered with the sl@0: * service. When the service changes, the ServiceListener's sl@0: * serviceChanged method is called with the service as the sl@0: * argument.

sl@0: * sl@0: *

The ICUService API is both rich and generic, and it is expected sl@0: * that most implementations will statically 'wrap' ICUService to sl@0: * present a more appropriate API-- for example, to declare the type sl@0: * of the objects returned from get, to limit the factories that can sl@0: * be registered with the service, or to define their own listener sl@0: * interface with a custom callback method. They might also customize sl@0: * ICUService by overriding it, for example, to customize the sl@0: * ICUServiceKey and fallback strategy. ICULocaleService is a sl@0: * subclass of ICUService that uses Locale names as IDs and uses sl@0: * ICUServiceKeys that implement the standard resource bundle fallback sl@0: * strategy. Most clients will wish to subclass it instead of sl@0: * ICUService.

sl@0: */ sl@0: class U_COMMON_API ICUService : public ICUNotifier { sl@0: protected: sl@0: /** sl@0: * Name useful for debugging. sl@0: */ sl@0: const UnicodeString name; sl@0: sl@0: private: sl@0: sl@0: /** sl@0: * single lock used by this service. sl@0: */ sl@0: UMTX lock; sl@0: sl@0: /** sl@0: * Timestamp so iterators can be fail-fast. sl@0: */ sl@0: uint32_t timestamp; sl@0: sl@0: /** sl@0: * All the factories registered with this service. sl@0: */ sl@0: UVector* factories; sl@0: sl@0: /** sl@0: * The service cache. sl@0: */ sl@0: Hashtable* serviceCache; sl@0: sl@0: /** sl@0: * The ID cache. sl@0: */ sl@0: Hashtable* idCache; sl@0: sl@0: /** sl@0: * The name cache. sl@0: */ sl@0: DNCache* dnCache; sl@0: sl@0: /** sl@0: * Constructor. sl@0: */ sl@0: public: sl@0: /** sl@0: *

Construct a new ICUService.

sl@0: */ sl@0: ICUService(); sl@0: sl@0: /** sl@0: *

Construct with a name (useful for debugging).

sl@0: * sl@0: * @param name a name to use in debugging. sl@0: */ sl@0: ICUService(const UnicodeString& name); sl@0: sl@0: /** sl@0: *

Destructor.

sl@0: */ sl@0: virtual ~ICUService(); sl@0: sl@0: /** sl@0: *

Return the name of this service. This will be the empty string if none was assigned. sl@0: * Returns result as a convenience.

sl@0: * sl@0: * @param result an output parameter to contain the name of this service. sl@0: * @return the name of this service. sl@0: */ sl@0: UnicodeString& getName(UnicodeString& result) const; sl@0: sl@0: /** sl@0: *

Convenience override for get(ICUServiceKey&, UnicodeString*). This uses sl@0: * createKey to create a key for the provided descriptor.

sl@0: * sl@0: * @param descriptor the descriptor. sl@0: * @param status the error code status. sl@0: * @return the service instance, or NULL. sl@0: */ sl@0: UObject* get(const UnicodeString& descriptor, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Convenience override for get(ICUServiceKey&, UnicodeString*). This uses sl@0: * createKey to create a key from the provided descriptor.

sl@0: * sl@0: * @param descriptor the descriptor. sl@0: * @param actualReturn a pointer to a UnicodeString to hold the matched descriptor, or NULL. sl@0: * @param status the error code status. sl@0: * @return the service instance, or NULL. sl@0: */ sl@0: UObject* get(const UnicodeString& descriptor, UnicodeString* actualReturn, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Convenience override for get(ICUServiceKey&, UnicodeString*).

sl@0: * sl@0: * @param key the key. sl@0: * @param status the error code status. sl@0: * @return the service instance, or NULL. sl@0: */ sl@0: UObject* getKey(ICUServiceKey& key, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Given a key, return a service object, and, if actualReturn sl@0: * is not NULL, the descriptor with which it was found in the sl@0: * first element of actualReturn. If no service object matches sl@0: * this key, returns NULL and leaves actualReturn unchanged.

sl@0: * sl@0: *

This queries the cache using the key's descriptor, and if no sl@0: * object in the cache matches, tries the key on each sl@0: * registered factory, in order. If none generates a service sl@0: * object for the key, repeats the process with each fallback of sl@0: * the key, until either a factory returns a service object, or the key sl@0: * has no fallback. If no object is found, the result of handleDefault sl@0: * is returned.

sl@0: * sl@0: *

Subclasses can override this method to further customize the sl@0: * result before returning it. sl@0: * sl@0: * @param key the key. sl@0: * @param actualReturn a pointer to a UnicodeString to hold the matched descriptor, or NULL. sl@0: * @param status the error code status. sl@0: * @return the service instance, or NULL. sl@0: */ sl@0: virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

This version of getKey is only called by ICUServiceFactories within the scope sl@0: * of a previous getKey call, to determine what previously-registered factories would sl@0: * have returned. For details, see getKey(ICUServiceKey&, UErrorCode&). Subclasses sl@0: * should not call it directly, but call through one of the other get functions.

sl@0: * sl@0: * @param key the key. sl@0: * @param actualReturn a pointer to a UnicodeString to hold the matched descriptor, or NULL. sl@0: * @param factory the factory making the recursive call. sl@0: * @param status the error code status. sl@0: * @return the service instance, or NULL. sl@0: */ sl@0: UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUServiceFactory* factory, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Convenience override for getVisibleIDs(String) that passes null sl@0: * as the fallback, thus returning all visible IDs.

sl@0: * sl@0: * @param result a vector to hold the returned IDs. sl@0: * @param status the error code status. sl@0: * @return the result vector. sl@0: */ sl@0: UVector& getVisibleIDs(UVector& result, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Return a snapshot of the visible IDs for this service. This sl@0: * list will not change as ICUServiceFactories are added or removed, but the sl@0: * supported IDs will, so there is no guarantee that all and only sl@0: * the IDs in the returned list will be visible and supported by the sl@0: * service in subsequent calls.

sl@0: * sl@0: *

The IDs are returned as pointers to UnicodeStrings. The sl@0: * caller owns the IDs. Previous contents of result are discarded before sl@0: * new elements, if any, are added.

sl@0: * sl@0: *

matchID is passed to createKey to create a key. If the key sl@0: * is not NULL, its isFallbackOf method is used to filter out IDs sl@0: * that don't match the key or have it as a fallback.

sl@0: * sl@0: * @param result a vector to hold the returned IDs. sl@0: * @param matchID an ID used to filter the result, or NULL if all IDs are desired. sl@0: * @param status the error code status. sl@0: * @return the result vector. sl@0: */ sl@0: UVector& getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Convenience override for getDisplayName(const UnicodeString&, const Locale&, UnicodeString&) that sl@0: * uses the current default locale.

sl@0: * sl@0: * @param id the ID for which to retrieve the localized displayName. sl@0: * @param result an output parameter to hold the display name. sl@0: * @return the modified result. sl@0: */ sl@0: UnicodeString& getDisplayName(const UnicodeString& id, UnicodeString& result) const; sl@0: sl@0: /** sl@0: *

Given a visible ID, return the display name in the requested locale. sl@0: * If there is no directly supported ID corresponding to this ID, result is sl@0: * set to bogus.

sl@0: * sl@0: * @param id the ID for which to retrieve the localized displayName. sl@0: * @param result an output parameter to hold the display name. sl@0: * @param locale the locale in which to localize the ID. sl@0: * @return the modified result. sl@0: */ sl@0: UnicodeString& getDisplayName(const UnicodeString& id, UnicodeString& result, const Locale& locale) const; sl@0: sl@0: /** sl@0: *

Convenience override of getDisplayNames(const Locale&, const UnicodeString*) that sl@0: * uses the current default Locale as the locale and NULL for sl@0: * the matchID.

sl@0: * sl@0: * @param result a vector to hold the returned displayName/id StringPairs. sl@0: * @param status the error code status. sl@0: * @return the modified result vector. sl@0: */ sl@0: UVector& getDisplayNames(UVector& result, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Convenience override of getDisplayNames(const Locale&, const UnicodeString*) that sl@0: * uses NULL for the matchID.

sl@0: * sl@0: * @param result a vector to hold the returned displayName/id StringPairs. sl@0: * @param locale the locale in which to localize the ID. sl@0: * @param status the error code status. sl@0: * @return the modified result vector. sl@0: */ sl@0: UVector& getDisplayNames(UVector& result, const Locale& locale, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Return a snapshot of the mapping from display names to visible sl@0: * IDs for this service. This set will not change as factories sl@0: * are added or removed, but the supported IDs will, so there is sl@0: * no guarantee that all and only the IDs in the returned map will sl@0: * be visible and supported by the service in subsequent calls, sl@0: * nor is there any guarantee that the current display names match sl@0: * those in the result.

sl@0: * sl@0: *

The names are returned as pointers to StringPairs, which sl@0: * contain both the displayName and the corresponding ID. The sl@0: * caller owns the StringPairs. Previous contents of result are sl@0: * discarded before new elements, if any, are added.

sl@0: * sl@0: *

matchID is passed to createKey to create a key. If the key sl@0: * is not NULL, its isFallbackOf method is used to filter out IDs sl@0: * that don't match the key or have it as a fallback.

sl@0: * sl@0: * @param result a vector to hold the returned displayName/id StringPairs. sl@0: * @param locale the locale in which to localize the ID. sl@0: * @param matchID an ID used to filter the result, or NULL if all IDs are desired. sl@0: * @param status the error code status. sl@0: * @return the result vector. */ sl@0: UVector& getDisplayNames(UVector& result, sl@0: const Locale& locale, sl@0: const UnicodeString* matchID, sl@0: UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

A convenience override of registerInstance(UObject*, const UnicodeString&, UBool) sl@0: * that defaults visible to TRUE.

sl@0: * sl@0: * @param objToAdopt the object to register and adopt. sl@0: * @param id the ID to assign to this object. sl@0: * @param status the error code status. sl@0: * @return a registry key that can be passed to unregister to unregister sl@0: * (and discard) this instance. sl@0: */ sl@0: URegistryKey registerInstance(UObject* objToAdopt, const UnicodeString& id, UErrorCode& status); sl@0: sl@0: /** sl@0: *

Register a service instance with the provided ID. The ID will be sl@0: * canonicalized. The canonicalized ID will be returned by sl@0: * getVisibleIDs if visible is TRUE. The service instance will be adopted and sl@0: * must not be modified subsequent to this call.

sl@0: * sl@0: *

This issues a serviceChanged notification to registered listeners.

sl@0: * sl@0: *

This implementation wraps the object using sl@0: * createSimpleFactory, and calls registerFactory.

sl@0: * sl@0: * @param objToAdopt the object to register and adopt. sl@0: * @param id the ID to assign to this object. sl@0: * @param visible TRUE if getVisibleIDs is to return this ID. sl@0: * @param status the error code status. sl@0: * @return a registry key that can be passed to unregister() to unregister sl@0: * (and discard) this instance. sl@0: */ sl@0: virtual URegistryKey registerInstance(UObject* objToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status); sl@0: sl@0: /** sl@0: *

Register an ICUServiceFactory. Returns a registry key that sl@0: * can be used to unregister the factory. The factory sl@0: * must not be modified subsequent to this call. The service owns sl@0: * all registered factories. In case of an error, the factory is sl@0: * deleted.

sl@0: * sl@0: *

This issues a serviceChanged notification to registered listeners.

sl@0: * sl@0: *

The default implementation accepts all factories.

sl@0: * sl@0: * @param factoryToAdopt the factory to register and adopt. sl@0: * @param status the error code status. sl@0: * @return a registry key that can be passed to unregister to unregister sl@0: * (and discard) this factory. sl@0: */ sl@0: virtual URegistryKey registerFactory(ICUServiceFactory* factoryToAdopt, UErrorCode& status); sl@0: sl@0: /** sl@0: *

Unregister a factory using a registry key returned by sl@0: * registerInstance or registerFactory. After a successful call, sl@0: * the factory will be removed from the service factory list and sl@0: * deleted, and the key becomes invalid.

sl@0: * sl@0: *

This issues a serviceChanged notification to registered sl@0: * listeners.

sl@0: * sl@0: * @param rkey the registry key. sl@0: * @param status the error code status. sl@0: * @return TRUE if the call successfully unregistered the factory. sl@0: */ sl@0: virtual UBool unregister(URegistryKey rkey, UErrorCode& status); sl@0: sl@0: /** sl@0: *

Reset the service to the default factories. The factory sl@0: * lock is acquired and then reInitializeFactories is called.

sl@0: * sl@0: *

This issues a serviceChanged notification to registered listeners.

sl@0: */ sl@0: virtual void reset(void); sl@0: sl@0: /** sl@0: *

Return TRUE if the service is in its default state.

sl@0: * sl@0: *

The default implementation returns TRUE if there are no sl@0: * factories registered.

sl@0: */ sl@0: virtual UBool isDefault(void) const; sl@0: sl@0: /** sl@0: *

Create a key from an ID. If ID is NULL, returns NULL.

sl@0: * sl@0: *

The default implementation creates an ICUServiceKey instance. sl@0: * Subclasses can override to define more useful keys appropriate sl@0: * to the factories they accept.

sl@0: * sl@0: * @param a pointer to the ID for which to create a default ICUServiceKey. sl@0: * @param status the error code status. sl@0: * @return the ICUServiceKey corresponding to ID, or NULL. sl@0: */ sl@0: virtual ICUServiceKey* createKey(const UnicodeString* id, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Clone object so that caller can own the copy. In ICU2.4, UObject doesn't define sl@0: * clone, so we need an instance-aware method that knows how to do this. sl@0: * This is public so factories can call it, but should really be protected.

sl@0: * sl@0: * @param instance the service instance to clone. sl@0: * @return a clone of the passed-in instance, or NULL if cloning was unsuccessful. sl@0: */ sl@0: virtual UObject* cloneInstance(UObject* instance) const = 0; sl@0: sl@0: sl@0: /************************************************************************ sl@0: * Subclassing API sl@0: */ sl@0: sl@0: protected: sl@0: sl@0: /** sl@0: *

Create a factory that wraps a single service object. Called by registerInstance.

sl@0: * sl@0: *

The default implementation returns an instance of SimpleFactory.

sl@0: * sl@0: * @param instanceToAdopt the service instance to adopt. sl@0: * @param id the ID to assign to this service instance. sl@0: * @param visible if TRUE, the ID will be visible. sl@0: * @param status the error code status. sl@0: * @return an instance of ICUServiceFactory that maps this instance to the provided ID. sl@0: */ sl@0: virtual ICUServiceFactory* createSimpleFactory(UObject* instanceToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status); sl@0: sl@0: /** sl@0: *

Reinitialize the factory list to its default state. After this call, isDefault() sl@0: * must return TRUE.

sl@0: * sl@0: *

This issues a serviceChanged notification to registered listeners.

sl@0: * sl@0: *

The default implementation clears the factory list. sl@0: * Subclasses can override to provide other default initialization sl@0: * of the factory list. Subclasses must not call this method sl@0: * directly, since it must only be called while holding write sl@0: * access to the factory list.

sl@0: */ sl@0: virtual void reInitializeFactories(void); sl@0: sl@0: /** sl@0: *

Default handler for this service if no factory in the factory list sl@0: * handled the key passed to getKey.

sl@0: * sl@0: *

The default implementation returns NULL.

sl@0: * sl@0: * @param key the key. sl@0: * @param actualReturn a pointer to a UnicodeString to hold the matched descriptor, or NULL. sl@0: * @param status the error code status. sl@0: * @return the service instance, or NULL. sl@0: */ sl@0: virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Clear caches maintained by this service.

sl@0: * sl@0: *

Subclasses can override if they implement additional caches sl@0: * that need to be cleared when the service changes. Subclasses sl@0: * should generally not call this method directly, as it must only sl@0: * be called while synchronized on the factory lock.

sl@0: */ sl@0: virtual void clearCaches(void); sl@0: sl@0: /** sl@0: *

Return true if the listener is accepted.

sl@0: * sl@0: *

The default implementation accepts the listener if it is sl@0: * a ServiceListener. Subclasses can override this to accept sl@0: * different listeners.

sl@0: * sl@0: * @param l the listener to test. sl@0: * @return TRUE if the service accepts the listener. sl@0: */ sl@0: virtual UBool acceptsListener(const EventListener& l) const; sl@0: sl@0: /** sl@0: *

Notify the listener of a service change.

sl@0: * sl@0: *

The default implementation assumes a ServiceListener. sl@0: * If acceptsListener has been overridden to accept different sl@0: * listeners, this should be overridden as well.

sl@0: * sl@0: * @param l the listener to notify. sl@0: */ sl@0: virtual void notifyListener(EventListener& l) const; sl@0: sl@0: /************************************************************************ sl@0: * Utilities for subclasses. sl@0: */ sl@0: sl@0: /** sl@0: *

Clear only the service cache.

sl@0: * sl@0: *

This can be called by subclasses when a change affects the service sl@0: * cache but not the ID caches, e.g., when the default locale changes sl@0: * the resolution of IDs also changes, requiring the cache to be sl@0: * flushed, but not the visible IDs themselves.

sl@0: */ sl@0: void clearServiceCache(void); sl@0: sl@0: /** sl@0: *

Return a map from visible IDs to factories. sl@0: * This must only be called when the mutex is held.

sl@0: * sl@0: * @param status the error code status. sl@0: * @return a Hashtable containing mappings from visible sl@0: * IDs to factories. sl@0: */ sl@0: const Hashtable* getVisibleIDMap(UErrorCode& status) const; sl@0: sl@0: /** sl@0: *

Allow subclasses to read the time stamp.

sl@0: * sl@0: * @return the timestamp. sl@0: */ sl@0: int32_t getTimestamp(void) const; sl@0: sl@0: /** sl@0: *

Return the number of registered factories.

sl@0: * sl@0: * @return the number of factories registered at the time of the call. sl@0: */ sl@0: int32_t countFactories(void) const; sl@0: sl@0: private: sl@0: sl@0: friend class ::ICUServiceTest; // give tests access to countFactories. sl@0: }; sl@0: sl@0: U_NAMESPACE_END sl@0: sl@0: /* UCONFIG_NO_SERVICE */ sl@0: #endif sl@0: sl@0: /* ICUSERV_H */ sl@0: #endif sl@0: