1 #ifndef CORELIB___PLUGIN_MANAGER__IMPL__HPP
2 #define CORELIB___PLUGIN_MANAGER__IMPL__HPP
3 
4 /* $Id: plugin_manager_impl.hpp 546046 2017-09-13 14:32:40Z sadyrovr $
5  * ===========================================================================
6  *
7  *                            PUBLIC DOMAIN NOTICE
8  *               National Center for Biotechnology Information
9  *
10  *  This software/database is a "United States Government Work" under the
11  *  terms of the United States Copyright Act.  It was written as part of
12  *  the author's official duties as a United States Government employee and
13  *  thus cannot be copyrighted.  This software/database is freely available
14  *  to the public for use. The National Library of Medicine and the U.S.
15  *  Government have not placed any restriction on its use or reproduction.
16  *
17  *  Although all reasonable efforts have been taken to ensure the accuracy
18  *  and reliability of the software and data, the NLM and the U.S.
19  *  Government do not and cannot warrant the performance or results that
20  *  may be obtained by using this software or data. The NLM and the U.S.
21  *  Government disclaim all warranties, express or implied, including
22  *  warranties of performance, merchantability or fitness for any particular
23  *  purpose.
24  *
25  *  Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Author:  Anatoliy Kuznetsov
30  *
31  * File Description:  Collection of classes to implement different
32  *                    plugin manager paradigms.
33  *
34  *
35  */
36 
37 /// @file plugin_manager_impl.hpp
38 /// Helper classes and templates to implement plugins.
39 
40 #include <corelib/plugin_manager.hpp>
41 
42 
43 BEGIN_NCBI_SCOPE
44 
45 /** @addtogroup PluginMgr
46  *
47  * @{
48  */
49 
50 
51 /// Template class helps to implement one driver class factory.
52 ///
53 /// Class supports one driver, one version class factory
54 /// (the very basic one)
55 /// Template parameters are:
56 ///   IFace - interface class
57 ///   TDriver - driver class (implements IFace)
58 
59 template <class IFace, class TDriver>
60 class CSimpleClassFactoryImpl : public IClassFactory<IFace>
61 {
62 public:
63 
64     typedef TDriver                        TImplementation;
65     typedef IFace                          TInterface;
66     typedef IClassFactory<IFace>           TParent;
67     typedef typename TParent::SDriverInfo  TDriverInfo;
68     typedef typename TParent::TDriverList  TDriverList;
69 
70     /// Construction
71     ///
72     /// @param driver_name
73     ///   Driver name string
74     /// @param patch_level
75     ///   Patch level implemented by the driver.
76     ///   By default corresponds to interface patch level.
CSimpleClassFactoryImpl(const string & driver_name,int patch_level=-1)77     CSimpleClassFactoryImpl(const string& driver_name, int patch_level = -1)
78         : m_DriverVersionInfo
79         (TParent::GetDefaultDrvVers().GetMajor(),
80          TParent::GetDefaultDrvVers().GetMinor(),
81          patch_level >= 0 ?
82             patch_level : TParent::GetDefaultDrvVers().GetPatchLevel()),
83           m_DriverName(driver_name)
84     {
85         _ASSERT(!m_DriverName.empty());
86     }
87 
88     /// Create instance of TDriver
89     virtual TInterface*
CreateInstance(const string & driver=kEmptyStr,CVersionInfo version=TParent::GetDefaultDrvVers (),const TPluginManagerParamTree * =0) const90     CreateInstance(const string& driver  = kEmptyStr,
91                    CVersionInfo version = TParent::GetDefaultDrvVers(),
92                    const TPluginManagerParamTree* /*params*/ = 0) const
93     {
94         TDriver* drv = 0;
95         if (driver.empty() || driver == m_DriverName) {
96             if (version.Match(NCBI_INTERFACE_VERSION(IFace))
97                                 != CVersionInfo::eNonCompatible) {
98                 drv = new TImplementation();
99             }
100         }
101         return drv;
102     }
103 
GetDriverVersions(TDriverList & info_list) const104     void GetDriverVersions(TDriverList& info_list) const
105     {
106         info_list.push_back(TDriverInfo(m_DriverName, m_DriverVersionInfo));
107     }
108 
109 protected:
110     /// Utility function to get an element of parameter tree
111     /// Throws an exception when mandatory parameter is missing
112     /// (or returns the deafult value)
GetParam(const TPluginManagerParamTree * params,const string & param_name,bool mandatory,const string & default_value) const113     string GetParam(const TPluginManagerParamTree* params,
114                     const string&                  param_name,
115                     bool                           mandatory,
116                     const string&                  default_value) const
117     {
118         return
119             TParent::GetParam(m_DriverName,
120                               params, param_name, mandatory, default_value);
121     }
122 
123     /// This version always defaults to the empty string so that it
124     /// can safely return a reference.  (default_value may be
125     /// temporary in some cases.)
GetParam(const TPluginManagerParamTree * params,const string & param_name,bool mandatory) const126     const string& GetParam(const TPluginManagerParamTree* params,
127                            const string&                  param_name,
128                            bool                           mandatory) const
129     {
130         return
131             TParent::GetParam(m_DriverName, params, param_name, mandatory);
132     }
133 
134     /// Utility function to get an integer of parameter tree
135     /// Throws an exception when mandatory parameter is missing
136     /// (or returns the deafult value)
GetParamInt(const TPluginManagerParamTree * params,const string & param_name,bool,int default_value) const137     int GetParamInt(const TPluginManagerParamTree* params,
138                     const string&                  param_name,
139                     bool                           /* mandatory */,
140                     int                            default_value) const
141     {
142         CConfig conf(params);
143         return conf.GetInt(m_DriverName,
144                            param_name,
145                            CConfig::eErr_NoThrow,
146                            default_value);
147     }
148 
149     /// Utility function to get an integer of parameter tree
150     /// Throws an exception when mandatory parameter is missing
151     /// (or returns the deafult value)
152     Uint8
GetParamDataSize(const TPluginManagerParamTree * params,const string & param_name,bool,unsigned int default_value) const153     GetParamDataSize(const TPluginManagerParamTree* params,
154                      const string&                  param_name,
155                      bool                           /* mandatory */,
156                      unsigned int                   default_value) const
157     {
158         CConfig conf(params);
159         return conf.GetDataSize(m_DriverName,
160                                 param_name,
161                                 CConfig::eErr_NoThrow,
162                                 default_value);
163     }
164 
165 
166     /// Utility function to get an bool of parameter tree
167     /// Throws an exception when mandatory parameter is missing
168     /// (or returns the deafult value)
GetParamBool(const TPluginManagerParamTree * params,const string & param_name,bool,bool default_value) const169     bool GetParamBool(const TPluginManagerParamTree* params,
170                       const string&                  param_name,
171                       bool                           /* mandatory */,
172                       bool                           default_value) const
173     {
174         CConfig conf(params);
175         return conf.GetBool(m_DriverName,
176                             param_name,
177                             CConfig::eErr_NoThrow,
178                             default_value);
179 
180     }
181 
182 
183     /// Utility function to get a double of parameter tree
184     /// Throws an exception when mandatory parameter is missing
185     /// (or returns the default value)
GetParamDouble(const TPluginManagerParamTree * params,const string & param_name,bool,double default_value) const186     double GetParamDouble(const TPluginManagerParamTree* params,
187                           const string&                  param_name,
188                           bool                           /* mandatory */,
189                           double                         default_value) const
190     {
191         CConfig conf(params);
192         return conf.GetDouble(m_DriverName,
193                               param_name,
194                               CConfig::eErr_NoThrow,
195                               default_value);
196 
197     }
198 
199 
200 protected:
201     CVersionInfo  m_DriverVersionInfo;
202     string        m_DriverName;
203 };
204 
205 
206 /// Template implements entry point
207 ///
208 /// The actual entry point is a C callable exported function
209 ///   delegates the functionality to
210 ///               CHostEntryPointImpl<>::NCBI_EntryPointImpl()
211 
212 template<class TClassFactory>
213 struct CHostEntryPointImpl
214 {
215     typedef typename TClassFactory::TInterface                TInterface;
216     typedef CPluginManager<TInterface>                        TPluginManager;
217     typedef typename CPluginManager<TInterface>::SDriverInfo  TDriverInfo;
218 
219     typedef typename
220     CPluginManager<TInterface>::TDriverInfoList         TDriverInfoList;
221     typedef typename
222     CPluginManager<TInterface>::EEntryPointRequest      EEntryPointRequest;
223     typedef typename TClassFactory::SDriverInfo         TCFDriverInfo;
224 
225 
226     /// Entry point implementation.
227     ///
228     /// @sa CPluginManager::FNCBI_EntryPoint
NCBI_EntryPointImplCHostEntryPointImpl229     static void NCBI_EntryPointImpl(TDriverInfoList& info_list,
230                                     EEntryPointRequest method)
231     {
232         TClassFactory cf;
233         list<TCFDriverInfo> cf_info_list;
234         cf.GetDriverVersions(cf_info_list);
235 
236         switch (method)
237             {
238             case TPluginManager::eGetFactoryInfo:
239                 {
240                     typename list<TCFDriverInfo>::const_iterator it =
241                         cf_info_list.begin();
242                     typename list<TCFDriverInfo>::const_iterator it_end =
243                         cf_info_list.end();
244 
245                     for (; it != it_end; ++it) {
246                         info_list.push_back(TDriverInfo(it->name, it->version));
247                     }
248 
249                 }
250             break;
251             case TPluginManager::eInstantiateFactory:
252                 {
253                     typename TDriverInfoList::iterator it1 = info_list.begin();
254                     typename TDriverInfoList::iterator it1_end = info_list.end();
255                     for(; it1 != it1_end; ++it1) {
256                         // We do only an exact match here.
257                         // A factory cannot be matched twice.
258                         _ASSERT( it1->factory == NULL );
259 
260                         typename list<TCFDriverInfo>::iterator it2 =
261                             cf_info_list.begin();
262                         typename list<TCFDriverInfo>::iterator it2_end =
263                             cf_info_list.end();
264 
265                         for (; it2 != it2_end; ++it2) {
266                             if (it1->name == it2->name) {
267                                 // We do only an exact match here.
268                                 if (it1->version.Match(it2->version) ==
269                                     CVersionInfo::eFullyCompatible)
270                                     {
271                                         _ASSERT( it1->factory == NULL );
272 
273                                         TClassFactory* cg = new TClassFactory();
274                                         IClassFactory<TInterface>* icf = cg;
275                                         it1->factory = icf;
276                                     }
277                             }
278                         } // for
279 
280                     } // for
281 
282                 }
283             break;
284             default:
285                 _ASSERT(0);
286             } // switch
287     }
288 
289 };
290 
291 
292 /* @} */
293 
294 END_NCBI_SCOPE
295 
296 #endif  /* CORELIB___PLUGIN_MANAGER__IMPL_HPP */
297