PlugInRegistration.h

Go to the documentation of this file.
00001 /*
00002  * The information in this file is
00003  * Copyright(c) 2007 Ball Aerospace & Technologies Corporation
00004  * and is subject to the terms and conditions of the
00005  * GNU Lesser General Public License Version 2.1
00006  * The license text is available from   
00007  * http://www.gnu.org/licenses/lgpl.html
00008  */
00009 
00010 #ifndef PLUGINREGISTRATION_H
00011 #define PLUGINREGISTRATION_H
00012 
00013 #include "AppConfig.h"
00014 #include "ConfigurationSettings.h"
00015 #include "External.h"
00016 #include <algorithm>
00017 #include <stdlib.h>
00018 #include <string>
00019 #include <vector>
00020 
00021 class PlugIn;
00022 
00023 #define MOD_ZERO 0
00024 #define MOD_ONE 1
00025 #define MOD_TWO 2
00026 #define MOD_THREE 3
00027 
00028 #if defined(DEPRECATED_MODULE_TYPE)
00029 
00030 #define REGISTER_MODULE_BASIC(name__, moduleNamespace__) \
00031    class YouCannotUseThisMacroWith_DEPRECATED_MODULE_TYPE_defined; \
00032    const int iYouCannotUseThisMacroWith_DEPRECATED_MODULE_TYPE_defined = \
00033       sizeof(YouCannotUseThisMacroWith_DEPRECATED_MODULE_TYPE_defined);
00034 
00035 #define REGISTER_MODULE(name__) REGISTER_MODULE_BASIC(1, 1)
00036 #define REGISTER_NON_CACHED_MODULE REGISTER_MODULE_BASIC(1, 1)
00037 #define REGISTER_DYNAMIC_MODULE(name__, dynamicFactoryClass__) REGISTER_MODULE_BASIC(1, 1)
00038 #define REGISTER_PLUGIN(moduleNamespace__, pluginname__, className__) REGISTER_MODULE_BASIC(1, 1)
00039 #define REGISTER_PLUGIN_BASIC(moduleNamespace__, name__) REGISTER_MODULE_BASIC(1, 1)
00040 #define GENERATE_FACTORY(moduleNamespace__) REGISTER_MODULE_BASIC(1, 1)
00041 #define GENERATE_DYNAMIC_FACTORY(moduleNamespace__, dynamicFactoryClass__) REGISTER_MODULE_BASIC(1, 1)
00042 
00043 #else
00044 
00045 /**
00046  * \cond INTERNAL
00047  * This struct contains information about a version 3 plug-in module.
00048  */
00049 struct OpticksModuleDescriptor
00050 {
00051    unsigned int version;           /**< The version of this descriptor structure. This should be 3. */
00052    const char* pModuleId;          /**< A globally unique ID that identifies this module. this
00053                                         should be guarenteed unique to an instance of the application
00054                                         and it should not change between runs of the application for
00055                                         a specific version of the application. */
00056    const char* pInstantiateSymbol; /**< The name of the function that creates PlugIn objects. */
00057    bool debug;                     /**< True if this module contains debug plug-ins and
00058                                         false if thaey are release plug-ins. Certains systems may
00059                                         refuse to load plug-ins with mismatched debug flags. */
00060    bool cacheable;                  /**< True if the information about this module and it's plug-ins
00061                                          can be cached between application runs. */
00062 };
00063 /// \endcond
00064 
00065 /**
00066  * \cond INTERNAL
00067  * This is the function signature for opticks_get_module_descriptor()
00068  */
00069 typedef struct OpticksModuleDescriptor*(*OpticksGetModuleDescriptorType)(External*);
00070 /// \endcond
00071 
00072 /**
00073  * \cond INTERNAL
00074  * This is the function sugnature for the function which creates plug-in instances.
00075  */
00076 typedef bool(*OpticksInstantiateType)(External*, unsigned int, PlugIn**);
00077 /// \endcond
00078 
00079 #ifdef DEBUG
00080 #define DEBUG_BOOL true
00081 #else
00082 #define DEBUG_BOOL false
00083 #endif
00084 #define REGISTER_MODULE_BASIC(name__, moduleNamespace__, canCache__, modVersion__) \
00085    extern "C" \
00086    { \
00087       struct OpticksModuleDescriptor name__##Descriptor = \
00088       { \
00089          modVersion__, \
00090          #name__, \
00091          #name__ "InstantiatePlugIn", \
00092          DEBUG_BOOL, \
00093          canCache__ \
00094       }; \
00095       LINKAGE struct OpticksModuleDescriptor* opticks_get_module_descriptor(External*) \
00096       { \
00097          return &name__##Descriptor; \
00098       } \
00099       LINKAGE bool name__##InstantiatePlugIn(External* pExternal, unsigned int plugInNumber, PlugIn** pPlugIn) \
00100       { \
00101          ModuleManager::instance()->setService(pExternal); \
00102          *pPlugIn = moduleNamespace__::getPlugIn(plugInNumber); \
00103          return *pPlugIn != NULL; \
00104       } \
00105    }; \
00106    const char* ModuleManager::mspName = NULL; \
00107    const char* ModuleManager::mspVersion = NULL; \
00108    const char* ModuleManager::mspDescription = NULL; \
00109    const char* ModuleManager::mspValidationKey = NULL; \
00110    const char* ModuleManager::mspUniqueId = NULL; \
00111    unsigned int ModuleManager::getTotalPlugIns() { return 0; } \
00112    PlugIn* ModuleManager::getPlugIn(unsigned int) { return NULL; }
00113 
00114 #define REGISTER_NON_CACHED_MODULE(name__) \
00115    GENERATE_FACTORY(name__) \
00116    REGISTER_MODULE_BASIC(name__, name__, false, MOD_THREE)
00117 
00118 #define REGISTER_MODULE(name__) \
00119    GENERATE_FACTORY(name__) \
00120    REGISTER_MODULE_BASIC(name__, name__, true, MOD_THREE)
00121 
00122 #define REGISTER_DYNAMIC_MODULE(name__, dynamicFactoryClass__) \
00123    GENERATE_DYNAMIC_FACTORY(name__, dynamicFactoryClass__) \
00124    REGISTER_MODULE_BASIC(name__, name__, false, MOD_THREE) 
00125 
00126 #define REGISTER_V2_MODULE(name__) \
00127    GENERATE_FACTORY(name__) \
00128    REGISTER_MODULE_BASIC(name__, name__, true, MOD_TWO)
00129 
00130 #define REGISTER_V2_DYNAMIC_MODULE(name__, dynamicFactoryClass__) \
00131    GENERATE_DYNAMIC_FACTORY(name__, dynamicFactoryClass__) \
00132    REGISTER_MODULE_BASIC(name__, name__, false, MOD_TWO) 
00133 
00134 class PlugIn;
00135 class PlugInFactory;
00136 
00137 /**
00138  * \cond INTERNAL
00139  * Automatically registers plug-ins in a module using convenient macros.
00140  *
00141  * Using this class requires ModuleManager.cpp to be configured for PlugInFactory use.
00142  * The sample ModuleManager.cpp contained in the Opticks SDK shows how to configure
00143  * ModuleManager.cpp for use with PlugInFactory. Direct use of this class is not needed.
00144  * @see REGISTER_PLUGIN(), REGISTER_PLUGIN_BASIC()
00145  */
00146 class PlugInFactory
00147 {
00148 public:
00149    /**
00150     * Construct a new factory for a given name adding it to the factory list for this module.
00151     *
00152     * @param name
00153     *        The name of the object created by this factory.
00154     */
00155    PlugInFactory() {}
00156 
00157    virtual ~PlugInFactory() {}
00158 
00159    /**
00160     * Create a new plugin.
00161     *
00162     * @return The PlugIn object
00163     */
00164    virtual PlugIn* createPlugIn(const std::string& name) = 0;
00165 
00166    virtual std::vector<std::string> getPlugInNames() = 0;
00167 };
00168 /// \endcond
00169 
00170 /**
00171  * \cond INTERNAL
00172  * Automatically registers plug-ins in a module using convenient macros.
00173  *
00174  * Using this class requires ModuleManager.cpp to be configured for PlugInFactory use.
00175  * The sample ModuleManager.cpp contained in the Opticks SDK shows how to configure
00176  * ModuleManager.cpp for use with PlugInFactory. Direct use of this class is not needed.
00177  * @see REGISTER_PLUGIN(), REGISTER_PLUGIN_BASIC()
00178  */
00179 class BasicPlugInFactory : public PlugInFactory
00180 {
00181 public:
00182    /**
00183     * Construct a new factory for a given name adding it to the factory list for this module.
00184     *
00185     * @param name
00186     *        The name of the object created by this factory.
00187     */
00188    BasicPlugInFactory(const std::string& name) : PlugInFactory()
00189    {
00190       addPlugInName(name);
00191    }
00192    virtual ~BasicPlugInFactory() {}
00193    virtual std::vector<std::string> getPlugInNames()
00194    {
00195       return mPlugInNames;
00196    }
00197 
00198 private:
00199    BasicPlugInFactory() {}
00200 
00201    void addPlugInName(std::string name)
00202    {
00203       mPlugInNames.push_back(name);
00204    }
00205 
00206    std::vector<std::string> mPlugInNames;
00207 };
00208 /// \endcond
00209 
00210 /**
00211  * This class is used to perform dynamic plug-in registration.
00212  * 
00213  * To perform dynamic plug-in registration, a subclass of this
00214  * class must be created that performs the actual dynamic plug-in
00215  * registration.  The subclass must then be provided as the
00216  * second argument to the REGISTER_DYNAMIC_MODULE() macro.
00217  * Please read \ref advanced_plugin_register for more details.
00218  */
00219 class DynamicPlugInFactory : public PlugInFactory
00220 {
00221 public:
00222    /**
00223     * Constructor.
00224     *
00225     * @warning Subclasses should NOT perform any logic
00226     *          in their constructors.
00227     */
00228    DynamicPlugInFactory() {}
00229    virtual ~DynamicPlugInFactory() {};
00230 
00231    /// \cond INTERNAL
00232    void setModuleId(const std::string& moduleId)
00233    {
00234       mModuleId = moduleId;
00235    }
00236    /// \endcond
00237 
00238    /**
00239     * Subclasses should perform any dynamic plug-in lookup
00240     * in this function.  This function will be called once
00241     * per application run, with a \c true value passed for the
00242     * \c locate parameter.  It is during this invocation, that
00243     * this function should \c locate all dynamic plug-ins and insert
00244     * unique string identifiers for each plug-in into
00245     * the \c dynamicPlugIns vector.
00246     * Every other time this function is invoked, the \c locate
00247     * parameter will be passed a value of \c false.  When this is done
00248     * the previously located identifiers (those found when
00249     * this function was called with a value of \c true for \c locate)
00250     * will be provided to the \c dynamicPlugIns argument.  The purpose
00251     * of performing the additional calls to init() with \c locate having
00252     * a value of \c false, is to allow the class instance to re-initialize
00253     * any member state that might be necessary to implement the createPlugIn()
00254     * function.
00255     *
00256     * \note %Any time this function is invoked, all the 
00257     * %Opticks services will be constructed and valid.  For example,
00258     * this function's implementation can use Service<ConfigurationSettings>().
00259     *
00260     * @param locate
00261     *        When \c true, this function should perform dynamic plug-in
00262     *        lookup and populate \c dynamicPlugIns with unique string
00263     *        identifiers for each plug-in. When \c false, this class
00264     *        can re-initialize any member state required for createPlugIn()
00265     *        to work properly.  When \c false, the \c dynamicPlugIns argument
00266     *        will be pre-populated with the string identifiers located when
00267     *        function was called with this paramter having a value of \c true.
00268     * @param dynamicPlugIns
00269     *        The list of unique string identifiers for the dynamically
00270     *        located plug-ins.  When the \c locate parameter is \c true, this list
00271     *        should be populated.  When the \c locate parameter is \c false, this
00272     *        list will be pre-populated with the earlier values.  When the
00273     *        \c locate paramter is \c false, any changes to this vector will be
00274     *        ignored by the invoking class.  The string identifiers populated
00275     *        into this list, will be used when invoking createPlugIn().
00276     *
00277     * @see \ref advanced_plugin_register
00278     */
00279    virtual void init(bool locate, std::vector<std::string>& dynamicPlugIns) = 0;
00280 
00281    /**
00282     * Construct the given PlugIn instance.
00283     * 
00284     * @param name
00285     *        Construct the PlugIn instance associated with the
00286     *        unique string identifier.  The string identifiers
00287     *        provided will be those returned from the init() function.
00288     *
00289     * @return The PlugIn instance associated with the given string
00290     *         identifier.  If the data required to construct the
00291     *         dynamic plug-in is no longer available, please return \c NULL.
00292     */
00293    virtual PlugIn* createPlugIn(const std::string& name) = 0;
00294 
00295    /// \cond INTERNAL
00296    std::vector<std::string> getPlugInNames()
00297    {
00298       Service<ConfigurationSettings> pSettings;
00299       std::string plugInsKey = "_" + mModuleId + "DynamicPlugInNames_";
00300       std::vector<std::string> names;
00301       if (pSettings->isTemporarySetting(plugInsKey))
00302       {
00303          const std::vector<std::string>* pNames = NULL;
00304          pNames = dv_cast<std::vector<std::string> >(&pSettings->getSetting(plugInsKey));
00305          if (pNames != NULL)
00306          {
00307             names = *pNames;
00308          }
00309          std::vector<std::string> tempCopy = names;
00310          init(false, tempCopy);
00311       }
00312       else
00313       {
00314          init(true, names);
00315          pSettings->setTemporarySetting(plugInsKey, names);
00316       }
00317       return names;
00318    }
00319    /// \endcond
00320 protected:
00321    /// \cond INTERNAL
00322    std::string mModuleId;
00323    /// \endcond
00324 };
00325 
00326 /**
00327  * \cond INTERNAL
00328  * Used to sort plug-in factories.
00329  */
00330 struct FactoryPtrComparator
00331 {
00332    bool operator()(std::pair<std::string, PlugInFactory*> pLhs, std::pair<std::string, PlugInFactory*> pRhs)
00333    {
00334       if (pLhs.second == NULL || pRhs.second == NULL)
00335       {
00336          return false;
00337       }
00338       size_t leftCount = std::count(pLhs.first.begin(), pLhs.first.end(), '_');
00339       size_t rightCount = std::count(pRhs.first.begin(), pRhs.first.end(), '_');
00340       if (leftCount != rightCount)
00341       {
00342          return leftCount > rightCount;
00343       }
00344       return pLhs.first < pRhs.first;
00345    }
00346 };
00347 /// \endcond
00348 
00349 
00350 #define REGISTER_PLUGIN(moduleNamespace__, pluginname__, className__) \
00351    namespace moduleNamespace__ \
00352    { \
00353       void addFactory(PlugInFactory*); \
00354       class pluginname__##PlugInFactory : public BasicPlugInFactory \
00355       { \
00356       public: \
00357          pluginname__##PlugInFactory(const std::string& name) : BasicPlugInFactory(name) \
00358          { \
00359             moduleNamespace__::addFactory(this); \
00360          } \
00361          virtual ~pluginname__##PlugInFactory() {}; \
00362          PlugIn* createPlugIn(const std::string& name) \
00363          { \
00364             return new className__; \
00365          } \
00366       }; \
00367       static pluginname__##PlugInFactory pluginname__##pluginFactory(#pluginname__); \
00368    }
00369 
00370 #define REGISTER_PLUGIN_BASIC(moduleNamespace__, name__) REGISTER_PLUGIN(moduleNamespace__, name__, name__)
00371 
00372 #define GENERATE_FACTORY(moduleNamespace__) \
00373    namespace moduleNamespace__ { \
00374    std::vector<std::pair<std::string, PlugInFactory*> >& factories() \
00375    { \
00376       static std::vector<std::pair<std::string, PlugInFactory*> > sFactories; \
00377       return sFactories; \
00378    } \
00379    void addFactory(PlugInFactory* pFactory) \
00380    { \
00381       if (pFactory != NULL) \
00382       { \
00383          std::vector<std::string> names = pFactory->getPlugInNames(); \
00384          for (std::vector<std::string>::iterator nameIter = names.begin(); nameIter != names.end(); ++nameIter) \
00385          { \
00386             factories().push_back(make_pair(*nameIter, pFactory)); \
00387          } \
00388       } \
00389    } \
00390    PlugIn* getPlugIn(unsigned int plugInNumber) \
00391    { \
00392       static bool factoriesSorted = false; \
00393       if (!factoriesSorted) \
00394       { \
00395          factoriesSorted = true; \
00396          FactoryPtrComparator comp; \
00397          std::sort(factories().begin(), factories().end(), comp); \
00398       } \
00399       if (plugInNumber >= factories().size()) \
00400       { \
00401          return NULL; \
00402       } \
00403       const std::pair<std::string, PlugInFactory*>& plugin = factories()[plugInNumber]; \
00404       return plugin.second->createPlugIn(plugin.first); \
00405    } \
00406    }
00407 
00408 #define GENERATE_DYNAMIC_FACTORY(moduleNamespace__, dynamicFactoryClass__) \
00409    namespace moduleNamespace__ { \
00410    static dynamicFactoryClass__ sDynamicFactoryInstance__; \
00411    std::vector<std::pair<std::string, PlugInFactory*> >& factories() \
00412    { \
00413       static std::vector<std::pair<std::string, PlugInFactory*> > sFactories; \
00414       return sFactories; \
00415    } \
00416    void addFactory(PlugInFactory* pFactory) \
00417    { \
00418       if (pFactory != NULL) \
00419       { \
00420          std::vector<std::string> names = pFactory->getPlugInNames(); \
00421          for (std::vector<std::string>::iterator nameIter = names.begin(); nameIter != names.end(); ++nameIter) \
00422          { \
00423             factories().push_back(make_pair(*nameIter, pFactory)); \
00424          } \
00425       } \
00426    } \
00427    PlugIn* getPlugIn(unsigned int plugInNumber) \
00428    { \
00429       static bool factoriesSorted = false; \
00430       if (!factoriesSorted) \
00431       { \
00432          factoriesSorted = true; \
00433          DynamicPlugInFactory* pFac = &sDynamicFactoryInstance__; \
00434          addFactory(pFac); \
00435          FactoryPtrComparator comp; \
00436          std::sort(factories().begin(), factories().end(), comp); \
00437       } \
00438       if (plugInNumber >= factories().size()) \
00439       { \
00440          return NULL; \
00441       } \
00442       const std::pair<std::string, PlugInFactory*>& plugin = factories()[plugInNumber]; \
00443       return plugin.second->createPlugIn(plugin.first); \
00444    } \
00445    }
00446 
00447 #endif
00448 
00449 /**
00450  *  \cond INTERNAL
00451  *  Plug-in management within a module
00452  *
00453  *  The module manager is used to inform the main application about the
00454  *  plug-ins within the module.  It is also used to create, destroy, and 
00455  *  provide access to the plug-ins.  Plug-in developers edit this class to 
00456  *  build a plug-in module composed of their plug-ins. This is a singleton 
00457  *  class, where only one instance of this class exists at a given time.  Use 
00458  *  the instance() method to get a reference to the class.
00459  */
00460 class ModuleManager
00461 {
00462 protected:
00463    /**
00464     *  Constructor which can NOT be called outside this class.
00465     *
00466     *  The default constructor is protected to control the number of
00467     *  instances of this class.  Use the instance() method to obtain
00468     *  access to the class.
00469     */
00470    ModuleManager();
00471 
00472    /**
00473     *  Destructor which can not be invoked outside this class.
00474     *
00475     *  This destructor deletes all dynamic memory associated with the
00476     *  class.
00477     */
00478    ~ModuleManager();
00479 
00480 public:
00481    /**
00482     *  Returns the instance of this singleton class.
00483     *
00484     *  This method controls the instantiation of this class and
00485     *  returns a reference to the singleton instance.  If the class
00486     *  has not been instantiated, it creates the instance, stores
00487     *  it internally, and then returns a reference to the new 
00488     *  reference.
00489     *
00490     *  @return  This method returns the singleton class instance.
00491     */
00492    static ModuleManager* instance();
00493 
00494    /**
00495     *  Gets the name of the module.
00496     *
00497     *  This method is used to get the name of the module.
00498     *
00499     *  @return  This method returns the string name of the module.
00500     */
00501    static char *getName()
00502    {
00503       return (char*)mspName;
00504    }
00505 
00506    /**
00507     *  Gets the version of the module.
00508     *
00509     *  This method is used to get the version of the module.  The
00510     *  version is a string in the following format: "1.2.3".
00511     *
00512     *  @return  This method returns the string version of the module.
00513     */
00514    static char *getVersion()
00515    {
00516       return (char*)mspVersion;
00517    }
00518 
00519    /**
00520     *  Gets the description of the module.
00521     *
00522     *  This method is used to get a string describing the purpose
00523     *  and operation of the module.
00524     *
00525     *  @return  A string containing the description of the module.
00526     */
00527    static char *getDescription()
00528    {
00529       return (char*)mspDescription;
00530    }
00531 
00532    /**
00533     *  Returns the number of plug-ins within the module.
00534     *
00535     *  This method may be implemented to allow for a dynamic number
00536     *  of plug-ins.  This may be useful for a plug-in suite which can
00537     *  be configured based on data files present.  Each time this method
00538     *  is called, it may return a different number.
00539     *
00540     *  @return  The number of plug-ins within the module.
00541     */
00542    static unsigned int getTotalPlugIns();
00543 
00544    static char *getValidationKey()
00545    {
00546       return (char*)mspValidationKey;
00547    }
00548 
00549    /**
00550     *  Sets the reference to the main application External services.
00551     *
00552     *  This method sets the reference to the services class provided
00553     *  by the main application.  The services class can be used to
00554     *  query the main application for services that it provides and
00555     *  get access to those services.
00556     *
00557     *  @param   address
00558     *           The External services class to set.
00559     */
00560    void setService( External* address )
00561    {
00562       mpServices = address;
00563    }
00564 
00565    /**
00566     *  Gets the reference to the main application External services.
00567     *
00568     *  This method gets the reference to the services class provided
00569     *  by the main application.  The services class can be used to
00570     *  query the main application for services that it provides and
00571     *  get access to those services.
00572     *
00573     *  @return  Returns a reference to the main application External
00574     *           services.
00575     *
00576     *  @see     External
00577     */
00578    External* getService()
00579    {
00580       return mpServices;
00581    }
00582 
00583    /** 
00584     *  Creates an instance of a plug-in.
00585     *
00586     *  This method is used to create an instance of a Plug-In.  PLUG-IN
00587     *  DEVELOPERS SHOULD EDIT THIS CLASS TO ADD INSTANCE CREATION FOR THEIR
00588     *  PLUG-IN.
00589     *
00590     *  Plug-in developers are responsible for ensuring a consistent ordering
00591     *  to plug-ins for each time the module is queried for its plug-in count.
00592     *  If this module has dynamically defined plug-ins, the mapping of plug-in
00593     *  number to plug-in must remain constant until getTotalPlugIns() is called
00594     *
00595     *  @param   plugInNumber
00596     *           The plug-in to create within the module.  The number of the
00597     *           first plug-in in the module is zero.
00598     *
00599     *  @return  This method returns a pointer to the new plug-in.
00600     *
00601     */
00602    PlugIn* getPlugIn( unsigned int plugInNumber );
00603 
00604    /**
00605     *  Returns the UUID for the module.
00606     *
00607     *  This method returns a unique id for the module. This value must be the
00608     *  same between instances of the application. It should be formatted as a
00609     *  UUID.
00610     *
00611     *  @return This method returns a module's unique id.
00612     */
00613    static char *getUniqueId()
00614    {
00615       return const_cast<char*>(mspUniqueId);
00616    }
00617 
00618 private:
00619    static const char*    mspName;
00620    static const char*    mspVersion;
00621    static const char*    mspDescription;
00622    static const char*    mspValidationKey;
00623    static const char*    mspUniqueId;
00624 
00625    External*             mpServices;
00626 
00627    static ModuleManager* mspSingleton;
00628 };
00629 /// \endcond
00630 
00631 #endif

Software Development Kit - Opticks 4.9.0 Build 16218