00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include <archon/util/term.H>
00027 #include <archon/util/text.H>
00028
00029 #include <archon/x3d/server/type.H>
00030 #include <archon/x3d/server/node.H>
00031 #include <archon/x3d/server/scene.H>
00032 #include <archon/x3d/server/custom_field.H>
00033
00034 namespace Archon
00035 {
00036 using namespace Utilities;
00037
00038 namespace X3D
00039 {
00040 namespace
00041 {
00045 vector<const NodeType *> nodeTypes;
00046
00047 map<string, const NodeType *> nodeTypeMap;
00048 map<string, const FieldType *> fieldTypeMap;
00049 }
00050
00051 void NodeType::addFields(vector<pair<const FieldBase *,
00052 const NodeType *> > &l) const
00053 {
00054 for(unsigned i=0; i<derivedFrom.size(); ++i)
00055 derivedFrom[i]->addFields(l);
00056 for(unsigned i=0; i<fields.size(); ++i)
00057 l.push_back(make_pair(fields[i], this));
00058 }
00059
00060 void NodeType::initFieldMap(map<string, const FieldBase *> &m,
00061 string nodeType,
00062 set<const NodeType *> &virtualBases) const
00063 {
00064 for(unsigned i=0; i<derivedFrom.size(); ++i)
00065 {
00066 const NodeType *b = derivedFrom[i];
00067 if(!b->isVirtualBase() || virtualBases.insert(b).second)
00068 b->initFieldMap(m, nodeType, virtualBases);
00069 }
00070 for(unsigned i=0; i<fields.size(); ++i)
00071 {
00072 const FieldBase *f = fields[i];
00073 if(!m.insert(make_pair(f->getName(), f)).second ||
00074 f->getIsEventTarget() && f->getIsEventSource() &&
00075 (!m.insert(make_pair("set_" + f->getName(), f)).second ||
00076 !m.insert(make_pair(f->getName() + "_changed", f)).second))
00077 ARCHON_THROW1(InternalException,
00078 "Ambiguous field '" + f->getName() +
00079 "' for node type '" + nodeType + "'");
00080 }
00081 }
00082
00083 NodeType::NodeType(string name, string containerField,
00084 bool virtualBase,
00085 const vector<const NodeType *> *d,
00086 const vector<const FieldBase *> *f,
00087 Ref<NodeBase> (*instanceMaker)(BackRef<ExecutionContext>)):
00088 index(nodeTypes.size()), name(name), containerField(containerField),
00089 virtualBase(virtualBase), internalUseOnly(false),
00090 instanceMaker(instanceMaker)
00091 {
00092 if(nodeTypes.size() == (1 << maxIndexBits) - 1)
00093 ARCHON_THROW1(InternalException, "Too many node types");
00094
00095 if(d) derivedFrom = *d;
00096
00097 setFields(f);
00098
00099 if(!nodeTypeMap.insert(make_pair(name, this)).second)
00100 ARCHON_THROW1(InternalException,
00101 "Redefinition of node type '" + name + "'");
00102
00103 nodeTypes.push_back(this);
00104 }
00105
00106 void NodeType::setFields(const vector<const FieldBase *> *f)
00107 {
00108 fields.clear();
00109 if(f)
00110 {
00111 fields = *f;
00112 for(unsigned i=0; i<fields.size(); ++i)
00113 {
00114 unsigned long j = i;
00115 j <<= maxIndexBits;
00116 j |= index;
00117 const_cast<FieldBase *>(fields[i])->id = j;
00118 }
00119 }
00120
00121
00122 fieldMap.clear();
00123 set<const NodeType *> virtualBases;
00124 initFieldMap(fieldMap, name, virtualBases);
00125 }
00126
00127 unsigned long NodeType::getTotalNumber()
00128 {
00129 return nodeTypes.size();
00130 }
00131
00132 const NodeType *NodeType::get(unsigned long i)
00133 {
00134 if(i >= nodeTypes.size())
00135 ARCHON_THROW1(ArgumentException, "Index out of bound");
00136 return nodeTypes[i];
00137 }
00138
00139 const NodeType *NodeType::lookup(const string &n)
00140 {
00141 map<string, const NodeType *>::iterator i = nodeTypeMap.find(n);
00142 return i==nodeTypeMap.end() ? 0 : i->second;
00143 }
00144
00145 Ref<NodeBase> NodeType::instantiate(BackRef<ExecutionContext> c) const
00146 {
00147 if(!instanceMaker)
00148 ARCHON_THROW1(ArgumentException,
00149 "Attempt to instantiate abstract node type");
00150 return (*instanceMaker)(c);
00151 }
00152
00153 bool NodeType::isDerivedFrom(const NodeType *baseType) const
00154 {
00155 if(this == baseType) return true;
00156 for(unsigned i=0; i<derivedFrom.size(); ++i)
00157 if(derivedFrom[i]->isDerivedFrom(baseType)) return true;
00158 return false;
00159 }
00160
00161
00162 const FieldBase *FieldBase::fetch(unsigned long i, const NodeBase *n)
00163 {
00164 unsigned long j = i & (1 << NodeType::maxIndexBits) - 1;
00165 if(j >= nodeTypes.size()) return 0;
00166 const NodeType *t = nodeTypes[j];
00167 unsigned long k = i >> NodeType::maxIndexBits;
00168 if(k < t->getNumberOfImmediateFields()) return t->getImmediateField(k);
00169 if(!n || j != n->getType()->getIndex()) return 0;
00170 const CustomFieldNode *m = dynamic_cast<const CustomFieldNode *>(n);
00171 if(!m) return 0;
00172 return m->getCustomField(k - t->getNumberOfImmediateFields()).get();
00173 }
00174
00175
00176 FieldBase::FieldBase(string name, const FieldType *type,
00177 bool isEventTarget, bool isEventSource):
00178 isEventTarget(isEventTarget), isEventSource(isEventSource),
00179 id(0), name(name), type(type)
00180 {
00181 }
00182
00183 const FieldBase *NodeType::lookupField(string name) const
00184 {
00185 map<string, const FieldBase *>::const_iterator i =
00186 fieldMap.find(name);
00187 return i==fieldMap.end() ? 0 : i->second;
00188 }
00189
00190 const FieldBase *NodeType::lookupImmediateField(string name) const
00191 {
00192 for(unsigned i=0; i<fields.size(); ++i)
00193 {
00194 const FieldBase *f = fields[i];
00195 if(f->getName() == name) return f;
00196 }
00197 return 0;
00198 }
00199
00200 const NodeFieldBase *NodeType::lookupNodeField(const NodeType *nodeType) const
00201 {
00202 for(unsigned i=0; i<derivedFrom.size(); ++i)
00203 {
00204 const NodeFieldBase *f = derivedFrom[i]->lookupNodeField(nodeType);
00205 if(f) return f;
00206 }
00207 for(unsigned i=0; i<fields.size(); ++i)
00208 {
00209 if(const NodeFieldBase *f =
00210 dynamic_cast<const NodeFieldBase *>(fields[i]))
00211 {
00212 if(f->getIsEventTarget() == f->getIsEventSource() &&
00213 nodeType->isDerivedFrom(f->getNodeType())) return f;
00214 }
00215 }
00216 return 0;
00217 }
00218
00219 const NodeType *NodeType::
00220 newAbstract(string name, bool virtualBase,
00221 const vector<const FieldBase *> *fields)
00222 {
00223 return new NodeType(name, "", virtualBase, 0, fields, 0);
00224 }
00225
00226 const NodeType *NodeType::
00227 newAbstract(string name, bool virtualBase,
00228 const vector<const FieldBase *> *fields,
00229 const NodeType *derivedFrom1)
00230 {
00231 if(!derivedFrom1)
00232 ARCHON_THROW1(InternalException,
00233 "Deriving '" + name + "' from uninitialized node type");
00234 vector<const NodeType *> derivedFrom;
00235 derivedFrom.push_back(derivedFrom1);
00236 return new NodeType(name, "", virtualBase, &derivedFrom, fields, 0);
00237 }
00238
00239 const NodeType *NodeType::
00240 newAbstract(string name, bool virtualBase,
00241 const vector<const FieldBase *> *fields,
00242 const NodeType *derivedFrom1,
00243 const NodeType *derivedFrom2)
00244 {
00245 if(!derivedFrom1 || !derivedFrom2)
00246 ARCHON_THROW1(InternalException,
00247 "Deriving '" + name + "' from uninitialized node type");
00248 vector<const NodeType *> derivedFrom;
00249 derivedFrom.push_back(derivedFrom1);
00250 derivedFrom.push_back(derivedFrom2);
00251 return new NodeType(name, "", virtualBase, &derivedFrom, fields, 0);
00252 }
00253
00254 const NodeType *NodeType::
00255 newConcrete(string name, string containerField,
00256 Ref<NodeBase> (*instanceMaker)(BackRef<ExecutionContext>),
00257 const vector<const FieldBase *> *fields,
00258 const NodeType *derivedFrom1)
00259 {
00260 if(!derivedFrom1)
00261 ARCHON_THROW1(InternalException,
00262 "Deriving '" + name + "' from uninitialized node type");
00263 vector<const NodeType *> derivedFrom;
00264 derivedFrom.push_back(derivedFrom1);
00265 return new NodeType(name, containerField, false,
00266 &derivedFrom, fields, instanceMaker);
00267 }
00268
00269 const NodeType *NodeType::
00270 newConcrete(string name, string containerField,
00271 Ref<NodeBase> (*instanceMaker)(BackRef<ExecutionContext>),
00272 const vector<const FieldBase *> *fields,
00273 const NodeType *derivedFrom1,
00274 const NodeType *derivedFrom2)
00275 {
00276 if(!derivedFrom1 || !derivedFrom2)
00277 ARCHON_THROW1(InternalException,
00278 "Deriving '" + name + "' from uninitialized node type");
00279 vector<const NodeType *> derivedFrom;
00280 derivedFrom.push_back(derivedFrom1);
00281 derivedFrom.push_back(derivedFrom2);
00282 return new NodeType(name, containerField, false,
00283 &derivedFrom, fields, instanceMaker);
00284 }
00285
00286 void NodeType::forwardClear(NodeBase *n) const
00287 {
00288 for(unsigned i=0; i<fields.size(); ++i)
00289 fields[i]->forwardClear(n);
00290 for(unsigned i=0; i<derivedFrom.size(); ++i)
00291 derivedFrom[i]->forwardClear(n);
00292 }
00293
00294 bool NodeType::changedSince(const NodeBase *n, const Time &t) const
00295 {
00296 for(unsigned i=0; i<fields.size(); ++i)
00297 if(fields[i]->changedSince(n, t)) return true;
00298 for(unsigned i=0; i<derivedFrom.size(); ++i)
00299 if(derivedFrom[i]->changedSince(n, t)) return true;
00300 return false;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 void NodeType::describe(Logger *logger) const
00316 {
00317 string header = getName();
00318 if(derivedFrom.size())
00319 {
00320 header += ": ";
00321 for(unsigned i=0; i<derivedFrom.size(); ++i)
00322 {
00323 if(i) header += ", ";
00324 header += derivedFrom[i]->getName();
00325 }
00326 }
00327 if(!instanceMaker) header += " // abstract";
00328 vector<pair<const FieldBase *, const NodeType *> > l;
00329 addFields(l);
00330 vector<double> columnWidthFractions;
00331 columnWidthFractions.push_back(0.1);
00332 columnWidthFractions.push_back(0.1);
00333 columnWidthFractions.push_back(0.2);
00334 columnWidthFractions.push_back(0.2);
00335 columnWidthFractions.push_back(0.2);
00336 columnWidthFractions.push_back(0.2);
00337 Text::Table<string> table(l.size(), columnWidthFractions);
00338 for(unsigned i=0; i<l.size(); ++i)
00339 {
00340 const FieldBase *f = l[i].first;
00341 table(i, 0) = " " + f->getType()->getName();
00342 table(i, 1) = "[" +
00343 string(f->getIsEventTarget()?"in":"") +
00344 (f->getIsEventTarget() && f->getIsEventSource()?",":"") +
00345 (f->getIsEventSource()?"out":"") + "]";
00346 table(i, 2) = f->getName();
00347 table(i, 3) = "<default value>";
00348 if(const NodeFieldBase *nf =
00349 dynamic_cast<const NodeFieldBase *>(f))
00350 table(i, 4) = nf->getNodeType()->getName();
00351 else
00352 table(i, 4) = "<domain>";
00353 if(l[i].second != this) table(i, 5) = "// " + l[i].second->getName();
00354 }
00355 logger->log(header + "\n{\n" +
00356 Text::format(table, Term::getWidth(), 2, false) + "}\n");
00357 }
00358
00359 void NodeType::describeAll(Logger *l)
00360 {
00361 for(unsigned i=0; i<nodeTypes.size(); ++i) nodeTypes[i]->describe(l);
00362 }
00363
00364 NodeType::iterator NodeType::derivedFromBegin() const
00365 {
00366 return derivedFrom.begin();
00367 }
00368
00369 NodeType::iterator NodeType::derivedFromEnd() const
00370 {
00371 return derivedFrom.end();
00372 }
00373
00374
00375 FieldType::FieldType(unsigned index, string name,
00376 const FieldType *singleType):
00377 index(index), name(name), singleType(singleType)
00378 {
00379 if(!fieldTypeMap.insert(make_pair(name, this)).second)
00380 ARCHON_THROW1(InternalException,
00381 "Redefinition of field type '" +
00382 name + "'");
00383 }
00384
00385 const FieldType *FieldType::lookup(string name)
00386 {
00387 map<string, const FieldType *>::iterator i = fieldTypeMap.find(name);
00388 return i==fieldTypeMap.end() ? 0 : i->second;
00389 }
00390 }
00391 }