Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/corelibs/vos/typingtweaks/vobject.cc

Go to the documentation of this file.
00001 /*
00002     This file is part of the Virtual Object System of
00003     the Interreality project (http://interreality.org).
00004 
00005     Copyright (C) 2001, 2002 Peter Amstutz
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00020 
00021     Peter Amstutz <tetron@interreality.org>
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 /** @file
00033     Implements VobjectImplementation.
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(); // released by: excise() or destructor
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(); // acquired by: constructor
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(); // released by: the caller of this method
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         // pass reference through
00129         return objsite;
00130     } else {
00131         // pass reference to 'v' through
00132         try {
00133             Vobject& v = objsite.findObject(u.getPath());
00134             objsite.release(); // acquired by: findSite() above
00135             return v;
00136         } catch(...) {
00137             objsite.release(); // acquired by: findSite() above
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(); // released by: the caller of this method
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(); // released by: the caller of this method
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         //LOG("Vobject", 5, "comparing " << (*piter)->parent->getSite().getURL().getString() << " to " << parent.getSite().getURL().getString());
00169         //LOG("Vobject", 5, "comparing " << (*piter)->parent->getName() << " to " << parent.getName());
00170         if(*((*piter)->parent) == parent) {
00171             (*piter)->acquire(); // released by: the caller of this method
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         // pass reference through
00183         return findObjectFromRoot(path);
00184     }
00185     if(path == "") {
00186         acquire(); // released by: the caller of this method
00187         return *this;
00188     }
00189     if(path == "/" ) throw NoSuchObjectError("\"/\" is not a legal path");
00190     unsigned int nextpart;
00191     if(path[0] == '/') {
00192         // pass reference through
00193         rREF(Site&, site, getSite(),
00194              Vobject& v = site.findObject(path.substr(1));
00195              site.release(); // acquired by: getSite() above
00196              return v;
00197             ); // will catch any exceptions, release the site, and re-throw the exception
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(); // released by: the caller of this method
00209         return *child;
00210     } else {
00211         // pass reference through
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(); // released by: removeChild() or setChild()
00237     // since both children and children_map[] are manipulated in
00238     // parallel, consider it a single reference
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         /* because the child now has a reference to c as well */
00248         c->acquire(); // released by: removeChild() or setChild()
00249         v->parents.insert(&c);
00250 
00251         for(set<ParentChangeListener*>::iterator i = v->parentListeners.begin();
00252             i != v->parentListeners.end(); i++)
00253         {
00254             /*    try {
00255                 (*i)->notifyParentInserted(*v, *this, pos, context_name);
00256             } catch(runtime_error x) {
00257                 LOG("refcount", 0, "call to notifyParentInserted emitted exception: " << x.what());
00258                 } catch(...) { }*/
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         /*try {
00271             (*i)->notifyChildInserted(*this, pos, context_name, *child);
00272         } catch(runtime_error x) {
00273             LOG("refcount", 0, "call to notifyChildInserted emitted exception: " << x.what());
00274             } catch(...) { }*/
00275         thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ChildInserted,
00276                                                          this, pos, context_name, child));
00277     }
00278 }
00279 
00280 
00281 /// @bug is there an unspec'ed exception in this method?
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             /*if(position == 3 && children.size() == 5 && contextual_name == "orientation"
00315                 && child->getName() == "719885386") {
00316                 raise(SIGINT);
00317                 }*/
00318              for(set<ChildChangeListener*>::iterator i = childListeners.begin();
00319                  i != childListeners.end(); i++)
00320              {
00321                  //try {
00322                      //(*i)->notifyChildReplaced(*this, position, contextual_name, *child, *oldedge->child);
00323                  //} catch(runtime_error x) {
00324                  //  LOG("refcount", 0, "call to notifyChildReplaced emitted exception: " << x.what());
00325                  //} catch(...) { }
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(); // released below (after doing notifications)
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                 //try {
00343                     //(*i)->notifyParentRemoved(*v, *this, oldedge->position, oldedge->contextual_name);
00344                 thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ParentRemoved,
00345                                                               v, this, oldedge->position,
00346                                                               oldedge->contextual_name));
00347 
00348                                        //} catch(runtime_error x) {
00349                                        //LOG("vobject", 0, "call to notifyParentRemoved emitted exception: " << x.what());
00350                                        //} catch(...) { }
00351                                        //}
00352             }
00353         }
00354 
00355         LOG("vobject", 5, "about to release oldedge twice, count is " << oldedge->getCount());
00356 
00357         /* release twice, once for parent, once for child */
00358         oldedge->release(); // acquired by: insertChild() or setChild()
00359         oldedge->release(); // acquired by: insertChild() or setChild()
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(); // released by: removeChild() or setChild()
00369     // since both children and children_map[] are manipulated in
00370     // parallel, consider it a single reference
00371     children[position]=&c;
00372     children_map[contextual_name]=&c;
00373 
00374     if(VobjectImplementation* v = dynamic_cast<VobjectImplementation*>(child)) {
00375         /* because the child now has a reference to c as well */
00376         c->acquire(); // released by: setChild() or removeChild()
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             //try {
00387             //(*i)->notifyParentInserted(*v, *this, position, contextual_name);
00388             //} catch(runtime_error x) {
00389             //LOG("vobject", 0, "call to notifyParentInserted emitted exception: " << x.what());
00390             //} catch(...) { }
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           for(int foo = 0; foo < children.size(); foo++) {
00398           ParentChildRelation* ch = children[foo];
00399           LOG("Vobject", 4, "---");
00400           for(set<ParentChildRelation*, Vobject::ParentChildRelation::Cmp>::iterator i = ch->child->getParents().begin();
00401           i != ch->child->getParents().end(); i++) {
00402           LOG("Vobject", 4, (*i)->parent->getURL().getString() << " is parent of "
00403           << (*i)->child->getURL().getString());
00404           }
00405           }
00406         */
00407     }
00408 
00409     if(oldchild) {
00410         for(set<ChildChangeListener*>::iterator i = childListeners.begin();
00411             i != childListeners.end(); i++) {
00412             /*try {
00413               (*i)->notifyChildReplaced(*this, position, contextual_name, *child, *oldchild);
00414               } catch(runtime_error x) {
00415               LOG("refcount", 0, "call to notifyChildReplaced emitted exception: " << x.what());
00416               } catch(...) { }*/
00417             thissite->addNotification(new VobjectNotifyEvent(*i, VobjectNotifyEvent::ChildReplaced,
00418                                                              this, position, contextual_name,
00419                                                              child, oldchild));
00420         }
00421         oldchild->release(); // acquired above (when releasing old edge)
00422     } else {
00423         for(set<ChildChangeListener*>::iterator i = childListeners.begin();
00424             i != childListeners.end(); i++)
00425         {
00426             /*try {
00427               (*i)->notifyChildInserted(*this, position, contextual_name, *child);
00428               } catch(runtime_error x) {
00429               LOG("refcount", 0, "call to notifyChildInserted emitted exception: " << x.what());
00430               } catch(...) { }*/
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     //LOG("Vobject", 2, "size before erase is " << children.size());
00451     children.erase(children.begin() + pos);
00452     //LOG("Vobject", 2, "size after erase is " << children.size());
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(); // acquired by: insertChild() or setChild()
00472 
00473             for(set<ParentChangeListener*>::iterator i = v->parentListeners.begin();
00474                 i != v->parentListeners.end(); i++)
00475             {
00476                 /*try {
00477                   (*i)->notifyParentRemoved(*v, *this, c->position, c->contextual_name);
00478                   } catch(runtime_error x) {
00479                   LOG("refcount", 0, "call to notifyParentRemoved emitted exception: " << x.what());
00480                   } catch(...) { }*/
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 /* get the next message this object has received */
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     // pass the reference through
00514     return m;
00515 }
00516 
00517 void VobjectImplementation::sendUpdateMessage(Message* m)
00518 {
00519     if(queueUpdateMsgs) {
00520         m->acquire(); // released by: the caller of receiveUpdateMessage()
00521         incomingUpdateMessageQueue.push_back(m);
00522         // do not release "m" because we are holding onto
00523         // a reference to it
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     // do not release because we are implicitly transfering
00537     // the acquire from incomingMessageQueue to the calling method
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(); // released by: removeTypeListener() or this destructor
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(); // released by: removeParentListener() or this destructor
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(); // released by: removeChildListener() or this destructor
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(); // acquired by: addTypeListener()
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(); // acquired by: addParentListener()
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(); // acquired by: addChildListener()
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     //if(site) site->release(); // acquired by: constructor
00712     //site=0;
00713 
00714     for(int i=children.size() - 1; i >= 0; i--) {
00715         VobjectImplementation::removeChild(i);
00716     }
00717 
00718     // copy it so as to avoid concurrently modifying the _same_ set object, which would be baaaaad.
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 

Generated on Tue Aug 12 03:55:42 2003 for Interreality Project - VOS by doxygen 1.3.2