]> Creatis software - bbtk.git/blob - kernel/src/bbtkPackage.h
Feature #1774
[bbtk.git] / kernel / src / bbtkPackage.h
1 /*
2  # ---------------------------------------------------------------------
3  #
4  # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
5  #                        pour la SantÈ)
6  # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7  # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8  # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9  #
10  #  This software is governed by the CeCILL-B license under French law and
11  #  abiding by the rules of distribution of free software. You can  use,
12  #  modify and/ or redistribute the software under the terms of the CeCILL-B
13  #  license as circulated by CEA, CNRS and INRIA at the following URL
14  #  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15  #  or in the file LICENSE.txt.
16  #
17  #  As a counterpart to the access to the source code and  rights to copy,
18  #  modify and redistribute granted by the license, users are provided only
19  #  with a limited warranty  and the software's author,  the holder of the
20  #  economic rights,  and the successive licensors  have only  limited
21  #  liability.
22  #
23  #  The fact that you are presently reading this means that you have had
24  #  knowledge of the CeCILL-B license and that you accept its terms.
25  # ------------------------------------------------------------------------ */
26
27
28 /*=========================================================================
29   Program:   bbtk
30   Module:    $RCSfile: bbtkPackage.h,v $
31   Language:  C++
32   Date:      $Date: 2012/11/16 08:49:01 $
33   Version:   $Revision: 1.18 $
34 =========================================================================*/
35
36
37
38 /**
39  * \file
40  * \brief Class bbtk::Package : registers black boxes descriptors and is able to create instances of the black boxes registered.
41  */
42 /**
43  * \class bbtk::Package
44  * \brief registers black boxes descriptors and is able to create instances of the black boxes registered.
45  */
46
47 #ifndef __bbtkPackage_h__
48 #define __bbtkPackage_h__
49
50 #include "bbtkBlackBox.h"
51 #include "bbtkDynamicLibraryHandling.h"
52
53 namespace bbtk
54 {
55
56   class Factory;
57   BBTK_FORWARD_DECLARE_POINTER(Factory);
58
59   class BBTK_EXPORT Package : public Object
60   {
61     BBTK_OBJECT_INTERFACE(Package);
62     typedef Object Superclass;
63   public:
64     /// Creates a new package
65     static Pointer New(const std::string& name,
66                        const std::string& author,
67                        const std::string& description,
68                        const std::string& version);
69     /// Creates a package from a dynamic library
70     static Pointer CreateFromDynamicLibrary(const std::string& libname,
71                                             const std::string& pkgname,
72                                             const std::string& path);
73
74     /// NOTE : All the static methods below for package destruction
75     /// are not member because they can cause the package death 
76     /// and thus close the dynamic library from which it has been loaded.
77     /// If the dynamic lib which provides a function is closed while 
78     /// in the function: imagine the crash !
79     /// The principal method is Release
80
81     /// UnLoads the package dynamic library 
82     /// (if any and if the package is released)
83     /// If doit == false then does not do it but just 
84     /// put the package in the list of ReleasedDynamicallyLoadedPackages.
85     /// This is because we cannot close the dl from inside a 
86     /// package member method or the program crashes.
87     /// The actual dl close must be done by an external user 
88     /// calling UnLoadReleasedDynamicallyLoadedPackages
89     static void UnLoadDynamicLibrary(Package::WeakPointer p, bool doit = true);
90
91     /// UnLoads released packages that were loaded dynamically
92     /// see UnLoadDynamicLibrary and ReleaseBlackBoxDescriptor
93     static void UnLoadReleasedDynamicallyLoadedPackages();
94
95     /// "Releases" the package
96     /// Signals the package that it can free its descriptors 
97     /// if they are no more used 
98     /// then frees and unloads the package 
99     /// if it is no more used (released)
100     /// Note : Any non-weak pointer on the package must have been freed
101     static void Release(Package::WeakPointer p);
102
103
104     /// Registers the BlackBoxDescriptor in the Package
105     bool Register(BlackBoxDescriptor::Pointer); 
106
107     /// "Releases" a black box descriptor
108     /// Signals the package that it can free the given descriptor
109     /// if it is no more used and frees and put it the the 
110     /// ReleasedDynamicallyLoadedPackages if it is dyn loaded 
111     /// and no more used (released)
112     /// Note : Any non-weak pointer on the package must have been freed
113     static void ReleaseBlackBoxDescriptor(Package::WeakPointer p,
114                                           BlackBoxDescriptor::WeakPointer d);
115     
116     
117     typedef Package::Pointer (*DLGetPackageFunction)();
118     typedef void (*DLDeletePackageFunction)();
119     typedef const std::string& (*DLGetPackageBBTKVersionFunction)();
120
121     /// Opens a dynamic library which contains a bbtk package
122     /// Returns the handler 
123     /// Load the package management symbols from the lib
124     /// returns false if a problem occured hence can be used 
125     /// to test that a dyn lib is a valid bbtk package lib
126     /// NB : The BBTK version exported from the library 
127     ///      is tested against the current bbtk version
128     static DynamicLibraryHandler OpenDynamicLibrary
129     ( const std::string& dynamic_library_path,
130       const std::string& package_name,
131       DLGetPackageFunction&,
132       DLDeletePackageFunction&);
133
134  
135     /// Returns the name of the package
136     const std::string& GetName() const { return mName; }
137
138     /// Returns the author of the package
139     const std::string& GetAuthor() const { return mAuthor; }
140
141     /// Returns the category of the package
142     const std::string& GetCategory() const { return mCategory; }
143
144     /// Returns the description of the package
145     const std::string& GetDescription() const { return mDescription; }
146
147     /// Returns the version of the package
148     const std::string& GetVersion() const { return mVersion; }
149
150     /// Returns true iff the package contains a BlackBoxDescriptor
151     /// with the name provided
152     bool ContainsDescriptor(const std::string& name) const;
153
154     /// Creates a new BlackBox of given type with name name
155     BlackBox::Pointer NewBlackBox(const std::string& type,
156                              const std::string& name) const;
157     
158     /// Creates a new adaptor BlackBox for the given input and output types 
159     /// with name name
160     BlackBox::Pointer NewAdaptor(const DataInfo& typein,
161                                  const DataInfo& typeout,
162                                  const std::string& name) const;
163     
164     /// Creates a new widget adaptor BlackBox 
165     /// for the given input and output types 
166     /// with name name
167     BlackBox::Pointer NewWidgetAdaptor(const DataInfo& typein,
168                                        const DataInfo& typeout,
169                                        const std::string& name) const;
170     bool FindAdaptor(const DataInfo& typein,
171                      const DataInfo& typeout,
172                      std::string& adaptor) const;
173     bool FindWidgetAdaptor(const DataInfo& typein,
174                            const DataInfo& typeout,
175                            std::string& adaptor) const;
176
177
178     /// Displays the list of black box descriptors of the package    
179     void PrintHelpListDescriptors(bool description = false, 
180                               bool adaptors = false) const;
181     /// Displays the list of adaptors of the package
182     void PrintHelpListAdaptors(bool description = false) const;
183     /// Prints help on a particular Descriptor
184     void PrintHelpDescriptor(const std::string& name, bool full=true) const;
185     
186
187
188     void CreateHtmlPage(const std::string& filename,
189                         const std::string& caller = "?",
190                         const std::string& source = "?",
191                         const std::string& custom_header = "",
192                         const std::string& custom_title = "",
193                         int detail = 1, 
194                         int level = 0,
195                         bool relative_link = false ) const;
196
197     void  SetDocURL(std::string url){ mDocURL=url; }
198     const std::string& GetDocURL() const { return mDocURL; }
199     
200     void  SetDocRelativeURL(std::string url){ mDocRelativeURL=url; }
201     const std::string& GetDocRelativeURL() const { return mDocRelativeURL; }
202
203
204     unsigned int GetNumberOfDescriptors() const { return mDescriptorMap.size(); }
205     
206     /// Changes the name of a descriptor
207     void ChangeDescriptorName( const std::string& oldname, 
208                                const std::string& newname );
209     /// The type of map of descriptors
210     typedef std::map< std::string, BlackBoxDescriptor::Pointer> 
211     DescriptorMapType;
212     const DescriptorMapType& GetDescriptorMap() const { return mDescriptorMap; }
213     DescriptorMapType& GetDescriptorMap() { return mDescriptorMap; }
214
215     /// The type of key in the map of adaptor descriptors
216     class AdaptorKey 
217     {
218     public:
219       AdaptorKey( const DataInfo& typein, const DataInfo& typeout, 
220                   BlackBoxDescriptor::Kind kind ) 
221         : mTypeIn(typein), mTypeOut(typeout), mKind(kind) {}
222       
223       bool operator< ( const AdaptorKey& k ) const
224       {
225         return ( ( mKind < k.mKind ) ||
226                  ( ( mKind == k.mKind ) &&
227                    ( ( mTypeIn < k.mTypeIn ) ||
228                      ( ( mTypeIn == k.mTypeIn ) && 
229                        ( mTypeOut < k.mTypeOut ) ) ) ) );
230       }
231       
232       bool operator== ( const AdaptorKey& k ) const
233       {
234         return ( ( mKind == k.mKind ) && 
235                  ( mTypeIn == k.mTypeIn ) && 
236                  ( mTypeOut == k.mTypeOut ) );
237       }
238       DataInfo mTypeIn;
239       DataInfo mTypeOut; 
240       BlackBoxDescriptor::Kind mKind;
241     };
242     
243     /// The type of map of adaptor descriptors
244     typedef std::map< AdaptorKey, BlackBoxDescriptor::WeakPointer> AdaptorMapType;
245
246  
247    const AdaptorMapType& GetAdaptorMap() const { return mAdaptorMap; }
248
249     
250     // Factories management
251     /// Adds the factory to the set of factories which use the package
252     void AddFactory(FactoryPointer f) { mFactorySet.insert(f); }
253     /// Removes the factory from the set of factories which use the package
254     void RemoveFactory(FactoryPointer f) { mFactorySet.erase(f); }
255
256     
257     typedef std::set<FactoryWeakPointer> FactorySet;
258     /// Gets the set of factories which use the package
259     FactorySet& GetFactorySet() { return mFactorySet; }
260     /// Gets the set of factories which use the package (const)
261     const FactorySet& GetFactorySet() const { return mFactorySet; }
262     
263     void Check() const;
264           bool ifBoxExist( std::string boxType );
265
266           
267   private:
268     /// Default ctor is private : use the static New method
269     //    Package() {}
270     /// A Package cannot be copy constructed
271     //    Package(const Package&) {}
272     /// Ctor is private : use the static New method
273     Package(const std::string& name,
274             const std::string& author,
275             const std::string& description,
276             const std::string& version);
277     /// Does unload a package (no test)
278     static void UnLoad(Package::WeakPointer p);
279
280     /// The dynamic library handler of the package if it was loaded from a dl
281     DynamicLibraryHandler mDynamicLibraryHandler;
282     /// The pointer on the delete function of the package 
283     /// in case it was loaded from a dynamic library
284     DLDeletePackageFunction mDLDeletePackageFunction;
285
286
287     /// The name of the package
288     std::string mName;
289     /// The author of the package
290     std::string mAuthor;
291     /// The categories of the package
292     std::string mCategory;    
293     /// The description of the package
294     std::string mDescription;
295     /// The version of the package
296     std::string mVersion;
297     /// URL of the documentation of the Package (absolute path)
298     std::string mDocURL;
299     /// URL of the documentation of the Package 
300     /// (path relative to bbtk doc root)
301     std::string mDocRelativeURL;
302
303     /// The map of black boxes descriptors
304     DescriptorMapType mDescriptorMap;
305
306     /// The map of adaptors descriptors
307     AdaptorMapType mAdaptorMap;
308
309
310     /// The set of factories which contain the package 
311     FactorySet mFactorySet;
312
313     /// The set of released dynamically loaded packages 
314     /// to be unloaded explicitely calling 
315     /// UnLoadReleasedDynamicallyLoadedPackages
316     static std::set<Package::WeakPointer> 
317     mReleasedDynamicallyLoadedPackages;
318   };
319   // EO class Package
320   //====================================================================
321
322
323 //====================================================================
324 #if defined(_WIN32)
325   #define BBTK_PACKAGE_EXPORT __declspec( dllexport )
326 #else
327   #define BBTK_PACKAGE_EXPORT
328 #endif // defined(_WIN32) 
329 //====================================================================
330
331 #define BBTK_GET_PACKAGE_FUNCTION_NAME GetPackage
332 #define BBTK_DEL_PACKAGE_FUNCTION_NAME DeletePackage
333 #define BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME GetPackageBBTKVersion
334   
335
336
337 //====================================================================
338 #define BBTK_DECLARE_PACKAGE(NAME)                                      \
339   extern "C"                                                            \
340   {                                                                     \
341     bbtk::Package::Pointer& NAME ## GetPackagePointer();                \
342     BBTK_PACKAGE_EXPORT                                                 \
343     void BBTK_CDECL NAME ## DeletePackage ();           \
344     BBTK_PACKAGE_EXPORT bbtk::Package::Pointer                          \
345     BBTK_CDECL NAME ## GetPackage ();           \
346     BBTK_PACKAGE_EXPORT const std::string&                              \
347     BBTK_CDECL NAME ## GetPackageBBTKVersion ();        \
348   }
349 //==================================================================== 
350
351 //==================================================================== 
352 #define BBTK_IMPLEMENT_PACKAGE(NAME,AUTHOR,DESCRIPTION,VERSION)         \
353   extern "C"                                                            \
354   {                                                                     \
355     bbtk::Package::Pointer& NAME ## GetPackagePointer()                 \
356     {                                                                   \
357       static bbtk::Package::Pointer u;                                  \
358       return u;                                                         \
359     }                                                                   \
360     BBTK_PACKAGE_EXPORT                                                 \
361     void BBTK_CDECL NAME ## DeletePackage ()                            \
362     {                                                                   \
363       NAME ## GetPackagePointer().reset();                              \
364     }                                                                   \
365     BBTK_PACKAGE_EXPORT                                                 \
366     bbtk::Package::Pointer                                              \
367     BBTK_CDECL NAME ## GetPackage()             \
368     {                                                                   \
369         if (!NAME ## GetPackagePointer())               {                       \
370           NAME ## GetPackagePointer() =                                 \
371               bbtk::Package::New(#NAME,                                 \
372                              AUTHOR,                                    \
373                              DESCRIPTION,                               \
374                              VERSION    \
375                              );                                         \
376            bbtk::Object::InsertInPackageList( NAME ## GetPackagePointer() );  \
377          }                                              \
378       return NAME ## GetPackagePointer();                               \
379     }                                                                   \
380     BBTK_PACKAGE_EXPORT const std::string&                              \
381     BBTK_CDECL NAME ## GetPackageBBTKVersion ()                                                                                 \
382     { static const std::string v(BBTK_STRINGIFY_SYMBOL(BBTK_VERSION));     return v; }  \
383     class NAME ## PackageAutodestructor                                 \
384     {                                                                   \
385     public:                                                             \
386       NAME ## PackageAutodestructor() {}                                \
387       ~NAME ## PackageAutodestructor()                                  \
388       {                                                                 \
389         if (NAME ## GetPackagePointer().use_count()>0)                  \
390           {                                                             \
391             bbtk::Package::WeakPointer p = NAME ## GetPackagePointer(); \
392             bbtk::Package::Release(p);                                  \
393           }                                                             \
394       }                                                                 \
395     };                                                                  \
396     NAME ## PackageAutodestructor NAME ## PackageAutodestructorInstance; \
397   }
398 //====================================================================  
399
400 //====================================================================
401 #define BBTK_ADD_BLACK_BOX_TO_PACKAGE(NAME,CLASS)                       \
402   bool bbDummy##NAME##CLASS = NAME ## GetPackage ()     \
403     ->Register(CLASS ## Descriptor::Instance());
404   //====================================================================
405   
406   //====================================================================
407 #define BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(NAME,CLASS,TEMPLATE_PARAM) \
408   bool bbDummy##NAME##CLASS##TEMPLATE_PARAM = NAME ## GetPackage ()     \
409     ->Register(CLASS ## Descriptor <TEMPLATE_PARAM>::Instance());
410   //====================================================================
411   
412   //====================================================================
413 #define BBTK_ADD_TEMPLATE2_BLACK_BOX_TO_PACKAGE(NAME,CLASS,T1,T2)       \
414   bool bbDummy##NAME##CLASS##T1##T2 = NAME ## GetPackage ()             \
415     ->Register(CLASS ## Descriptor <T1,T2>::Instance()); 
416   //====================================================================
417   
418
419 }// namespace bbtk
420
421
422
423 #endif
424