ObjectFactory.h

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 #ifndef SOFA_CORE_OBJECTFACTORY_H
00028 #define SOFA_CORE_OBJECTFACTORY_H
00029 
00030 #include <sofa/helper/system/config.h>
00031 #include <sofa/core/objectmodel/BaseObjectDescription.h>
00032 #include <sofa/core/objectmodel/BaseContext.h>
00033 #include <sofa/core/objectmodel/ContextObject.h>
00034 #include <sofa/core/VisualModel.h>
00035 #include <sofa/core/BehaviorModel.h>
00036 #include <sofa/core/CollisionModel.h>
00037 #include <sofa/core/BaseMapping.h>
00038 #include <sofa/core/componentmodel/topology/TopologicalMapping.h>
00039 #include <sofa/core/componentmodel/behavior/BaseMechanicalState.h>
00040 #include <sofa/core/componentmodel/behavior/BaseForceField.h>
00041 #include <sofa/core/componentmodel/behavior/InteractionForceField.h>
00042 #include <sofa/core/componentmodel/behavior/BaseConstraint.h>
00043 #include <sofa/core/componentmodel/behavior/BaseMechanicalMapping.h>
00044 #include <sofa/core/componentmodel/behavior/BaseMass.h>
00045 #include <sofa/core/componentmodel/behavior/OdeSolver.h>
00046 #include <sofa/core/componentmodel/behavior/LinearSolver.h>
00047 #include <sofa/core/componentmodel/behavior/MasterSolver.h>
00048 #include <sofa/core/componentmodel/topology/Topology.h>
00049 #include <sofa/core/componentmodel/topology/BaseTopologyObject.h>
00050 #include <sofa/core/componentmodel/behavior/BaseController.h>
00051 
00052 #include <map>
00053 #include <iostream>
00054 #include <typeinfo>
00055 
00056 namespace sofa
00057 {
00058 
00059 namespace core
00060 {
00061 
00074 class ObjectFactory
00075 {
00076 public:
00077 
00079     class Creator
00080     {
00081     public:
00082         virtual ~Creator() { }
00086         virtual bool canCreate(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg) = 0;
00087 
00091         virtual objectmodel::BaseObject* createInstance(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg) = 0;
00092 
00094         virtual const std::type_info& type() = 0;
00095     };
00096 
00098     class ClassEntry
00099     {
00100     public:
00101         std::string className;
00102         std::set<std::string> baseClasses;
00103         std::set<std::string> aliases;
00104         std::string description;
00105         std::string authors;
00106         std::string license;
00107         std::string defaultTemplate;
00108         std::list< std::pair<std::string, Creator*> > creatorList;
00109         std::map<std::string, Creator*> creatorMap;
00110         //void print();
00111     };
00112 
00113 protected:
00114 
00116     std::map<std::string,ClassEntry*> registry;
00117 
00118 public:
00119 
00121     ClassEntry* getEntry(std::string classname);
00122 
00124     void getAllEntries(std::vector<ClassEntry*>& result);
00125 
00132     bool addAlias(std::string name, std::string result, bool force=false, ClassEntry** previous = NULL);
00133 
00138     void resetAlias(std::string name, ClassEntry* previous);
00139 
00141     objectmodel::BaseObject* createObject(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg);
00142 
00144     static ObjectFactory* getInstance();
00145 
00147     static objectmodel::BaseObject* CreateObject(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg)
00148     {
00149         return getInstance()->createObject(context, arg);
00150     }
00151 
00153     static bool AddAlias(std::string name, std::string result, bool force=false, ClassEntry** previous = NULL)
00154     {
00155         return getInstance()->addAlias(name, result, force, previous);
00156     }
00157 
00159     static void ResetAlias(std::string name, ClassEntry* previous)
00160     {
00161         getInstance()->resetAlias(name, previous);
00162     }
00163 
00165     void dump(std::ostream& out = std::cout);
00166 
00168     void dumpXML(std::ostream& out = std::cout);
00169 
00171     void dumpHTML(std::ostream& out = std::cout);
00172 };
00173 
00177 template<class RealObject>
00178 class ObjectCreator : public ObjectFactory::Creator
00179 {
00180 public:
00181     bool canCreate(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg)
00182     {
00183         RealObject* instance = NULL;
00184         return RealObject::canCreate(instance, context, arg);
00185     }
00186     objectmodel::BaseObject *createInstance(objectmodel::BaseContext* context, objectmodel::BaseObjectDescription* arg)
00187     {
00188         RealObject* instance = NULL;
00189         RealObject::create(instance, context, arg);
00190         return instance;
00191     }
00192     const std::type_info& type()
00193     {
00194         return typeid(RealObject);
00195     }
00196 };
00197 
00216 class RegisterObject
00217 {
00218 protected:
00220     ObjectFactory::ClassEntry entry;
00221 public:
00222 
00224     RegisterObject(const std::string& description);
00225 
00227     RegisterObject& addAlias(std::string val);
00228 
00230     RegisterObject& addDescription(std::string val);
00231 
00233     RegisterObject& addAuthor(std::string val);
00234 
00236     RegisterObject& addLicense(std::string val);
00237 
00241     RegisterObject& addCreator(std::string classname, std::string templatename, ObjectFactory::Creator* creator);
00242 
00246     template <class T, class U>
00247     class Conversion
00248     {
00249         typedef char Small;
00250         class Big {char dummy[2];};
00251         static Small Test(U*);
00252         static Big Test(...);
00253         static T* MakeT();
00254     public:
00255         enum { exists = sizeof(Test(MakeT())) == sizeof(Small) };
00256         static int Exists() { return exists; }
00257     };
00258 
00261     template<class RealClass, class BaseClass>
00262     bool implements()
00263     {
00264         bool res = Conversion<RealClass, BaseClass>::exists;
00265         //RealClass* p1=NULL;
00266         //BaseClass* p2=NULL;
00267         //if (res)
00268         //    std::cout << "class "<<RealClass::typeName(p1)<<" implements "<<BaseClass::typeName(p2)<<std::endl;
00269         //else
00270         //    std::cout << "class "<<RealClass::typeName(p1)<<" does not implement "<<BaseClass::typeName(p2)<<std::endl;
00271         return res;
00272     }
00273 
00277     template<class RealObject>
00278     RegisterObject& add(bool defaultTemplate=false)
00279     {
00280         RealObject* p = NULL;
00281         std::string classname = RealObject::className(p);
00282         std::string templatename = RealObject::templateName(p);
00283 
00284         if (defaultTemplate)
00285             entry.defaultTemplate = templatename;
00286 
00287         // This is the only place where we can test which base classes are implemented by this particular object, without having to create any instance
00288         // Unfortunately, we have to enumerate all classes we are interested in...
00289 
00290         if (implements<RealObject,objectmodel::ContextObject>())
00291             entry.baseClasses.insert("ContextObject");
00292         if (implements<RealObject,VisualModel>())
00293             entry.baseClasses.insert("VisualModel");
00294         if (implements<RealObject,BehaviorModel>())
00295             entry.baseClasses.insert("BehaviorModel");
00296         if (implements<RealObject,CollisionModel>())
00297             entry.baseClasses.insert("CollisionModel");
00298         if (implements<RealObject,core::componentmodel::behavior::BaseMechanicalState>())
00299             entry.baseClasses.insert("MechanicalState");
00300         if (implements<RealObject,core::componentmodel::behavior::BaseForceField>())
00301             entry.baseClasses.insert("ForceField");
00302         if (implements<RealObject,core::componentmodel::behavior::InteractionForceField>())
00303             entry.baseClasses.insert("InteractionForceField");
00304         if (implements<RealObject,core::componentmodel::behavior::BaseConstraint>())
00305             entry.baseClasses.insert("Constraint");
00306         if (implements<RealObject,core::BaseMapping>())
00307             entry.baseClasses.insert("Mapping");
00308         if (implements<RealObject,core::componentmodel::behavior::BaseMechanicalMapping>())
00309       entry.baseClasses.insert("MechanicalMapping");
00310     if (implements<RealObject,core::componentmodel::topology::TopologicalMapping>())
00311       entry.baseClasses.insert("TopologicalMapping");
00312         if (implements<RealObject,core::componentmodel::behavior::BaseMass>())
00313             entry.baseClasses.insert("Mass");
00314         if (implements<RealObject,core::componentmodel::behavior::OdeSolver>())
00315       entry.baseClasses.insert("OdeSolver");
00316     if (implements<RealObject,core::componentmodel::behavior::LinearSolver>())
00317       entry.baseClasses.insert("Linear Solver");
00318         if (implements<RealObject,core::componentmodel::behavior::MasterSolver>())
00319             entry.baseClasses.insert("MasterSolver");
00320         if (implements<RealObject,core::componentmodel::topology::Topology>())
00321       entry.baseClasses.insert("Topology");
00322         if (implements<RealObject,core::componentmodel::topology::BaseTopologyObject>())
00323       entry.baseClasses.insert("TopologyObject");
00324     if (implements<RealObject,core::componentmodel::behavior::BaseController>())
00325       entry.baseClasses.insert("Controller");
00326     
00327     
00328     
00329 
00330         return addCreator(classname, templatename, new ObjectCreator<RealObject>);
00331     }
00332 
00334     operator int();
00335 };
00336 
00337 } // namespace core
00338 
00339 } // namespace sofa
00340 
00341 #endif

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