00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <signal.h>
00025
00026 #include <string>
00027 #include <algorithm>
00028 #include <typeinfo>
00029
00030 #include "vos.hh"
00031
00032
00033
00034
00035
00036 bool VobjectImplementation::queueMsgs_def=false;
00037 bool VobjectImplementation::queueUpdateMsgs_def=false;
00038
00039 DoNothingListener DoNothingListener::static_;
00040
00041 bool Vobject::operator==(Vobject& v) {
00042 bool ret;
00043 rREF(Site&, ts, getSite(),
00044 rREF(Site&, vs, v.getSite(),
00045 ret = (((void*)&ts == (void*)&vs) && getName() == v.getName());
00046 );
00047 );
00048 return ret;
00049 }
00050
00051 bool Vobject::operator==(Vobject* v) {
00052 bool ret;
00053 rREF(Site&, ts, getSite(),
00054 rREF(Site&, vs, v->getSite(),
00055 ret = (((void*)&ts == (void*)&vs) && getName() == v->getName());
00056 );
00057 );
00058 return ret;
00059 }
00060
00061 VobjectImplementation::VobjectImplementation(const string& n, Site* s, bool islocalobj)
00062 : islocal(islocalobj), exciseCalled(false), site(s), name(n),
00063 queueMsgs(queueMsgs_def), queueUpdateMsgs(queueUpdateMsgs_def)
00064 {
00065 if(site) {
00066 url=site->getURL();
00067 url.setPath("/" + name);
00068 site->acquire();
00069 }
00070 }
00071
00072 VobjectImplementation::~VobjectImplementation()
00073 {
00074 LOG("Vobject", 3, "deleting " << url.getString());
00075
00076 if(site) {
00077 LOG("refcount", 5, "count on site " << site->getURL().getString() << " is " << site->getCount());
00078 site->release();
00079 }
00080
00081 for(set<ParentChangeListener*>::iterator i = parentListeners.begin(); i != parentListeners.end(); i++) {
00082 if(RefCounted* rc = dynamic_cast<RefCounted*>(*i)) {
00083 rc->removeExciseListener(this, false);
00084 rc->release();
00085 }
00086 }
00087 for(set<ChildChangeListener*>::iterator i = childListeners.begin(); i != childListeners.end(); i++) {
00088 if(RefCounted* rc = dynamic_cast<RefCounted*>(*i)) {
00089 rc->removeExciseListener(this, false);
00090 rc->release();
00091 }
00092 }
00093 for(set<TypeChangeListener*>::iterator i = typeListeners.begin(); i != typeListeners.end(); i++) {
00094 if(RefCounted* rc = dynamic_cast<RefCounted*>(*i)) {
00095 rc->removeExciseListener(this, false);
00096 rc->release();
00097 }
00098 }
00099 }
00100
00101 Site& VobjectImplementation::getSite() {
00102 site->acquire();
00103 return *site;
00104 }
00105
00106 const set<string>& VobjectImplementation::getTypes() throw (AccessControlError, RemoteError)
00107 { return types; }
00108
00109 const set<Vobject::ParentChildRelation*,
00110 Vobject::ParentChildRelation::Cmp>& VobjectImplementation::getParents()
00111 throw (AccessControlError, RemoteError)
00112 { return parents; }
00113
00114 const deque<Vobject::ParentChildRelation*>& VobjectImplementation::getChildren()
00115 throw (AccessControlError, RemoteError)
00116 { return children; }
00117
00118 Vobject& Vobject::findObjectFromRoot(const string& path)
00119 throw (NoSuchSiteError, NoSuchObjectError, URL::BadURLError, AccessControlError, RemoteError)
00120 {
00121 if(path.substr(0, 6) != "vop://") throw NoSuchObjectError("Object path doesn't start with vop://");
00122 URL u(path);
00123 string s;
00124 s += u.getHostAndPort();
00125 Site& objsite=Site::findSite(s);
00126
00127 if(u.getPath() == "") {
00128
00129 return objsite;
00130 } else {
00131
00132 try {
00133 Vobject& v = objsite.findObject(u.getPath());
00134 objsite.release();
00135 return v;
00136 } catch(...) {
00137 objsite.release();
00138 throw;
00139 }
00140 }
00141 }
00142
00143 Vobject::ParentChildRelation& VobjectImplementation::findChild(const string& path)
00144 throw (NoSuchObjectError, AccessControlError, RemoteError)
00145 {
00146 if(path[0] == '#') {
00147 int pos=atoi(path.substr(1).c_str());
00148 if(pos < 0) pos=children.size()+pos;
00149 if((unsigned int)pos >= children.size()) throw NoSuchObjectError(string("Object position out of range: ") + path);
00150 Vobject::ParentChildRelation* child=children[pos];
00151 if(child == 0) throw NoSuchObjectError("Object at position not aquired (BUG!)");
00152 child->acquire();
00153 return *child;
00154 } else {
00155 map<string, Vobject::ParentChildRelation*>::iterator it=children_map.find(path);
00156 if(it == children_map.end()) throw NoSuchObjectError(string("No object by that name: ") + path);
00157 ((*it).second)->acquire();
00158 return *((*it).second);
00159 }
00160 }
00161
00162 Vobject::ParentChildRelation& VobjectImplementation::findParent(Vobject& parent)
00163 throw (NoSuchObjectError, AccessControlError, RemoteError)
00164 {
00165 for(set<Vobject::ParentChildRelation*, Vobject::ParentChildRelation::Cmp>::const_iterator piter = getParents().begin();
00166 piter != parents.end();
00167 piter++) {
00168
00169
00170 if(*((*piter)->parent) == parent) {
00171 (*piter)->acquire();
00172 return **piter;
00173 }
00174 }
00175 throw NoSuchObjectError("Supplied object is not a parent");
00176 }
00177
00178 Vobject& VobjectImplementation::findObject(const string& path)
00179 throw (NoSuchSiteError, NoSuchObjectError, URL::BadURLError, AccessControlError, RemoteError)
00180 {
00181 if(path.substr(0, 6) == "vop://") {
00182
00183 return findObjectFromRoot(path);
00184 }
00185 if(path == "") {
00186 acquire();
00187 return *this;
00188 }
00189 if(path == "/" ) throw NoSuchObjectError("\"/\" is not a legal path");
00190 unsigned int nextpart;
00191 if(path[0] == '/') {
00192
00193 rREF(Site&, site, getSite(),
00194 Vobject& v = site.findObject(path.substr(1));
00195 site.release();
00196 return v;
00197 );
00198 }
00199 nextpart=path.find("/");
00200 string cur=path.substr(0, nextpart);
00201 string rest;
00202 if(nextpart != string::npos) rest=path.substr(nextpart+1);
00203
00204 Vobject* child;
00205 rREF(Vobject::ParentChildRelation&, pcr, findChild(cur), child = pcr.child);
00206 if(! child) throw NoSuchObjectError("Object not available");
00207 if(rest == "") {
00208 child->acquire();
00209 return *child;
00210 } else {
00211
00212 return child->findObject(rest);
00213 }
00214 }
00215
00216 void VobjectImplementation::insertChild(int pos, const string& context_name, Vobject* child)
00217 throw (AccessControlError, RemoteError)
00218 {
00219
00220 if(pos < 0) pos = children.size() + pos + 1;
00221
00222 if(MetaObject* m = dynamic_cast<MetaObject*>(child)) {
00223 child=m->getTopObject();
00224 }
00225
00226 vRef<Site> thissite = getSite();
00227
00228 vRef<Vobject::ParentChildRelation> c = new Vobject::ParentChildRelation(child, this);
00229 c->position=pos;
00230 c->contextual_name=context_name;
00231
00232 if(children.size() < (unsigned int)pos) {
00233 children.resize(pos, 0);
00234 }
00235
00236 c->acquire();
00237
00238
00239 children.insert(children.begin()+pos, &c);
00240 children_map[context_name]=&c;
00241
00242 for(unsigned int i=pos+1; i < children.size(); i++) {
00243 if(children[i]) children[i]->position++;
00244 }
00245
00246 if(VobjectImplementation* v = dynamic_cast<VobjectImplementation*>(child)) {
00247
00248 c->acquire();
00249 v->parents.insert(&c);
00250
00251 for(set<ParentChangeListener*>::iterator i = v->parentListeners.begin();
00252 i != v->parentListeners.end(); i++)
00253 {
00254
00255
00256
00257
00258
00259
00260 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ParentInserted,
00261 v, this, pos, context_name));
00262 }
00263 LOG("insertChild", 3, "did add " << c->parent->getURL().getString() << " as a parent for "
00264 << c->child->getURL().getString() << "(count " << c->child->getCount() << ") at position " << pos << ", size of parents is " << v->parents.size());
00265 }
00266
00267 for(set<ChildChangeListener*>::iterator i = childListeners.begin();
00268 i != childListeners.end(); i++)
00269 {
00270
00271
00272
00273
00274
00275 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ChildInserted,
00276 this, pos, context_name, child));
00277 }
00278 }
00279
00280
00281
00282 void VobjectImplementation::setChild(int position, const string& contextual_name, Vobject* child)
00283 throw (AccessControlError, RemoteError)
00284 {
00285 if(! child) return;
00286 if(position < 0) position=children.size()+position;
00287
00288 if(MetaObject* m = dynamic_cast<MetaObject*>(child)) {
00289 child=m->getTopObject();
00290 }
00291
00292 LOG("vobject", 5, "position " << position << " size " << children.size());
00293 if(children.size() > (unsigned int)position) {
00294 LOG("vobject", 5, "oldedge is " << children[position]);
00295 }
00296 else {
00297 LOG("vobject", 5, "position doesn't fit");
00298 }
00299
00300 if(children.size() <= (unsigned int)position) {
00301 children.resize(position+1, 0);
00302 }
00303
00304 Vobject* oldchild = 0;
00305
00306 vRef<Site> thissite = getSite();
00307
00308 ParentChildRelation* oldedge = children[position];
00309 LOG("vobject", 4, "entered setChild on " << getURL().getString() << " for child " << child->getURL().getString()
00310 << "(" << contextual_name << ")" << " and oldedge is " << oldedge);
00311 if(oldedge) {
00312 if(oldedge->child == child && oldedge->contextual_name == contextual_name) {
00313 LOG("vobject", 5, "new child/pos/contextname same as old one. sending notifications but otherwise ignoring");
00314
00315
00316
00317
00318 for(set<ChildChangeListener*>::iterator i = childListeners.begin();
00319 i != childListeners.end(); i++)
00320 {
00321
00322
00323
00324
00325
00326
00327 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ChildReplaced,
00328 this, position, contextual_name,
00329 child, oldedge->child));
00330 }
00331 thissite->flushNotifications();
00332 return;
00333 }
00334
00335 oldedge->child->acquire();
00336 oldchild = oldedge->child;
00337
00338 if(VobjectImplementation* v = dynamic_cast<VobjectImplementation*>(oldedge->child)) {
00339 v->parents.erase(children[position]);
00340 for(set<ParentChangeListener*>::iterator i = v->parentListeners.begin();
00341 i != v->parentListeners.end(); i++) {
00342
00343
00344 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ParentRemoved,
00345 v, this, oldedge->position,
00346 oldedge->contextual_name));
00347
00348
00349
00350
00351
00352 }
00353 }
00354
00355 LOG("vobject", 5, "about to release oldedge twice, count is " << oldedge->getCount());
00356
00357
00358 oldedge->release();
00359 oldedge->release();
00360 }
00361
00362 LOG("vobject", 5, "about to create a pcr, count on child is " << getCount());
00363 vRef<Vobject::ParentChildRelation> c = new Vobject::ParentChildRelation(child, this);
00364
00365 c->position=position;
00366 c->contextual_name=contextual_name;
00367
00368 c->acquire();
00369
00370
00371 children[position]=&c;
00372 children_map[contextual_name]=&c;
00373
00374 if(VobjectImplementation* v = dynamic_cast<VobjectImplementation*>(child)) {
00375
00376 c->acquire();
00377 v->parents.insert(&c);
00378
00379 for(set<ParentChangeListener*>::iterator i = v->parentListeners.begin();
00380 i != v->parentListeners.end(); i++)
00381 {
00382
00383 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ParentInserted,
00384 v, this, position,
00385 contextual_name));
00386
00387
00388
00389
00390
00391 }
00392
00393 LOG("setChild", 4, "did add " << c->parent->getURL().getString() << " as a parent for "
00394 << child->getURL().getString() << " at position " << position << ", size of parents is " << v->parents.size() << ", and size of children " << children.size());
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 }
00408
00409 if(oldchild) {
00410 for(set<ChildChangeListener*>::iterator i = childListeners.begin();
00411 i != childListeners.end(); i++) {
00412
00413
00414
00415
00416
00417 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ChildReplaced,
00418 this, position, contextual_name,
00419 child, oldchild));
00420 }
00421 oldchild->release();
00422 } else {
00423 for(set<ChildChangeListener*>::iterator i = childListeners.begin();
00424 i != childListeners.end(); i++)
00425 {
00426
00427
00428
00429
00430
00431 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ChildInserted,
00432 this, position, contextual_name,
00433 child));
00434
00435 }
00436 }
00437
00438 thissite->flushNotifications();
00439
00440 LOG("setChild", 4, getURL().getString() << " children.size() == " << children.size());
00441 }
00442
00443
00444 void VobjectImplementation::removeChild(int pos)
00445 throw (AccessControlError, RemoteError)
00446 {
00447 if(pos < 0) pos=children.size()+pos;
00448 if((unsigned int)pos >= children.size()) pos = pos % children.size();
00449 vRef<Vobject::ParentChildRelation> c = children[pos];
00450
00451 children.erase(children.begin() + pos);
00452
00453 if(&c) {
00454 children_map.erase(c->contextual_name);
00455
00456 for(unsigned int i=pos; i < children.size(); i++) {
00457 if(children[i]) children[i]->position--;
00458 }
00459
00460 string context_name = c->contextual_name;
00461 Vobject* child = c->child;
00462
00463 if(MetaObject* m = dynamic_cast<MetaObject*>(child)) {
00464 child=m->getTopObject();
00465 }
00466
00467 vRef<Site> thissite = getSite();
00468
00469 if(VobjectImplementation* v = dynamic_cast<VobjectImplementation*>(child)) {
00470 v->parents.erase(&c);
00471 c->release();
00472
00473 for(set<ParentChangeListener*>::iterator i = v->parentListeners.begin();
00474 i != v->parentListeners.end(); i++)
00475 {
00476
00477
00478
00479
00480
00481 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ParentRemoved,
00482 v, this, c->position, c->contextual_name));
00483 }
00484 }
00485
00486 if(child) {
00487 for(set<ChildChangeListener*>::iterator i = childListeners.begin();
00488 i != childListeners.end(); i++)
00489 {
00490 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ChildRemoved,
00491 this, pos, context_name, child));
00492 }
00493 }
00494 thissite->flushNotifications();
00495 }
00496 }
00497
00498 bool VobjectImplementation::hasMessageAvailable()
00499 {
00500 rREF(Site&, site, getSite(), site.flushIncomingBuffers());
00501 return (!incomingMessageQueue.empty());
00502 }
00503
00504
00505 Message* VobjectImplementation::receiveMessage() throw (MessageQueueEmptyError)
00506 {
00507 rREF(Site&, site, getSite(), site.flushIncomingBuffers());
00508
00509 Message* m;
00510 if(incomingMessageQueue.empty()) throw MessageQueueEmptyError("No messages available");
00511 m = incomingMessageQueue.front();
00512 incomingMessageQueue.pop_front();
00513
00514 return m;
00515 }
00516
00517 void VobjectImplementation::sendUpdateMessage(Message* m)
00518 {
00519 if(queueUpdateMsgs) {
00520 m->acquire();
00521 incomingUpdateMessageQueue.push_back(m);
00522
00523
00524 }
00525 }
00526
00527 Message* VobjectImplementation::receiveUpdateMessage() throw (MessageQueueEmptyError)
00528 {
00529 rREF(Site&, site, getSite(), site.flushIncomingBuffers());
00530
00531 Message* m;
00532 if(incomingUpdateMessageQueue.empty()) throw MessageQueueEmptyError("No messages available");
00533 m = incomingUpdateMessageQueue.front();
00534 incomingUpdateMessageQueue.pop_front();
00535 return m;
00536
00537
00538 }
00539
00540 bool VobjectImplementation::hasUpdateMessageAvailable()
00541 {
00542 rREF(Site&, site, getSite(), site.flushIncomingBuffers());
00543 return (!incomingUpdateMessageQueue.empty());
00544 }
00545
00546 void VobjectImplementation::addTypeListener(TypeChangeListener* tl, bool refresh)
00547 {
00548 if(RefCounted* rc = dynamic_cast<RefCounted*>(tl)) {
00549 rc->acquire();
00550 rc->addExciseListener(this);
00551 }
00552 typeListeners.insert(tl);
00553
00554 if(refresh) {
00555 TypeSet tmptypeset = types;
00556 for(set<string>::iterator it = tmptypeset.begin();
00557 it != tmptypeset.end(); it++) {
00558 try {
00559 tl->notifyTypeInserted(*this, (*it));
00560 } catch(runtime_error x) {
00561 LOG("vobject", 0, "call to notifyTypeInserted emitted exception: " << x.what());
00562 } catch(...) { }
00563 }
00564 }
00565 }
00566
00567 void VobjectImplementation::addParentListener(ParentChangeListener* pl, bool refresh)
00568 {
00569 if(RefCounted* rc = dynamic_cast<RefCounted*>(pl)) {
00570 rc->acquire();
00571 rc->addExciseListener(this);
00572 }
00573 parentListeners.insert(pl);
00574
00575 if(refresh) {
00576 ParentSet tmpparentset = parents;
00577 for(set<ParentChildRelation*, ParentChildRelation::Cmp>::iterator it = tmpparentset.begin();
00578 it != tmpparentset.end(); it++) {
00579 try {
00580 if((*it)->parent) pl->notifyParentInserted(*this, *((*it)->parent), (*it)->position, (*it)->contextual_name);
00581 } catch(runtime_error x) {
00582 LOG("vobject", 0, "call to notifyParentInserted emitted exception: " << x.what());
00583 } catch(...) { }
00584 }
00585 }
00586 }
00587
00588 void VobjectImplementation::addChildListener(ChildChangeListener* cl, bool refresh)
00589 {
00590 if(RefCounted* rc = dynamic_cast<RefCounted*>(cl)) {
00591 rc->acquire();
00592 rc->addExciseListener(this);
00593 }
00594 childListeners.insert(cl);
00595
00596 if(refresh) {
00597 ChildList cc = children;
00598 for(unsigned int it = 0; it < cc.size(); it++) {
00599 if(cc[it]) cc[it]->acquire();
00600 }
00601 for(unsigned int it = 0; it < cc.size(); it++) {
00602 if(cc[it]) {
00603 if(cc[it]->getCount() > 1) {
00604 try {
00605 ParentChildRelation* pcr = cc[it];
00606 if(pcr->child) {
00607 cl->notifyChildInserted(*this, pcr->position,
00608 pcr->contextual_name,
00609 *(pcr->child));
00610 }
00611 } catch(runtime_error x) {
00612 LOG("vobject", 0, "call to notifyChildInserted emitted exception: " << x.what());
00613 } catch(...) {
00614 LOG("vobject", 0, "call to notifyChildInserted emitted unknown exception!");
00615 }
00616 }
00617 cc[it]->release();
00618 }
00619 }
00620 }
00621 }
00622
00623 void VobjectImplementation::removeTypeListener(TypeChangeListener* tl)
00624 {
00625 if(typeListeners.count(tl)) {
00626 typeListeners.erase(tl);
00627 if(RefCounted* rc = dynamic_cast<RefCounted*>(tl)) {
00628 rc->removeExciseListener(this);
00629 rc->release();
00630 }
00631 }
00632 }
00633
00634 void VobjectImplementation::removeParentListener(ParentChangeListener* pl)
00635 {
00636 if(parentListeners.count(pl)) {
00637 parentListeners.erase(pl);
00638 if(RefCounted* rc = dynamic_cast<RefCounted*>(pl)) {
00639 rc->removeExciseListener(this);
00640 rc->release();
00641 }
00642 }
00643 }
00644
00645 void VobjectImplementation::removeChildListener(ChildChangeListener* cl)
00646 {
00647 if(childListeners.count(cl)) {
00648 childListeners.erase(cl);
00649 if(RefCounted* rc = dynamic_cast<RefCounted*>(cl)) {
00650 rc->removeExciseListener(this);
00651 rc->release();
00652 }
00653 }
00654 }
00655
00656 void VobjectImplementation::notifyObjectExcise(RefCounted* rc)
00657 {
00658 if(TypeChangeListener* tl = dynamic_cast<TypeChangeListener*>(rc)) removeTypeListener(tl);
00659 if(ParentChangeListener* pl = dynamic_cast<ParentChangeListener*>(rc)) removeParentListener(pl);
00660 if(ChildChangeListener* cl = dynamic_cast<ChildChangeListener*>(rc)) removeChildListener(cl);
00661
00662 for(HandlerMap::iterator it = msghandlers.begin(); it != msghandlers.end(); ) {
00663 if((*it).second->holds(rc)) {
00664 HandlerMap::iterator tmp = it;
00665 delete (*it).second;
00666 it++;
00667 msghandlers.erase(tmp);
00668 } else it++;
00669 }
00670 for(HandlerMap::iterator it = updatehandlers.begin(); it != updatehandlers.end(); ) {
00671 if((*it).second->holds(rc)) {
00672 HandlerMap::iterator tmp = it;
00673 delete (*it).second;
00674 it++;
00675 updatehandlers.erase(tmp);
00676 } else it++;
00677 }
00678 }
00679
00680 void VobjectImplementation::addType(const string& s)
00681 {
00682 if(s != "" && !types.count(s)) {
00683 for(TypeSet::iterator i = types.begin(); i != types.end(); i++) {
00684 if((*i).substr(0, s.size()) == s
00685 && (*i).substr(s.size(), 1) == ".")
00686 {
00687 return;
00688 }
00689 }
00690 types.insert(s);
00691
00692 for(set<TypeChangeListener*>::iterator i = typeListeners.begin();
00693 i != typeListeners.end();
00694 i++) {
00695 try {
00696 (*i)->notifyTypeInserted(*this, s);
00697 } catch(runtime_error x) {
00698 LOG("refcount", 0, "call to notifyTypeInserted emitted exception: " << x.what());
00699 } catch(...) { }
00700 }
00701 }
00702 }
00703
00704 void VobjectImplementation::excise()
00705 {
00706 if(exciseCalled) return;
00707 else exciseCalled = true;
00708
00709 RefCounted::excise();
00710
00711
00712
00713
00714 for(int i=children.size() - 1; i >= 0; i--) {
00715 VobjectImplementation::removeChild(i);
00716 }
00717
00718
00719 set<ParentChildRelation*, Vobject::ParentChildRelation::Cmp> parentbuf = parents;
00720 LOG("Vobject", 4, "parents size is " << parentbuf.size());
00721 for(set<ParentChildRelation*, Vobject::ParentChildRelation::Cmp>::iterator it = parentbuf.begin();
00722 it != parentbuf.end();
00723 it++) {
00724 LOG("Vobject", 4, "parents size is " << parents.size());
00725 try {
00726 if(VobjectImplementation* p = dynamic_cast<VobjectImplementation*>((*it)->parent)) {
00727 LOG("Vobject", 4, "removing parent " << p->getURL().getString() << " of child " << getURL().getString());
00728 if(p->isRemote()) p->setChild((*it)->position, (*it)->contextual_name, 0);
00729 else p->VobjectImplementation::removeChild((*it)->position);
00730 }
00731 } catch(AccessControlError) { }
00732 }
00733
00734 for(set<ParentChangeListener*>::iterator i = parentListeners.begin(); i != parentListeners.end(); i++) {
00735 if(RefCounted* rc = dynamic_cast<RefCounted*>(*i)) {
00736 rc->removeExciseListener(this);
00737 rc->release();
00738 }
00739 }
00740 for(set<ChildChangeListener*>::iterator i = childListeners.begin(); i != childListeners.end(); i++) {
00741 if(RefCounted* rc = dynamic_cast<RefCounted*>(*i)) {
00742 rc->removeExciseListener(this);
00743 rc->release();
00744 }
00745 }
00746 for(set<TypeChangeListener*>::iterator i = typeListeners.begin(); i != typeListeners.end(); i++) {
00747 if(RefCounted* rc = dynamic_cast<RefCounted*>(*i)) {
00748 rc->removeExciseListener(this);
00749 rc->release();
00750 }
00751 }
00752 parentListeners.clear();
00753 childListeners.clear();
00754 typeListeners.clear();
00755
00756 for(HandlerMap::iterator it = msghandlers.begin(); it != msghandlers.end(); it++) {
00757 delete (*it).second;
00758 }
00759 for(HandlerMap::iterator it = updatehandlers.begin(); it != updatehandlers.end(); it++) {
00760 delete (*it).second;
00761 }
00762 msghandlers.clear();
00763 updatehandlers.clear();
00764
00765 LOG("Vobject", 4, "excise: refcount on this is " << getCount());
00766 if(getCount() < 1) {
00767 LOG("Vobject", 0, "excise: refcount on this is " << getCount() << "! The method which called excise() should be holding the last reference. (I'm going to abort now).");
00768 abort();
00769 }
00770 }
00771
00772 void VobjectImplementation::saveState(MessageBlock& output, set<string>& t, bool portable)
00773 {
00774 t = types;
00775 }
00776
00777 void VobjectImplementation::addFlag(const string& flag)
00778 {
00779 flagstrings.insert(flag);
00780 }
00781
00782 void VobjectImplementation::removeFlag(const string& flag)
00783 {
00784 flagstrings.erase(flag);
00785 }
00786
00787 bool VobjectImplementation::checkFlag(const string& flag)
00788 {
00789 return (flagstrings.count(flag) > 0);
00790 }
00791
00792