type.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/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       // Verify uniqueness of all local and inherited field names
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     string NodeType::dumpFields(const NodeBase *n, int level) const
00305     {
00306       string s;
00307       for(unsigned i=0; i<derivedFrom.size(); ++i)
00308         s += derivedFrom[i]->dumpFields(n, level);
00309       for(unsigned i=0; i<fields.size(); ++i)
00310         s += fields[i]->dump(n, level);
00311       return s;
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 }

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