ObjectFactory.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
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       //std::cout << "ObjectFactory: class "<<classname<<" NOT FOUND."<<std::endl;
00095     }
00096       else
00097     {
00098 //    std::cout << "ObjectFactory: class "<<classname<<" FOUND."<<std::endl;
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 //        std::cout << "ObjectFactory: template "<<templatename<<" FOUND."<<std::endl;
00105           Creator* c = it2->second;
00106           if (c->canCreate(context, arg))
00107                 creators.push_back(c);
00108         }
00109       else
00110         {
00111 //        std::cout << "ObjectFactory: template "<<templatename<<" NOT FOUND."<<std::endl;
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"; //<<std::endl;
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 //      std::cout << "Create Instance : " << arg->getFullName() << "\n";
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 += "&lt;"; break;
00199         case '>': res += "&gt;"; break;
00200         case '&': res += "&amp;"; break;
00201         case '"': res += "&quot;"; break;
00202         case '\'': res += "&apos;"; 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     //std::cerr<<"description.size() = "<<description.size()<<", value = "<<description<<std::endl;
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       //std::cout << "ObjectFactory: add description "<<val<<std::endl;
00300       val += '\n';
00301       entry.description += val;
00302       return *this;
00303     }
00304 
00305     RegisterObject& RegisterObject::addAuthor(std::string val)
00306     {
00307       //std::cout << "ObjectFactory: add author "<<val<<std::endl;
00308       val += ' ';
00309       entry.authors += val;
00310       return *this;
00311     }
00312 
00313     RegisterObject& RegisterObject::addLicense(std::string val)
00314     {
00315       //std::cout << "ObjectFactory: add license "<<val<<std::endl;
00316       entry.license += val;
00317       return *this;
00318     }
00319 
00320     RegisterObject& RegisterObject::addCreator(std::string classname, std::string templatename, ObjectFactory::Creator* creator)
00321     {
00322       //std::cout << "ObjectFactory: add creator "<<classname<<" with template "<<templatename<<std::endl;
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       //std::cout << "ObjectFactory: commit"<<std::endl;
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         //for (std::map<std::string, ObjectFactory::Creator*>::iterator itc = entry.creators.begin(), itcend = entry.creators.end(); itc != itcend; ++itc)
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       //std::cout << "ObjectFactory: commit end"<<std::endl;
00392       return 1;
00393     }
00394     }
00395 
00396     // void ObjectFactory::ClassEntry::print()
00397     // {
00398     //   cout<<"className = "<<className<<endl;
00399     //   cout<<"  baseClasses: ";
00400     //   for( std::set<std::string>::const_iterator i=baseClasses.begin(), iend=baseClasses.end(); i!=iend; i++ )
00401     //     cout<<*i<<", ";
00402     //   cout<<endl;
00403     //   cout<<"  aliases: ";
00404     //   for( std::set<std::string>::const_iterator i=aliases.begin(), iend=aliases.end(); i!=iend; i++ )
00405     //     cout<<*i<<", ";
00406     //   cout<<endl;
00407     //   cout<<"  description: "<<description<<endl;
00408     //   cout<<"  authors: "<<authors<<endl;
00409     //   cout<<"  license: "<<license<<endl; 
00410     //   cout<<"  creators: ";
00411     //   for( std::list< std::pair<std::string, Creator*> >::const_iterator i=creatorList.begin(), iend=creatorList.end(); i!=iend; i++ )
00412     //     cout<<(*i).first<<", ";
00413     //   cout<<endl;
00414     //   cout<<"  creatorMap: ";
00415     //   for( std::map<std::string, Creator*>::const_iterator i=creatorMap.begin(), iend=creatorMap.end(); i!=iend; i++ )
00416     //     cout<<(*i).first<<", ";
00417     //   cout<<endl;
00418     //   
00419     // }
00420 
00421   } // namespace core
00422 
00423 } // namespace sofa

Generated on Sun Nov 23 02:29:25 2008 for Sofa by  doxygen 1.5.7.1