node.C

Go to the documentation of this file.
00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00026 #include <archon/x3d/server/field_type.H>
00027 #include <archon/x3d/server/field.H>
00028 #include <archon/x3d/server/node.H>
00029 #include <archon/x3d/server/scene.H>
00030 #include <archon/x3d/server/server.H>
00031 
00032 namespace Archon
00033 {
00034   namespace X3D
00035   {
00036     NodeBase::NodeBase(BackRef<ExecutionContext> context):
00037       context(context), realized(false)
00038     {
00039       if(!context)
00040         ARCHON_THROW1(ArgumentException,
00041                       "ExecutionContext required to construct node");
00042     }
00043 
00044     NodeBase::NodeBase()
00045     {
00046       ARCHON_THROW1(InternalException,
00047                     "Construction of abstract node type");
00048     }
00049 
00050     NodeBase::~NodeBase()
00051     {
00052       try { context->changeNodeName(this, name, ""); } // Erase the mapping
00053       catch(ForwardDestroyedException &) {}
00054     }    
00055 
00056     void NodeBase::refForwardDestroy()
00057     {
00058       getType()->forwardClear(this);
00059       routeTargets.clear();
00060     }
00061 
00062     void NodeBase::realize()
00063     {
00064       {
00065         Mutex::Lock l(mutex);
00066         if(realized) return;
00067         realized = true;
00068       }
00069       onRealized();
00070     }
00071 
00072     bool NodeBase::isRealized() const
00073     {
00074       Mutex::Lock l(mutex);
00075       return realized;
00076     }
00077 
00078     string NodeBase::getName() const
00079     {
00080       Mutex::Lock l(mutex);
00081       return name;
00082     }
00083 
00084     void NodeBase::setName(string newName)
00085       throw(NodeNameInUseException)
00086     {
00087       Mutex::Lock l(mutex);
00088       context->changeNodeName(this, name, newName);
00089       name = newName;
00090     }
00091 
00092     const FieldBase *NodeBase::lookupField(string name) const
00093     {
00094       return getType()->lookupField(name);
00095     }
00096 
00097     Ref<ValueBase> NodeBase::get(const FieldBase *f) const
00098       throw(AccessException, UnexpectedException)
00099     {
00100       {
00101         Mutex::Lock l(mutex);
00102         if(!realized)
00103         {
00104           if(f->getIsEventTarget() != f->getIsEventSource())
00105             ARCHON_THROW(AccessException);
00106           return f->get(this);
00107         }
00108       }
00109       try
00110       {
00111         if(!f->getIsEventSource()) ARCHON_THROW(AccessException);
00112         Mutex::Lock l(context->server->scenegraphMutex);
00113         return f->get(this);
00114       }
00115       catch(ForwardDestroyedException &)
00116       {
00117         ARCHON_THROW(AccessException);
00118       }
00119     }
00120 
00121     unsigned NodeBase::getSize(const SequenceFieldBase *f) const
00122       throw(AccessException, UnexpectedException)
00123     {
00124       {
00125         Mutex::Lock l(mutex);
00126         if(!realized)
00127         {
00128           if(f->getIsEventTarget() != f->getIsEventSource())
00129             ARCHON_THROW(AccessException);
00130           return f->getSize(this);
00131         }
00132       }
00133       try
00134       {
00135         if(!f->getIsEventSource()) ARCHON_THROW(AccessException);
00136         Mutex::Lock l(context->server->scenegraphMutex);
00137         return f->getSize(this);
00138       }
00139       catch(ForwardDestroyedException &)
00140       {
00141         ARCHON_THROW(AccessException);
00142       }
00143     }
00144 
00145     Ref<ValueBase> NodeBase::getAt(const SequenceFieldBase *f, unsigned i) const
00146       throw(AccessException, RangeException, UnexpectedException)
00147     {
00148       {
00149         Mutex::Lock l(mutex);
00150         if(!realized)
00151         {
00152           if(f->getIsEventTarget() != f->getIsEventSource())
00153             ARCHON_THROW(AccessException);
00154           if(i >= f->getSize(this)) ARCHON_THROW(RangeException);
00155           return f->getAt(this, i);
00156         }
00157       }
00158       try
00159       {
00160         if(!f->getIsEventSource()) ARCHON_THROW(AccessException);
00161         Mutex::Lock l(context->server->scenegraphMutex);
00162         if(i >= f->getSize(this)) ARCHON_THROW(RangeException);
00163         return f->getAt(this, i);
00164       }
00165       catch(ForwardDestroyedException &)
00166       {
00167         ARCHON_THROW(AccessException);
00168       }
00169     }
00170 
00175     void NodeBase::set(const FieldBase *f, const Event *e)
00176       throw(AccessException, UnexpectedException)
00177     {
00178       // If the event value consists of one or more nodes then verify
00179       // and realize them
00180       if(const NodeValue *v = dynamic_cast<const NodeValue *>(e->value.get()))
00181       {
00182         if(v->value)
00183         {
00184           if(v->value->context != context)
00185             ARCHON_THROW1(ArgumentException,
00186                           "set: Node has wrong context");
00187           v->value->realize();
00188         }
00189       }
00190       else if(const NodeSequenceValue *v =
00191               dynamic_cast<const NodeSequenceValue *>(e->value.get()))
00192         for(NodeSequenceValue::ConstIterator i=v->begin(); i!=v->end(); ++i)
00193         {
00194           if(!*i)
00195             ARCHON_THROW1(ArgumentException,
00196                           "set: null found in node vector");
00197           if((*i)->context != context)
00198             ARCHON_THROW1(ArgumentException,
00199                           "set: Node has wrong context");
00200           (*i)->realize();
00201         }
00202       
00203       {
00204         Mutex::Lock l(mutex);
00205         if(!realized)
00206         {
00207           if(f->getIsEventTarget() != f->getIsEventSource())
00208             ARCHON_THROW(AccessException);
00209           f->set(this, e, false);
00210           return;
00211         }
00212       }
00213       try
00214       {
00215         if(!f->getIsEventTarget()) ARCHON_THROW(AccessException);
00216         Mutex::Lock l(context->server->scenegraphMutex);
00217         f->set(this, e, true);
00218       }
00219       catch(ForwardDestroyedException &)
00220       {
00221         ARCHON_THROW(AccessException);
00222       }
00223     }
00224 
00229     void NodeBase::setAt(const SequenceFieldBase *f, Ref<const ValueBase> v,
00230                      unsigned i, Time t)
00231       throw(AccessException, RangeException, UnexpectedException)
00232     {
00233       if(const NodeValue *w = dynamic_cast<const NodeValue *>(v.get()))
00234       {
00235         if(!w->value)
00236           ARCHON_THROW1(ArgumentException, "setAt: Node was null");
00237         if(w->value->context != context)
00238           ARCHON_THROW1(ArgumentException, "setAt: Node has wrong context");
00239         w->value->realize();
00240       }
00241 
00242       {
00243         Mutex::Lock l(mutex);
00244         if(!realized)
00245         {
00246           if(f->getIsEventTarget() != f->getIsEventSource())
00247             ARCHON_THROW(AccessException);
00248           if(i >= f->getSize(this)) ARCHON_THROW(RangeException);
00249           f->setAt(this, v.get(), i, t, false);
00250           return;
00251         }
00252       }
00253       try
00254       {
00255         if(!f->getIsEventTarget() || !f->getIsEventSource())
00256           ARCHON_THROW(AccessException);
00257         Mutex::Lock l(context->server->scenegraphMutex);
00258         if(i >= f->getSize(this)) ARCHON_THROW(RangeException);
00259         f->setAt(this, v.get(), i, t, true);
00260       }
00261       catch(ForwardDestroyedException &)
00262       {
00263         ARCHON_THROW(AccessException);
00264       }
00265     }
00266 
00271     void NodeBase::add(const SequenceFieldBase *f, Ref<const ValueBase> v, Time t)
00272       throw(AccessException, UnexpectedException)
00273     {
00274       if(const NodeValue *w = dynamic_cast<const NodeValue *>(v.get()))
00275       {
00276         if(!w->value)
00277           ARCHON_THROW1(ArgumentException, "add: Node was null");
00278         if(w->value->context != context)
00279           ARCHON_THROW1(ArgumentException, "add: Node has wrong context");
00280         w->value->realize();
00281       }
00282 
00283       {
00284         Mutex::Lock l(mutex);
00285         if(!realized)
00286         {
00287           if(f->getIsEventTarget() != f->getIsEventSource())
00288             ARCHON_THROW(AccessException);
00289           f->add(this, v.get(), t, false);
00290           return;
00291         }
00292       }
00293       try
00294       {
00295         if(!f->getIsEventTarget() || !f->getIsEventSource())
00296           ARCHON_THROW(AccessException);
00297         Mutex::Lock l(context->server->scenegraphMutex);
00298         f->add(this, v.get(), t, true);
00299       }
00300       catch(ForwardDestroyedException &)
00301       {
00302         ARCHON_THROW(AccessException);
00303       }
00304     }
00305 
00309     void NodeBase::remove(const SequenceFieldBase *f, Ref<const ValueBase> v,
00310                       Time t)
00311       throw(AccessException, UnexpectedException)
00312     {
00313       if(const NodeValue *w = dynamic_cast<const NodeValue *>(v.get()))
00314       {
00315         if(!w->value)
00316           ARCHON_THROW1(ArgumentException, "remove: Node was null");
00317         if(w->value->context != context)
00318           ARCHON_THROW1(ArgumentException, "remove: Node has wrong context");
00319       }
00320 
00321       {
00322         Mutex::Lock l(mutex);
00323         if(!realized)
00324         {
00325           if(f->getIsEventTarget() != f->getIsEventSource())
00326             ARCHON_THROW(AccessException);
00327           f->remove(this, v.get(), t, false);
00328           return;
00329         }
00330       }
00331       try
00332       {
00333         if(!f->getIsEventTarget() || !f->getIsEventSource())
00334           ARCHON_THROW(AccessException);
00335         Mutex::Lock l(context->server->scenegraphMutex);
00336         f->remove(this, v.get(), t, true);
00337       }
00338       catch(ForwardDestroyedException &)
00339       {
00340         ARCHON_THROW(AccessException);
00341       }
00342     }
00343 
00344     void NodeBase::add(const NodeSequenceFieldBase *f, Ref<NodeBase> n, Time t)
00345       throw(AccessException, UnexpectedException)
00346     {
00347       add(f, new NodeValue(SFNode::type, n.get()), t);
00348     }
00349 
00350     void NodeBase::remove(const NodeSequenceFieldBase *f, Ref<NodeBase> n, Time t)
00351       throw(AccessException, UnexpectedException)
00352     {
00353       remove(f, new NodeValue(SFNode::type, n.get()), t);
00354     }
00355 
00356 
00357     bool NodeBase::inject(const NodeFieldBase *f, Ref<NodeBase> n, Time stamp)
00358       throw(AccessException, UnexpectedException)
00359     {
00360       if(!n) ARCHON_THROW1(ArgumentException,
00361                            "inject: Node was null");
00362       if(n->context != context)
00363         ARCHON_THROW1(ArgumentException,
00364                       "inject: Node has wrong context");
00365 
00366       n->realize();
00367 
00368       {
00369         Mutex::Lock l(mutex);
00370         if(!realized)
00371         {
00372           if(f->getIsEventTarget() != f->getIsEventSource())
00373             ARCHON_THROW(AccessException);
00374           return f->inject(this, n.get(), stamp, false);
00375         }
00376       }
00377       try
00378       {
00379         if(!f->getIsEventTarget()) ARCHON_THROW(AccessException);
00380         Mutex::Lock l(context->server->scenegraphMutex);
00381         return f->inject(this, n.get(), stamp, true);
00382       }
00383       catch(ForwardDestroyedException &)
00384       {
00385         ARCHON_THROW(AccessException);
00386       }
00387     }
00388 
00389     bool NodeBase::changedSince(const Time &t) const
00390     {
00391       return getType()->changedSince(this, t);
00392     }
00393 
00394     /*
00395     string NodeBase::dumpFields(int level) const
00396     {
00397       return getType()->dumpFields(this, level);
00398     }
00399     */
00400 
00409     /*
00410     string NodeBase::dump(set<const NodeBase *> processedNodes, int level, bool indentFirstLine) const
00411     {
00412       string indent(2*level, ' ');
00413       string s;
00414       if(indentFirstLine) s += indent;
00415       string name = getName();
00416 
00417       if(!processedNodes.insert(this).second)
00418       {
00419         if(name.empty()) cerr << "Found recurring node with no name (skipping)" << endl;
00420         s += "USE \"" + name + "\"\n";
00421         return s;
00422       }
00423 
00424       if(!name.empty()) s += "DEF \"" + name + "\" ";
00425       s += getType()->getName() + " # [" +
00426         Text::toString(getUseCount()) + "]\n";
00427       s += indent + "{\n";
00428       s += dumpFields(level+1);
00429       s += indent + "}\n";
00430       return s;
00431     }
00432     */
00433 
00434     void NodeBase::addRouteTarget(Ref<const RouteHead> r)
00435     {
00436       Mutex::Lock l(routeTargetsMutex);
00437       routeTargets.push_back(r);
00438     }
00439 
00440     void NodeBase::removeRouteTarget(Ref<const RouteHead> r)
00441     {
00442       Mutex::Lock l(routeTargetsMutex);
00443       routeTargets.remove(r);
00444     }
00445   }
00446 }

Generated on Sun Jul 30 22:55:47 2006 for Archon by  doxygen 1.4.4