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