00001 /* -*- Mode: C++ -*- 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 2002 Net Integration Technologies, Inc. 00004 * 00005 * A UniConf key management abstraction. 00006 */ 00007 #ifndef __UNICONFGEN_H 00008 #define __UNICONFGEN_H 00009 00010 #include "uniconfkey.h" 00011 #include "wvcallback.h" 00012 #include "wvxplc.h" 00013 #include "wvlinklist.h" 00014 #include "uniconfpair.h" 00015 00016 class UniConfGen; 00017 00018 /** 00019 * The callback type for signalling key changes from a UniConfGen. 00020 * 00021 * Generators that wrap other generators should catch notifications 00022 * and reissue them using themselves as the "gen" parameter and their 00023 * userdata as the "userdata parameter". This can be done effectively by 00024 * invoking the delta() function on receipt of a notification from a 00025 * wrapped generator. See UniFilterGen. 00026 * 00027 * Parameters: gen, key, userdata 00028 * gen - the externally visible generator whose key has changed 00029 * key - the key that has changed 00030 * userdata - the userdata supplied during setcallback 00031 */ 00032 typedef WvCallback<void, const UniConfKey &, 00033 WvStringParm, void *> UniConfGenCallback; 00034 00035 /** 00036 * An abstract data container that backs a UniConf tree. 00037 * 00038 * This is intended to be implemented to provide support for fetching 00039 * and storing keys and values using different access methods. 00040 * 00041 */ 00042 class UniConfGen : public GenericComponent<IObject> 00043 { 00044 // These fields are deliberately hidden to encourage use of the 00045 // special notification members 00046 00047 UniConfGenCallback cb; //!< gets called whenever a key changes its value. 00048 void *cbdata; 00049 int hold_nesting; 00050 UniConfPairList deltas; 00051 00052 protected: 00053 /** Creates a UniConfGen object. */ 00054 UniConfGen(); 00055 00056 /** Raises an error condition. */ 00057 void seterror(WvStringParm error) 00058 { } // FIXME: decide on final API for this probably WvError 00059 00060 public: 00061 /** Destroys the UniConfGen and may discard uncommitted data. */ 00062 virtual ~UniConfGen(); 00063 00064 /***** Notification API *****/ 00065 00066 /** 00067 * Sets the callback for change notification. 00068 * Must not be reimplemented by subclasses. 00069 */ 00070 void setcallback(const UniConfGenCallback &callback, void *userdata); 00071 00072 /** 00073 * Immediately sends notification that a key has possibly changed. 00074 * Takes care of the details of invoking the callback. 00075 * 00076 * Note: You probably want to be using delta() instead. 00077 */ 00078 void dispatch_delta(const UniConfKey &key, WvStringParm value); 00079 00080 /** 00081 * Pauses notifications until matched with a call to unhold_delta(). 00082 * 00083 * While paused, notification events are placed into a pending list. 00084 * Redundant notifications may be discarded. 00085 * 00086 * Use this to safeguard non-reentrant code. 00087 */ 00088 void hold_delta(); 00089 00090 /** 00091 * Resumes notifications when each hold_delta() has been matched. 00092 * 00093 * On resumption, dispatches all pending notifications except 00094 * those that were destined to watches that were removed. 00095 * 00096 * Use this to safeguard non-reentrant code. 00097 */ 00098 void unhold_delta(); 00099 00100 /** 00101 * Clears the list of pending notifications without sending them. 00102 * Does not affect the hold nesting count. 00103 */ 00104 void clear_delta(); 00105 00106 /** 00107 * Flushes the list of pending notifications by sending them. 00108 * Does not affect the hold nesting count. 00109 */ 00110 void flush_delta(); 00111 00112 /** 00113 * Call this when a key's value or children have possibly changed. 00114 * 00115 * If the hold nesting count is 0, the notification is sent immediately. 00116 * Otherwise it is added to a pending list for later. 00117 */ 00118 void delta(const UniConfKey &key, WvStringParm value); 00119 00120 /***** Status API *****/ 00121 00122 /** 00123 * Determines if the generator is usable and working properly. 00124 * 00125 * The default implementation always returns true. 00126 */ 00127 virtual bool isok(); 00128 00129 00130 /***** Key Persistence API *****/ 00131 00132 /** 00133 * Commits any changes. The default implementation does nothing. 00134 */ 00135 virtual void commit() { } 00136 00137 /** 00138 * Refreshes information about a key recursively. 00139 * May discard uncommitted data. 00140 * 00141 * The default implementation always returns true. 00142 */ 00143 virtual bool refresh() { return true; } 00144 00145 00146 /***** Key Retrieval API *****/ 00147 00148 /** 00149 * Fetches a string value for a key from the registry. If the key doesn't 00150 * exist, the return value is WvString::null. 00151 */ 00152 virtual WvString get(const UniConfKey &key) = 0; 00153 00154 /** 00155 * Without fetching its value, returns true if a key exists. 00156 * 00157 * This is provided because it is often more efficient to 00158 * test existance than to actually retrieve the value. 00159 * 00160 * The default implementation returns !get(key).isnull(). 00161 */ 00162 virtual bool exists(const UniConfKey &key); 00163 00164 00165 /** 00166 * Converts a string to an integer. If the string is null or not 00167 * recognized, return defvalue. 00168 * 00169 * This is here to support the common str2int(get(key)). 00170 * 00171 * The default implementation recognizes the booleans 'true', 'yes', 'on' 00172 * and 'enabled' as 1, and 'false', 'no', 'off' and 'disabled' as 0. 00173 */ 00174 virtual int str2int(WvStringParm s, int defvalue) const; 00175 00176 00177 /***** Key Storage API *****/ 00178 00179 /** 00180 * Stores a string value for a key into the registry. If the value is 00181 * WvString::null, the key is deleted. 00182 * 00183 * Returns true on success. 00184 */ 00185 virtual void set(const UniConfKey &key, WvStringParm value) = 0; 00186 00187 00188 /***** Key Enumeration API *****/ 00189 00190 /** 00191 * Returns true if a key has children. 00192 * 00193 * This is provided because it is often more efficient to 00194 * test existance than to actually retrieve the keys. 00195 * 00196 * The default implementation uses the iterator returned by iterator() 00197 * to test whether the child has any keys. 00198 * Subclasses are strongly encouraged to provide a better implementation. 00199 */ 00200 virtual bool haschildren(const UniConfKey &key); 00201 00202 /** The abstract iterator type (see below) */ 00203 class Iter; 00204 00205 /** A concrete null iterator type (see below) */ 00206 class NullIter; 00207 00208 /** 00209 * Returns an iterator over the children of the specified key. 00210 * Must not return NULL; consider returning a NullIter instead. 00211 * 00212 * The caller takes ownership of the returned iterator and is responsible 00213 * for deleting it when finished. 00214 */ 00215 virtual Iter *iterator(const UniConfKey &key) = 0; 00216 }; 00217 00218 DEFINE_XIID(UniConfGen, {0x7ca76e98, 0xb694, 0x43ca, 00219 {0xb0, 0x56, 0x8b, 0x9d, 0xde, 0x9a, 0xbe, 0x9f}}); 00220 DeclareWvList(UniConfGen); 00221 00222 00223 /** 00224 * An abstract iterator over keys and values in a generator. 00225 * 00226 * Unlike other WvStreams iterators, this one declares virtual methods so 00227 * that UniConfGen implementations can supply the right behaviour 00228 * through a common interface that does not depend on static typing. 00229 * 00230 * The precise traversal sequence is defined by the iterator implementation. 00231 * 00232 * The iterator need not support concurrent modifications of the underlying 00233 * data structures. 00234 * 00235 * TODO: Consider changing this rule depending on observed usage patterns. 00236 */ 00237 class UniConfGen::Iter 00238 { 00239 public: 00240 /** Destroys the iterator. */ 00241 virtual ~Iter() { } 00242 00243 /** 00244 * Rewinds the iterator. 00245 * Must be called prior to the first invocation of next(). 00246 */ 00247 virtual void rewind() = 0; 00248 00249 /** 00250 * Seeks to the next element in the sequence. 00251 * Returns true if that element exists. 00252 * Must be called prior to the first invocation of key(). 00253 */ 00254 virtual bool next() = 0; 00255 00256 /** Returns the current key. */ 00257 virtual UniConfKey key() const = 0; 00258 }; 00259 00260 00261 /** 00262 * An iterator that's always empty. 00263 * This is handy if you don't have anything good to iterate over. 00264 */ 00265 class UniConfGen::NullIter : public UniConfGen::Iter 00266 { 00267 public: 00268 /***** Overridden members *****/ 00269 00270 virtual void rewind() { } 00271 virtual bool next() { return false; } 00272 virtual UniConfKey key() const { return UniConfKey::EMPTY; } 00273 }; 00274 00275 #endif // UNICONFGEN_H