ObjectFactory.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "ObjectFactory.h"
00028 #include <iostream>
00029 using std::cout;
00030 using std::cerr;
00031 using std::endl;
00032
00033 namespace sofa
00034 {
00035
00036 namespace core
00037 {
00038
00039 ObjectFactory::ClassEntry* ObjectFactory::getEntry(std::string classname)
00040 {
00041 ClassEntry*& p = registry[classname];
00042 if (p==NULL)
00043 {
00044 p = new ClassEntry;
00045 p->className = classname;
00046 }
00047 return p;
00048 }
00049
00050 bool ObjectFactory::addAlias(std::string name, std::string result, bool force, ClassEntry** previous)
00051 {
00052 ClassEntry*& p = registry[name];
00053 if (previous)
00054 *previous = p;
00055 std::map<std::string, ClassEntry*>::iterator it = registry.find(result);
00056 if (it == registry.end())
00057 {
00058 std::cerr << "ERROR: ObjectFactory: cannot create alias "<<name<<" to unknown class " << result << ".\n";
00059 return false;
00060 }
00061 ClassEntry* entry = it->second;
00062 if (p!=NULL && !force)
00063 {
00064 std::cerr << "ERROR: ObjectFactory: cannot create alias "<<name<<" as a class with this name already exists.\n";
00065 return false;
00066 }
00067 else
00068 {
00069 if (p!=NULL)
00070 {
00071 p->aliases.erase(name);
00072 }
00073 p = entry;
00074 entry->aliases.insert(name);
00075 return true;
00076 }
00077 }
00078
00079 void ObjectFactory::resetAlias(std::string name, ClassEntry* previous)
00080 {
00081 ClassEntry*& p = registry[name];
00082 p = previous;
00083 }
00084
00085 objectmodel::BaseObject* ObjectFactory::createObject(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg)
00086 {
00087 objectmodel::BaseObject* object = NULL;
00088 std::vector<Creator*> creators;
00089 std::string classname = arg->getAttribute( "type", "");
00090 std::string templatename = arg->getAttribute( "template", "");
00091 std::map<std::string, ClassEntry*>::iterator it = registry.find(classname);
00092 if (it == registry.end())
00093 {
00094
00095 }
00096 else
00097 {
00098
00099 ClassEntry* entry = it->second;
00100 if(templatename.empty()) templatename = entry->defaultTemplate;
00101 std::map<std::string, Creator*>::iterator it2 = entry->creatorMap.find(templatename);
00102 if (it2 != entry->creatorMap.end())
00103 {
00104
00105 Creator* c = it2->second;
00106 if (c->canCreate(context, arg))
00107 creators.push_back(c);
00108 }
00109 else
00110 {
00111
00112 std::list< std::pair< std::string, Creator*> >::iterator it3;
00113 for (it3 = entry->creatorList.begin(); it3 != entry->creatorList.end(); ++it3)
00114 {
00115 Creator* c = it3->second;
00116 if (c->canCreate(context, arg))
00117 creators.push_back(c);
00118 }
00119 }
00120 }
00121 if (creators.empty())
00122 {
00123 std::cerr<<"ERROR: ObjectFactory: Object type "<<classname<<"<"<<templatename<<"> creation failed."<<std::endl;
00124 }
00125 else
00126 {
00127 if (creators.size()>1)
00128 {
00129 std::cerr<<"WARNING: ObjectFactory: Several possibilities found for type "<<classname<<"<"<<templatename<<">:\n";
00130 for(unsigned int i=0;i<creators.size();++i)
00131 std::cerr << " " << objectmodel::Base::decodeTemplateName(creators[i]->type()) << std::endl;
00132 std::cerr << std::endl;
00133 }
00134
00135 object = creators[0]->createInstance(context, arg);
00136 }
00137 return object;
00138 }
00139
00140 ObjectFactory* ObjectFactory::getInstance()
00141 {
00142 static ObjectFactory instance;
00143 return &instance;
00144 }
00145
00146 void ObjectFactory::getAllEntries(std::vector<ClassEntry*>& result)
00147 {
00148 result.clear();
00149 for (std::map<std::string, ClassEntry*>::iterator it = registry.begin(), itend = registry.end(); it != itend; ++it)
00150 {
00151 ClassEntry* entry = it->second;
00152 if (entry->className != it->first) continue;
00153 result.push_back(entry);
00154 }
00155 }
00156
00157 void ObjectFactory::dump(std::ostream& out)
00158 {
00159 for (std::map<std::string, ClassEntry*>::iterator it = registry.begin(), itend = registry.end(); it != itend; ++it)
00160 {
00161 ClassEntry* entry = it->second;
00162 if (entry->className != it->first) continue;
00163 out << "class " << entry->className <<" :\n";
00164 if (!entry->aliases.empty())
00165 {
00166 out << " aliases :";
00167 for (std::set<std::string>::iterator it = entry->aliases.begin(), itend = entry->aliases.end(); it != itend; ++it)
00168 out << " " << *it;
00169 out << "\n";
00170 }
00171 if (!entry->baseClasses.empty())
00172 {
00173 out << " base classes :";
00174 for (std::set<std::string>::iterator it = entry->baseClasses.begin(), itend = entry->baseClasses.end(); it != itend; ++it)
00175 out << " " << *it;
00176 out << "\n";
00177 }
00178 if (!entry->description.empty())
00179 out << entry->description;
00180 if (!entry->authors.empty())
00181 out << " authors : " << entry->authors << "\n";
00182 if (!entry->license.empty())
00183 out << " license : " << entry->license << "\n";
00184 for (std::list< std::pair< std::string, Creator* > >::iterator itc = entry->creatorList.begin(), itcend = entry->creatorList.end(); itc != itcend; ++itc)
00185 {
00186 out << " template instance : " << itc->first << "\n";
00187 }
00188 }
00189 }
00190
00191 static std::string xmlencode(const std::string& str)
00192 {
00193 std::string res;
00194 for (unsigned int i=0; i<str.length(); ++i)
00195 {
00196 switch(str[i])
00197 {
00198 case '<': res += "<"; break;
00199 case '>': res += ">"; break;
00200 case '&': res += "&"; break;
00201 case '"': res += """; break;
00202 case '\'': res += "'"; break;
00203 default: res += str[i];
00204 }
00205 }
00206 return res;
00207 }
00208
00209 void ObjectFactory::dumpXML(std::ostream& out)
00210 {
00211 for (std::map<std::string, ClassEntry*>::iterator it = registry.begin(), itend = registry.end(); it != itend; ++it)
00212 {
00213 ClassEntry* entry = it->second;
00214 if (entry->className != it->first) continue;
00215 out << "<class name=\"" << xmlencode(entry->className) <<"\">\n";
00216 for (std::set<std::string>::iterator it = entry->aliases.begin(), itend = entry->aliases.end(); it != itend; ++it)
00217 out << "<alias>" << xmlencode(*it) << "</alias>\n";
00218 for (std::set<std::string>::iterator it = entry->baseClasses.begin(), itend = entry->baseClasses.end(); it != itend; ++it)
00219 out << "<base>" << *it << "</base>\n";
00220 if (!entry->description.empty())
00221 out << "<description>"<<entry->description<<"</description>\n";
00222 if (!entry->authors.empty())
00223 out << "<authors>"<<entry->authors<<"</authors>\n";
00224 if (!entry->license.empty())
00225 out << "<license>"<<entry->license<<"</license>\n";
00226 for (std::list< std::pair< std::string, Creator* > >::iterator itc = entry->creatorList.begin(), itcend = entry->creatorList.end(); itc != itcend; ++itc)
00227 {
00228 out << "<creator";
00229 if (!itc->first.empty()) out << " template=\"" << xmlencode(itc->first) << "\"";
00230 out << "/>\n";
00231 }
00232 out << "</class>\n";
00233 }
00234 }
00235
00236 void ObjectFactory::dumpHTML(std::ostream& out)
00237 {
00238 out << "<ul>\n";
00239 for (std::map<std::string, ClassEntry*>::iterator it = registry.begin(), itend = registry.end(); it != itend; ++it)
00240 {
00241 ClassEntry* entry = it->second;
00242 if (entry->className != it->first) continue;
00243 out << "<li><b>" << xmlencode(entry->className) <<"</b>\n";
00244 if (!entry->description.empty())
00245 out << "<br/>"<<entry->description<<"\n";
00246 out << "<ul>\n";
00247 if (!entry->aliases.empty())
00248 {
00249 out << "<li>Aliases:<i>";
00250 for (std::set<std::string>::iterator it = entry->aliases.begin(), itend = entry->aliases.end(); it != itend; ++it)
00251 out << " " << xmlencode(*it);
00252 out << "</i></li>\n";
00253 }
00254 if (!entry->baseClasses.empty())
00255 {
00256 out << "<li>Base Classes:<b>";
00257 for (std::set<std::string>::iterator it = entry->baseClasses.begin(), itend = entry->baseClasses.end(); it != itend; ++it)
00258 out << " " << xmlencode(*it);
00259 out << "</b></li>\n";
00260 }
00261 if (!entry->authors.empty())
00262 out << "<li>Authors: <i>"<<entry->authors<<"</i></li>\n";
00263 if (!entry->license.empty())
00264 out << "<li>License: <i>"<<entry->license<<"</i></li>\n";
00265 if (entry->creatorList.size()>2 || (entry->creatorList.size()==1 && !entry->creatorList.begin()->first.empty()))
00266 {
00267 out << "<li>Template instances:<i>";
00268 for (std::list< std::pair< std::string, Creator* > >::iterator itc = entry->creatorList.begin(), itcend = entry->creatorList.end(); itc != itcend; ++itc)
00269 {
00270 if (itc->first == entry->defaultTemplate)
00271 out << " <b>" << xmlencode(itc->first) << "</b>";
00272 else
00273 out << " " << xmlencode(itc->first);
00274 }
00275 out << "</i></li>\n";
00276 }
00277 out << "</ul>\n";
00278 out << "</li>\n";
00279 }
00280 out << "</ul>\n";
00281 }
00282
00283 RegisterObject::RegisterObject(const std::string& description)
00284 {
00285 if (!description.empty()){
00286
00287 addDescription(description);
00288 }
00289 }
00290
00291 RegisterObject& RegisterObject::addAlias(std::string val)
00292 {
00293 entry.aliases.insert(val);
00294 return *this;
00295 }
00296
00297 RegisterObject& RegisterObject::addDescription(std::string val)
00298 {
00299
00300 val += '\n';
00301 entry.description += val;
00302 return *this;
00303 }
00304
00305 RegisterObject& RegisterObject::addAuthor(std::string val)
00306 {
00307
00308 val += ' ';
00309 entry.authors += val;
00310 return *this;
00311 }
00312
00313 RegisterObject& RegisterObject::addLicense(std::string val)
00314 {
00315
00316 entry.license += val;
00317 return *this;
00318 }
00319
00320 RegisterObject& RegisterObject::addCreator(std::string classname, std::string templatename, ObjectFactory::Creator* creator)
00321 {
00322
00323 if (!entry.className.empty() && entry.className != classname)
00324 {
00325 std::cerr << "ERROR: ObjectFactory: all templated class should have the same base classname ("<<entry.className<<"!="<<classname<<")\n";
00326 }
00327 else if (entry.creatorMap.find(templatename) != entry.creatorMap.end())
00328 {
00329 std::cerr << "ERROR: ObjectFactory: class "<<classname<<"<"<<templatename<<"> already registered\n";
00330 }
00331 else
00332 {
00333 entry.className = classname;
00334 entry.creatorMap.insert(std::make_pair(templatename, creator));
00335 entry.creatorList.push_back(std::make_pair(templatename, creator));
00336 }
00337 return *this;
00338 }
00339
00340 RegisterObject::operator int()
00341 {
00342 if (entry.className.empty())
00343 {
00344 return 0;
00345 }
00346 else
00347 {
00348
00349 ObjectFactory::ClassEntry* reg = ObjectFactory::getInstance()->getEntry(entry.className);
00350 reg->description += entry.description;
00351 reg->authors += entry.authors;
00352 reg->license += entry.license;
00353 if (!entry.defaultTemplate.empty())
00354 {
00355 if (!reg->defaultTemplate.empty())
00356 {
00357 std::cerr << "ERROR: ObjectFactory: default template for class "<<entry.className<<" already registered <"<<reg->defaultTemplate<<">, do not register <"<<entry.defaultTemplate<<"> as default.\n";
00358 }
00359 else
00360 {
00361 reg->defaultTemplate = entry.defaultTemplate;
00362 }
00363 }
00364 for (std::list< std::pair< std::string, ObjectFactory::Creator* > >::iterator itc = entry.creatorList.begin(), itcend = entry.creatorList.end(); itc != itcend; ++itc)
00365
00366 {
00367 if (reg->creatorMap.find(itc->first) != reg->creatorMap.end())
00368 {
00369 std::cerr << "ERROR: ObjectFactory: class "<<entry.className<<"<"<<itc->first<<"> already registered\n";
00370 }
00371 else
00372 {
00373 reg->creatorMap.insert(*itc);
00374 reg->creatorList.push_back(*itc);
00375 }
00376 }
00377 for (std::set<std::string>::iterator it = entry.aliases.begin(), itend = entry.aliases.end(); it != itend; ++it)
00378 {
00379 if (reg->aliases.find(*it) == reg->aliases.end())
00380 {
00381 ObjectFactory::getInstance()->addAlias(*it,entry.className);
00382 }
00383 }
00384 for (std::set<std::string>::iterator it = entry.baseClasses.begin(), itend = entry.baseClasses.end(); it != itend; ++it)
00385 {
00386 if (reg->baseClasses.find(*it) == reg->baseClasses.end())
00387 {
00388 reg->baseClasses.insert(*it);
00389 }
00390 }
00391
00392 return 1;
00393 }
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 }
00422
00423 }