00001 /* 00002 00003 This file is part of the Virtual Object System of 00004 the Interreality project (http://interreality.org). 00005 00006 Copyright (C) 2001-2003 Peter Amstutz 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Lesser General Public 00010 License as published by the Free Software Foundation; either 00011 version 2 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Lesser General Public License for more details. 00017 00018 You should have received a copy of the GNU Lesser General Public 00019 License along with this library; if not, write to the Free Software 00020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 00022 Peter Amstutz <tetron@interreality.org> 00023 */ 00024 00025 #ifndef _VOBJECT_HH_ 00026 #define _VOBJECT_HH_ 00027 00028 /** @file 00029 Defines Vobject and VobjectImplementation. 00030 */ 00031 00032 #include <vos/corelibs/vos/refcount.hh> 00033 #include <vos/corelibs/vos/url.hh> // Need this for the exception 00034 #include <vos/corelibs/vos/log.hh> 00035 00036 #include <deque> 00037 #include <stdexcept> 00038 00039 /** Virtual Object System core library */ 00040 00041 namespace VOS 00042 { 00043 class Site; 00044 class Message; 00045 class MessageBlock; 00046 class TypeChangeListener; 00047 class ParentChangeListener; 00048 class ChildChangeListener; 00049 00050 /** @class Vobject vobject.hh vos/corelibs/vos/vobject.hh 00051 * 00052 * This is the abstract class that defines the basic API common to 00053 all virtual objects. 00054 */ 00055 class VOS_API Vobject : public virtual RefCounted 00056 { 00057 public: 00058 /** This structure expresses the relation between a parent vobject 00059 and a vobject which is a child of that parent. 00060 */ 00061 class ParentChildRelation : public virtual RefCounted 00062 { 00063 public: 00064 ParentChildRelation(Vobject* c, Vobject* p) : child(c), parent(p) { 00065 child->acquire(); // released by: ParentChildRelation() destructor 00066 parent->acquire(); // released by: ParentChildRelation() destructor 00067 } 00068 ~ParentChildRelation() { 00069 if(parent && child) { 00070 LOG("vobject", 4, "deleting edge between child " << child->getURL().getString() 00071 << " and parent " << parent->getURL().getString()); 00072 } else if(parent) { 00073 LOG("vobject", 4, "deleting dangling edge from parent " << parent->getURL().getString()); 00074 } else if(child) { 00075 LOG("vobject", 4, "deleting dangling edge to child " << child->getURL().getString()); 00076 } 00077 00078 if(child) child->release(); // acquired by: ParentChildRelation() constructor 00079 if(parent) parent->release(); // acquired by: ParentChildRelation() constructor 00080 } 00081 int position; /**< the position of the child in the parent's child list */ 00082 string contextual_name; /**< the contextual name of the child in the parent's child list */ 00083 Vobject* child; /**< the child object in question */ 00084 Vobject* parent; /**< the parent object in question */ 00085 /** This class is used internally to compare two ParentChildRelation structures 00086 to see if they represent the same relationship. 00087 */ 00088 class Cmp { 00089 public: 00090 /** Compares two ParentChildRelation classes. 00091 @param p left structure 00092 @param q right 00093 @return true if "p < q"; if the two are equal then ("p < q" || "q < p") is false. 00094 */ 00095 inline bool operator()(const ParentChildRelation* p, const ParentChildRelation* q) const { 00096 if(p->parent == q->parent) return (p->position < q->position); 00097 else return (p->parent < q->parent); 00098 }; 00099 }; 00100 }; 00101 00102 typedef set<Vobject::ParentChildRelation*, Vobject::ParentChildRelation::Cmp> ParentSet; 00103 typedef deque<Vobject::ParentChildRelation*> ChildList; 00104 typedef set<string> TypeSet; 00105 00106 /** An exception class thrown when the user attempts to read 00107 from the receiving queue and that queue is empty. */ 00108 class MessageQueueEmptyError : public runtime_error { 00109 public: 00110 MessageQueueEmptyError(const string& s) : runtime_error(s) { }; 00111 }; 00112 00113 /** An exception class thrown when a site lookup fails. */ 00114 class NoSuchSiteError : public runtime_error { 00115 public: 00116 NoSuchSiteError(const string& s) : runtime_error(s) { }; 00117 }; 00118 00119 /** An exception class thrown when an object lookup fails. */ 00120 class NoSuchObjectError : public runtime_error { 00121 public: 00122 NoSuchObjectError(const string& s) : runtime_error(s) { }; 00123 }; 00124 00125 class AccessControlError : public runtime_error { 00126 public: 00127 AccessControlError(const string& s) : runtime_error(s) { }; 00128 }; 00129 00130 /** An exception class thrown when a remote action fails. */ 00131 class RemoteError : public runtime_error { 00132 public: 00133 RemoteError(const string& s) : runtime_error(s) { }; 00134 }; 00135 00136 /** An exception class thrown when an expected reply didn't arrive in the alloted time. */ 00137 class TimeoutError : public RemoteError { 00138 public: 00139 TimeoutError(const string& s) : RemoteError(s) { }; 00140 }; 00141 00142 /** Get the site name of this object. 00143 @return the name string 00144 */ 00145 virtual const string& getName() = 0; 00146 00147 /** Get the site this object resides on. 00148 @return the site object. NOTE YOU MUST CALL release() WHEN DONE OR USE A rREF() BLOCK 00149 */ 00150 virtual Site& getSite() = 0; 00151 00152 /** Get the URL path (in the form "vop://site/name") 00153 @return the URL 00154 */ 00155 virtual const URL& getURL() = 0; 00156 00157 /** Return true if this object is local, false if not 00158 @return whether it is local 00159 */ 00160 virtual bool isLocal() = 0; 00161 00162 /** Return true if this object is remote, false if not 00163 @return whether it is remote 00164 */ 00165 virtual bool isRemote() = 0; 00166 00167 /** Return a set of type names for the types supported by this object. 00168 @return the set of type names 00169 */ 00170 virtual const TypeSet& getTypes() throw (AccessControlError, RemoteError) = 0; 00171 00172 /** Adds a new type to this object's type set. This only changes 00173 the stored set of type name strings and does not necessarily 00174 affect the actual code behind the object. See the Local Site 00175 class for information about extending the actual functionality 00176 of an existing meta objects. 00177 @param s the type string 00178 */ 00179 virtual void addType(const string& s) = 0; 00180 00181 /** Get the set of parent-child relationships in which this object is the child. 00182 @return a set of parent-child relations 00183 */ 00184 virtual const ParentSet& getParents() 00185 throw (AccessControlError, RemoteError) = 0; 00186 00187 /** Get the set of parent-child relationships in which this object is the parent. 00188 @return a set of parent-child relations 00189 00190 @warning You should <em>always</em> assign the results of 00191 getChildren to a variable. Do NOT do this: 00192 @code 00193 for(Vobject::ChildList::const_iterator i = v->getChildren().begin(); 00194 i != v->getChildren().end(); i++) { 00195 ... 00196 } 00197 @endcode 00198 Instead, you should do this: 00199 @code 00200 const ChildList& cl = v->getChildren(); 00201 for(Vobject::ChildList::const_iterator i = cl.begin(); i != cl.end(); i++) { 00202 ... 00203 } 00204 @endcode 00205 The reason for this is that if vobj is remote, each call to 00206 getChildren() may trigger a remote call. In addition to being 00207 inefficient, this will wipe and replace the child list you are 00208 in the midst of using, which will probably invalidate the 00209 iterator and cause your program to crash. 00210 00211 */ 00212 virtual const ChildList& getChildren() throw (AccessControlError, RemoteError) = 0; 00213 00214 /** Sends a message to the object. This may trigger immediate 00215 processing of the message if the object is local. 00216 @param m A pointer to the message which is being sent. Its reference count will be increased as necssary. 00217 */ 00218 virtual void sendMessage(Message* m) = 0; 00219 00220 /** Sends a block of messages to the object. This may trigger immediate 00221 processing of the message if the object is local. 00222 @param m A pointer to the message which is being sent. Its reference count will be increased as necssary. 00223 */ 00224 virtual void sendMessage(MessageBlock* m) = 0; 00225 00226 /** Gets the next message the object has received. 00227 @throws MessageQueueEmptyError If the message queue is empty. 00228 This may be the case if there are no messages available or if 00229 the user has set DoNotQueueMsgs to true in 00230 VobjectImplementation. 00231 @return the message. NOTE YOU MUST CALL release() WHEN DONE OR USE vRef! 00232 */ 00233 virtual Message* receiveMessage() throw (MessageQueueEmptyError) = 0; 00234 00235 /** Returns if the object has a message available to be dequeued by receiveMessage(). 00236 @return True if receiveMessage will succeed, false if receiveMessage will throw an exception. 00237 */ 00238 virtual bool hasMessageAvailable() = 0; 00239 00240 /** Gets the next message the update object has received. Update 00241 messages are special in that they consist of messages sent 00242 from remote sites to update changes to our local cache. 00243 @param m A pointer to the message which is being sent. Its reference count will be increased as necssary. 00244 */ 00245 virtual void sendUpdateMessage(Message* m) = 0; 00246 00247 /** Gets the next update message the object has received. 00248 @throws MessageQueueEmptyError If the message queue is empty. 00249 This may be the case if there are no messages available or if 00250 the user has set DoNotQueueUpdateMsgs to true in 00251 VobjectImplementation. 00252 @return the message. NOTE YOU MUST CALL release() WHEN DONE OR USE vRef! 00253 */ 00254 virtual Message* receiveUpdateMessage() throw (MessageQueueEmptyError) = 0; 00255 00256 /** Returns if the object has a message available to be dequeued 00257 by receiveUpdateMessage(). 00258 @return True if receiveMessage() will succeed, false if 00259 receiveMessage will throw an exception. 00260 */ 00261 virtual bool hasUpdateMessageAvailable() = 0; 00262 00263 /** Searchs and returns some object, given a rooted path (that is, 00264 in the form "vop://site:port/child1/child2/etc"). See 00265 findObject() for more information about paths. 00266 @param path the path to the object we want to find 00267 @return the object, if found. NOTE YOU MUST CALL release() WHEN DONE OR USE A rREF() BLOCK 00268 @throws NoSuchSiteError The DNS lookup for the site failed, 00269 the site is listening on the expected port, or the site 00270 otherwise could not be connected to 00271 @throws NoSuchObjectError if that object path does not exist on the site 00272 @throws URL::BadURLError if there is a syntax error in the supplied URL 00273 @throws AccessControlError if the site reported that the user is not allowed that information 00274 */ 00275 static Vobject& findObjectFromRoot(const string& path) 00276 throw (NoSuchSiteError, NoSuchObjectError, URL::BadURLError, AccessControlError, RemoteError); 00277 00278 /** Searchs and returns some object similarly to 00279 findObjectFromRoot(). However, if the path does not start 00280 with the string "vop://" the path will be intepreted as 00281 relative to this object. For example, "foo/bar" will find the 00282 first child object named "foo" of this object, then the first 00283 child named "bar" of the "foo" object and return it. If there 00284 is a leading slash, the path is relative to the object's site, 00285 so "/foo/bar" does @em not necessarily mean the same thing. 00286 Note that there should never be a slash at the end, so "foo/" 00287 is NOT a legal path. Finally, instead of using child names, 00288 one may use "\#position", starting from zero. So "\#0" refers 00289 to the first child of this object, "\#1" to the second etc. 00290 Obviously if the number in \#position is larger than the 00291 number of children, an exception will be raised. See 00292 setChild() for more information about the possible numerical 00293 values of positions. 00294 @param path the path to the object we want to find 00295 @return the object, if found. NOTE YOU MUST CALL release() WHEN DONE OR USE A rREF() BLOCK 00296 @throws NoSuchSiteError The DNS lookup for the site failed, 00297 the site is not listening on the expected port, or the site 00298 otherwise could not be connected to (only thrown if there is a 00299 site specified in the path.) 00300 @throws NoSuchObjectError if that object path does not exist on the site 00301 @throws URL::BadURLError if there is a syntax error in the supplied URL 00302 @throws AccessControlError if the site reported that the user is not allowed that information 00303 */ 00304 virtual Vobject& findObject(const string& path) 00305 throw (NoSuchSiteError, NoSuchObjectError, URL::BadURLError, AccessControlError, RemoteError) = 0; 00306 00307 /** Find a child. This searchs for a single parent-child relation 00308 in the immediate child list of this object. It is 00309 distinguished from findObject in that it returns the full 00310 parent-child relation structure, and that it only accepts two 00311 forms of input: the child name, or the \#position. See 00312 setChild() for more information about the possible 00313 numerical values of positions. 00314 @param path either the child name or \#position 00315 @return the ParentChildRelation structure representing the 00316 relation of this parent and the requested child. NOTE YOU MUST CALL release() WHEN DONE OR USE A rREF() BLOCK 00317 @throws NoSuchObjectError if the path is illegal 00318 @throws AccessControlError if the site reported the user is not allowed that information 00319 */ 00320 virtual Vobject::ParentChildRelation& findChild(const string& path) 00321 throw (NoSuchObjectError, AccessControlError, RemoteError) = 0; 00322 00323 /** Find a parent. This tests to see if the supplied Vobject is 00324 marked as a parent of this Vobject. 00325 @param parent the parent object 00326 @returns the parent-child relation. NOTE YOU MUST CALL release() WHEN DONE OR USE A rREF() BLOCK 00327 @throws NoSuchObjectError if the object is NOT a parent 00328 @throws AccessControlError if the site reported the user is not allowed that information 00329 */ 00330 virtual Vobject::ParentChildRelation& findParent(Vobject& parent) 00331 throw (NoSuchObjectError, AccessControlError, RemoteError) = 0; 00332 00333 /** Replace a child at some position with a new object. @note On 00334 positions: if a position is zero or positive, its meaning is 00335 as you would expect, expressing the offset into an array of 00336 children. However, if the position is negative, it expresses 00337 the offset from the end of the list. This means for a list of 00338 length n, -1 is the last item in the list (equal to position 00339 position n - 1) and -n is the first item (equal to positive 00340 position 0). This position notation is used in setChild() 00341 findObject(), findObjectFromRoot(), insertChild(), and 00342 removeChild(); it should also be available with any methods 00343 who make use of the previously-mentioned methods. 00344 @param position the position 00345 @param contextual_name This is the name, specific to this 00346 parent-child relation, used for refering to this object by 00347 path. 00348 @param child the child object, in question 00349 @throws AccessControl if this object (when it is remote) 00350 doesn't approve of this action. */ 00351 virtual void setChild(int position, const string& contextual_name, Vobject* child) 00352 throw (AccessControlError, RemoteError) = 0; 00353 00354 /** Insert a child at some position with a new object. If the 00355 position is positive, the object is inserted such that it now 00356 occupies that position, and all objects starting from the 00357 previous occupant of that position onward are moved up one. 00358 If the position in negative, the object is similarly inserted 00359 so that it now occupies that position. For example, position 00360 -1 will append the object to the end of the list, position -2 00361 will insert the object in the second-to-last position, etc. See 00362 setChild() for more information on positions. 00363 @param position the position 00364 @param contextual_name This is the name, specific to this 00365 parent-child relation, used for refering to this object by 00366 path. 00367 @param child the child object, in question 00368 @throws AccessControl if this object (when it is remote) 00369 doesn't approve of this action. 00370 */ 00371 virtual void insertChild(int position, 00372 const string& contextual_name, 00373 Vobject* child) 00374 throw (AccessControlError, RemoteError) = 0; 00375 00376 /** Remove the child at some position. See setChild() for more 00377 information on positions. 00378 @param position the position 00379 @throws AccessControl if this object (when it is remote) 00380 doesn't approve of this action. */ 00381 virtual void removeChild(int position) 00382 throw (AccessControlError, RemoteError) = 0; 00383 00384 /** Adds some object callback to be notified when the type set changes. 00385 @param tl the listener object. 00386 @param notifyImmediately if true, notify listener immediately (before returning). otherwise defer until a future update 00387 If this object is also a RefCounted object, reference counting will be done correctly. 00388 */ 00389 virtual void addTypeListener(TypeChangeListener* tl, bool notifyImmediately = true) = 0; 00390 00391 /** Adds some object callback to be notified when the parent set changes. 00392 @param pl the listener object 00393 @poram notifyImmediately if true, notify listener immediately (before returning). otherwise defer until a future update 00394 If this object is also a RefCounted object, reference counting will be done correctly. 00395 */ 00396 virtual void addParentListener(ParentChangeListener* pl, bool notifyImmediately = true) = 0; 00397 00398 /** Adds some object callback to be notified when the child list changes. 00399 The child listener will immediately be issued a notifyChildInserted() for 00400 each child. 00401 @param cl The listener object. If this object is also a RefCounted object, reference counting will be done correctly. 00402 @param notifyImmediately if true, notify listener immediately (before returning). otherwise defer until a future update 00403 */ 00404 virtual void addChildListener(ChildChangeListener* cl, bool notifyImmediately = true) = 0; 00405 00406 /** Removes an existing object callback, previously added with addTypeListener(). 00407 @param tl the listener object 00408 If this object is also a RefCounted object, reference counting will be done correctly. 00409 */ 00410 virtual void removeTypeListener(TypeChangeListener* tl) = 0; 00411 00412 /** Removes an existing object callback, previously added with addParentListener(). 00413 @param pl the listener object 00414 If this object is also a RefCounted object, reference counting will be done correctly. 00415 */ 00416 virtual void removeParentListener(ParentChangeListener* pl)= 0; 00417 00418 /** Removes an existing object callback, previously added with addChildListener(). 00419 @param cl the listener object 00420 If this object is also a RefCounted object, reference counting will be done correctly. 00421 */ 00422 virtual void removeChildListener(ChildChangeListener* cl) = 0; 00423 00424 /** Provide our own comparison function for objects which are logically 00425 equivilent in terms of the Vobject system. 00426 @param the object to compare this to 00427 @return v if these objects are equivalent 00428 */ 00429 bool operator==(Vobject& v); 00430 00431 /** Provide our own comparison function for objects which are logically 00432 equivilent in terms of the Vobject system. 00433 @param s the object to compare this to 00434 @return if these objects are equivalent 00435 */ 00436 bool operator==(Vobject* v); 00437 00438 /** Create a message block which, when run, will recreate any 00439 non-VOS state related to this vobject (such as property 00440 values). In other words, it should not emit anything related 00441 to parent-child relationships, but is rather is a hook for 00442 other arbitrary state information, encoded as messages. 00443 @note Save-state routines ought to work for saving remote 00444 objects as well, based on available state. Also, only the 00445 method and the message fields themselves should be used. "To", 00446 "from", "nonce" and others will be ignored. 00447 @param output messages should be appended to this message block 00448 @param types the type set that should be output for this vobject 00449 @param portable If true, generate a "portable" state. This 00450 means that all the data required to restore state should be 00451 embedded in the message. If false, fully recreating the state 00452 may rely on external resources such as files or databases. 00453 */ 00454 virtual void saveState(MessageBlock& output, set<string>& types, bool portable) = 0; 00455 00456 /** Add a flag string. Mainly useful for doing tree walks, when 00457 you want to mark an object as already having been touched. 00458 @param flag the flag string 00459 */ 00460 virtual void addFlag(const string& flag) = 0; 00461 00462 /** Remove a flag string. 00463 @param flag the flag string 00464 */ 00465 virtual void removeFlag(const string& flag) = 0; 00466 00467 /** Check the flag string. 00468 @param flag the flag string 00469 @return whether the flag string is set 00470 */ 00471 virtual bool checkFlag(const string& flag) = 0; 00472 }; 00473 00474 00475 /** A base implementation class for virtual objects. Except for a few 00476 implementation-specific added methods, the API is the same as 00477 Vobject. 00478 00479 @internal 00480 */ 00481 class VOS_API VobjectImplementation : public virtual Vobject, public virtual ObjectExciseListener 00482 { 00483 private: 00484 bool islocal; 00485 bool exciseCalled; 00486 Site* site; 00487 protected: 00488 string name; 00489 URL url; 00490 deque<Message*> incomingMessageQueue; 00491 deque<Message*> incomingUpdateMessageQueue; 00492 set<ParentChildRelation*, Vobject::ParentChildRelation::Cmp> parents; 00493 deque<ParentChildRelation*> children; 00494 map<string, ParentChildRelation*> children_map; 00495 set<string> types; 00496 VobjectImplementation(const string& name, Site* remotesite, bool islocalobj); 00497 bool queueMsgs; 00498 bool queueUpdateMsgs; 00499 static bool queueMsgs_def; 00500 static bool queueUpdateMsgs_def; 00501 set<TypeChangeListener*> typeListeners; 00502 set<ParentChangeListener*> parentListeners; 00503 set<ChildChangeListener*> childListeners; 00504 00505 set<string> flagstrings; 00506 00507 class Dispatch 00508 { 00509 public: 00510 virtual ~Dispatch() {}; 00511 virtual void sendMessage(Message* m) = 0; 00512 virtual bool equivalent(void*, void*) = 0; 00513 virtual bool holds(RefCounted* otherobj) = 0; 00514 }; 00515 00516 template<class T> class DispatchTemplate : public virtual Dispatch 00517 { 00518 private: 00519 T* thisobj; 00520 typedef void (T::* MessageHandler)(Message*); 00521 MessageHandler thismethod; 00522 bool needRelease; 00523 public: 00524 DispatchTemplate(T* theobj, MessageHandler themethod, bool doRefcount) 00525 : thisobj(theobj), thismethod(themethod), needRelease(doRefcount) 00526 { 00527 if(doRefcount) { 00528 if(RefCounted* rc = dynamic_cast<RefCounted*>(theobj)) { 00529 rc->acquire(); // released by: destructor 00530 } 00531 } 00532 } 00533 virtual ~DispatchTemplate() 00534 { 00535 if(needRelease) { 00536 if(RefCounted* rc = dynamic_cast<RefCounted*>(thisobj)) { 00537 rc->release(); // acquired by: constructor 00538 } 00539 } 00540 } 00541 00542 virtual void sendMessage(Message* m) { 00543 (thisobj->*thismethod)(m); 00544 } 00545 00546 virtual bool equivalent(void* otherobj, void* othermethod) { 00547 //return (otherobj == (void*)thisobj && othermethod == makevoid(thismethod)); 00548 return (otherobj == (void*)thisobj); 00549 } 00550 00551 virtual bool holds(RefCounted* otherobj) { 00552 return (dynamic_cast<RefCounted*>(thisobj) == otherobj); 00553 } 00554 }; 00555 00556 typedef multimap<string, Dispatch*> HandlerMap; 00557 HandlerMap msghandlers; 00558 HandlerMap updatehandlers; 00559 public: 00560 virtual ~VobjectImplementation(); 00561 00562 virtual const string& getName() { return name; }; 00563 virtual Site& getSite(); 00564 virtual const URL& getURL() { return url; } 00565 virtual bool isLocal() { return islocal; }; 00566 virtual bool isRemote() { return (!islocal); }; 00567 00568 template<class T> void addMessageHandler(const string& method, T* theobj, 00569 void (T::* MessageHandler)(Message*), 00570 bool addExListener = false) 00571 { 00572 Dispatch* dt = new DispatchTemplate<T>(theobj, MessageHandler, addExListener); 00573 msghandlers.insert(HandlerMap::value_type(method, dt)); 00574 if(addExListener) { 00575 if(RefCounted* rc = dynamic_cast<RefCounted*>(theobj)) { 00576 rc->addExciseListener(this); 00577 } 00578 } 00579 }; 00580 00581 template<class T> void addUpdateHandler(const string& method, T* theobj, 00582 void (T::* MessageHandler)(Message*), 00583 bool addExListener = false) 00584 { 00585 Dispatch* dt = new DispatchTemplate<T>(theobj, MessageHandler, addExListener); 00586 updatehandlers.insert(HandlerMap::value_type(method, dt)); 00587 if(addExListener) { 00588 if(RefCounted* rc = dynamic_cast<RefCounted*>(theobj)) { 00589 rc->addExciseListener(this); 00590 } 00591 } 00592 }; 00593 00594 template<class T> void removeMessageHandler(const string& method, T* theobj, 00595 void (T::* MessageHandler)(Message*)) 00596 { 00597 pair<HandlerMap::iterator, HandlerMap::iterator> g = msghandlers.equal_range(method); 00598 for(HandlerMap::iterator it = g.first; it != g.second; it++) { 00599 if((*it).second->equivalent(theobj, thehandler)) { 00600 if(RefCounted* rc = dynamic_cast<RefCounted*>(theobj)) { 00601 rc->removeExciseListener(this); 00602 } 00603 delete (*i).second; 00604 msghandlers.erase(it); 00605 break; 00606 } 00607 } 00608 }; 00609 00610 template<class T> void removeUpdateHandler(const string& method, T* theobj, 00611 void (T::* MessageHandler)(Message*)) 00612 { 00613 pair<HandlerMap::iterator, HandlerMap::iterator> g = updatehandlers.equal_range(method); 00614 for(HandlerMap::iterator it = g.first; it != g.second; it++) { 00615 if((*it).second->equivalent(theobj, thehandler)) { 00616 if(RefCounted* rc = dynamic_cast<RefCounted*>(theobj)) { 00617 rc->removeExciseListener(this); 00618 } 00619 delete (*i).second; 00620 updatehandlers.erase(it); 00621 break; 00622 } 00623 } 00624 }; 00625 00626 /** Get the default message discard policy for new objects. 00627 @return true if messages, after being passed through 00628 sendMessage(), are queued so they may be retrieved with 00629 receiveMessage(); false if the messages are instead discarded. 00630 */ 00631 static bool getQueueMsgsDefault() { return queueMsgs_def; } 00632 00633 /** Set the default message discard policy for new objects. 00634 @param t If false an incoming message, after being passed 00635 through sendMessage(), will be discarded. If 00636 true that message will be queued and may be retrived by the 00637 user with receiveMessage(). 00638 */ 00639 static void setQueueMsgsDefault(bool t) { queueMsgs_def=t; } 00640 00641 /** Get the default update message discard policy for new objects. 00642 @return true if update messages, after being passed through 00643 sendUpdateMessage(), are queued so they may be retrieved with 00644 receiveUpdateMessage(); false if the update messages are discarded. 00645 */ 00646 static bool getQueueUpdateMsgsDefault() { return queueUpdateMsgs_def; } 00647 00648 /** Set the default update message discard policy for new objects. 00649 @param t If false an incoming update message, after being passed 00650 through sendUpdateMessage(), will be discarded. If 00651 true that update message will be queued and may be retrived by the 00652 user with receiveUpdateMessage(). 00653 */ 00654 static void setQueueUpdateMsgsDefault(bool t) { queueUpdateMsgs_def=t; } 00655 00656 /** Get the message discard policy for this object. 00657 @return true if messages, after being passed through 00658 sendMessage(), are queued so they may be retrieved with 00659 receiveMessage(); false if the messages are instead discarded. 00660 */ 00661 virtual bool getQueueMsgs() { return queueMsgs; } 00662 00663 /** Set the message discard policy for this object. 00664 @param t If false an incoming message, after being passed 00665 through sendMessage(), will be discarded. If 00666 true that message will be queued and may be retrived by the 00667 user with receiveMessage(). 00668 */ 00669 virtual void setQueueMsgs(bool t) { queueMsgs=t; } 00670 00671 /** Get the update message discard policy for this object. 00672 @return true if update messages, after being passed through 00673 sendUpdateMessage(), are queued so they may be retrieved with 00674 receiveUpdateMessage(); false if the update messages are discarded. 00675 */ 00676 virtual bool getQueueUpdateMsgs() { return queueUpdateMsgs; } 00677 00678 /** Set the update message discard policy for this object. 00679 @param t If false an incoming update message, after being passed 00680 through sendUpdateMessage(), will be discarded. If 00681 true that update message will be queued and may be retrived by the 00682 user with receiveUpdateMessage(). 00683 */ 00684 virtual void setQueueUpdateMsgs(bool t) { queueUpdateMsgs=t; } 00685 00686 virtual const TypeSet& getTypes() 00687 throw (AccessControlError, RemoteError); 00688 00689 virtual void addType(Vobject* requester, const string& s); 00690 00691 virtual const ParentSet& getParents() 00692 throw (AccessControlError, RemoteError); 00693 virtual const ChildList& getChildren() 00694 throw (AccessControlError, RemoteError); 00695 00696 virtual Message* receiveMessage() throw (MessageQueueEmptyError); 00697 virtual bool hasMessageAvailable(); 00698 00699 void sendUpdateMessage(Message* m); 00700 virtual Message* receiveUpdateMessage() throw (MessageQueueEmptyError); 00701 virtual bool hasUpdateMessageAvailable(); 00702 00703 virtual Vobject& findObject(const string& path) 00704 throw (NoSuchSiteError, NoSuchObjectError, URL::BadURLError, AccessControlError, RemoteError); 00705 virtual Vobject::ParentChildRelation& findChild(const string& path) 00706 throw (NoSuchObjectError, AccessControlError, RemoteError); 00707 virtual Vobject::ParentChildRelation& findParent(Vobject& parent) 00708 throw (NoSuchObjectError, AccessControlError, RemoteError); 00709 00710 virtual void setChild(Vobject* requester, int position, const string& contextual_name, Vobject* child) 00711 throw (AccessControlError, RemoteError); 00712 virtual void insertChild(Vobject* requester, int position, const string& contextual_name, Vobject* child) 00713 throw (AccessControlError, RemoteError); 00714 virtual void removeChild(Vobject* requester, int position) 00715 throw (AccessControlError, RemoteError); 00716 00717 virtual void addTypeListener(TypeChangeListener* tl, bool refresh = true); 00718 virtual void addParentListener(ParentChangeListener* pl, bool refresh = true); 00719 virtual void addChildListener(ChildChangeListener* cl, bool refresh = true); 00720 virtual void removeTypeListener(TypeChangeListener* tl); 00721 virtual void removeParentListener(ParentChangeListener* pl); 00722 virtual void removeChildListener(ChildChangeListener* cl); 00723 00724 virtual void notifyObjectExcise(RefCounted* rc); 00725 00726 virtual void excise(); 00727 00728 virtual void saveState(MessageBlock& output, set<string>& types, bool portable); 00729 00730 virtual void addFlag(const string& flag); 00731 virtual void removeFlag(const string& flag); 00732 virtual bool checkFlag(const string& flag); 00733 00734 friend class RemoteVobject; 00735 }; 00736 } 00737 00738 #endif