00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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, ""); }
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
00179
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
00396
00397
00398
00399
00400
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
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 }