]> Creatis software - bbtk.git/blob - kernel/src/bbtkPackage.cxx
*** empty log message ***
[bbtk.git] / kernel / src / bbtkPackage.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkPackage.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/04/22 08:29:09 $
7   Version:   $Revision: 1.15 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See doc/license.txt or
11   http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 /**
19  *\file
20  *\brief Class bbtk::Package : registers black boxes descriptors and is able to create instances of the black boxes registered.
21  */
22 #include "bbtkPackage.h"
23 #include "bbtkMessageManager.h"
24 #include "bbtkConfigurationFile.h"
25 #include <fstream>
26 #include <time.h>
27 #include "bbtkUtilities.h"
28
29 namespace bbtk
30 {
31   
32
33
34   //==========================================================================
35   /// Creates a new package
36   Package::Pointer Package::New(const std::string& name,
37                                 const std::string& author,
38                                 const std::string& description,
39                                 const std::string& version,
40                                 const std::string& BBTKVersion) 
41   {
42     bbtkDebugMessage("object",1,"##> Package::New('"<<name<<"',...)"
43                      <<bbtkendl);
44     Package::Pointer p = MakePointer(new Package(name,
45                                                author,
46                                                description,
47                                                version,
48                                                BBTKVersion));
49     bbtkDebugMessage("object",2,"<## Package::New('"<<name<<"',...)"
50                      <<bbtkendl);
51     return p;
52   }
53   //==========================================================================
54
55   //==========================================================================
56   /// Ctor with the name of the package
57   Package::Package(const std::string& name,
58                    const std::string& author,
59                    const std::string& description,
60                    const std::string& version,
61                    const std::string& BBTKVersion) 
62     :
63     mDynamicLibraryHandler(0),
64     mName(name),
65     mAuthor(author),
66     mDescription(description),
67     mVersion(version)
68   {
69     bbtkDebugMessage("object",2,"==> Package::Package('"<<name<<"',...)"
70                      <<bbtkendl);
71     std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
72     char c = default_doc_dir.c_str()[strlen(default_doc_dir.c_str())-1];
73     std::string url = default_doc_dir; 
74     if (c != '/' && c !='\\') url = url + "/";
75     url = url +  "temp_dir/" + name + "/index.html";    
76     
77     SetDocURL(url);
78     SetDocRelativeURL("Relative url not set");
79
80     /*
81     std::string relurl(BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH));
82     relurl += "/packages/"+name+"/bbdoc/index.html";
83     std::string url = ConfigurationFile::GetInstance().Get_url()
84       + relurl; 
85     SetDocURL(url);
86     SetDocRelativeURL(relurl);   
87     */
88
89     //    std::cout  << "   url=["<<url<<"]"<<std::endl;
90     //    std::cout  << "relurl=["<<relurl<<"]"<<std::endl;
91     bbtkDebugMessage("object",2,"<== Package::Package('"<<name<<"',...) OK"
92                      <<bbtkendl);
93
94   }
95   //==========================================================================
96
97
98
99   //==========================================================================
100   /// Dtor
101   Package::~Package()
102   {
103     bbtkDebugMessage("object",2,"==> Package::~Package(\""<<mName<<"\")"<<bbtkendl);
104     bbtkDebugMessage("object",2,"<== Package::~Package(\""<<mName<<"\")"<<bbtkendl);
105   }
106   //==========================================================================
107
108
109   //==========================================================================
110   void PackageReleaseBlackBoxDescriptorInternal(Package::WeakPointer pack,
111                                                 const std::string& descname)
112   {
113     // Try to release descriptor
114     bbtkDebugMessage("package",3,"--- Trying to release descriptor '"
115                      <<descname<<"'"<<bbtkendl);
116     std::string packname = pack.lock()->GetName();
117
118     Package::BlackBoxMapType::iterator desc = 
119       pack.lock()->GetBlackBoxMap().find(descname);
120     if (desc ==  pack.lock()->GetBlackBoxMap().end())
121       {
122         bbtkDebugMessage("package",3,
123                          "    Descriptor has already been released"
124                          <<bbtkendl);
125         return;
126       }
127     //    bbtkDebugMessage("package",3,
128     //               "    Trying unreferencing it ... "<<std::endl);
129     BlackBoxDescriptor::WeakPointer pdesc = desc->second;
130     desc->second.reset();
131     // if it is dead : remove it 
132     if (pdesc.expired()) 
133       {
134         bbtkDebugMessage("package",2,"   '"<<packname<<"::"<<descname<<"' Descriptor expired"<<bbtkendl);
135         if (pack.expired()) 
136           {
137             bbtkDebugMessage("package",2,
138                              "    ... and caused its package death"
139                              <<bbtkendl);
140             return;
141           }
142         desc = pack.lock()->GetBlackBoxMap().find(descname);
143         if (desc !=  pack.lock()->GetBlackBoxMap().end())
144           pack.lock()->GetBlackBoxMap().erase(desc);
145       }
146     else 
147       {
148         bbtkDebugMessage("package",3,"    ... Descriptor still alive ("
149                          <<pdesc.use_count()<<" refs)"
150                          <<bbtkendl);
151         pack.lock()->GetBlackBoxMap()[descname] = pdesc.lock();
152       }
153   }
154   //==========================================================================
155
156
157   //==========================================================================
158   /// Release
159   void Package::Release(Package::WeakPointer pack)
160   {
161     std::string packname = pack.lock()->mName;
162     bbtkDebugMessage("package",1,"==> Package::Release('"<<
163                      packname<<"')"<<bbtkendl);
164
165     long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0; 
166     long ndesc = pack.lock()->GetBlackBoxMap().size();
167     long nrefs = pack.use_count();
168
169     bbtkDebugMessage("package",2," "<<nrefs<<" refs / "
170                      <<ndesc<<" descr / dyn="
171                      <<dyn<<std::endl);
172
173     // A package is "free" from any external reference iff :
174     // i) It is not dynamically loaded and nrefs == ndesc 
175     // (each desc references its package) or
176     // ii) It is dynamically loaded and nrefs == ndesc + 1
177     // (A dynamic library holds a static pointer on the package it contains
178     //  which is allocated when the PACKAGENAMEGetPackage() func is called,
179     //  and descallocated (reset) by PACKAGENAMEDeletePackage())
180     if (nrefs == ndesc + dyn) 
181       {
182         bbtkDebugMessage("package",2,
183                          " -> No more external ref : checking descriptors"
184                          <<bbtkendl);
185         // We must take care that removing refs on descriptors 
186         // can lead to their deletion which can in turn unref 
187         // internal boxes which can release their descriptors hence 
188         // call Package::ReleaseBlackBoxDescriptor 
189         // As a consequence during descriptors release :
190         // 1) The map can change dynamically : we cannot iterate over it 
191         //    as any iterator can become invalid
192         // 2) The package can auto-destruct : we must test its existence 
193         //    after each release
194         // We must also take care of not locking the package pointer 
195         // or any ref count check in Package::ReleaseBlackBoxDescriptor
196         // would be wrong
197
198         // The list of descriptors names at start
199         std::vector<std::string> descnamelist;
200         BlackBoxMapType::iterator i;
201         for (i=pack.lock()->mBlackBoxMap.begin();
202              i!= pack.lock()->mBlackBoxMap.end();
203              ++i)
204           descnamelist.push_back(i->first);
205
206         // Iterator over the initial names
207         std::vector<std::string>::iterator descname;
208         for (descname=descnamelist.begin();
209              descname!=descnamelist.end();
210              ++descname)
211           {
212             // Is package still alive ?
213             if (pack.expired()) 
214               {
215                 bbtkDebugMessage("package",2,"--- Package::Release('"<<
216                                  packname
217                                  <<"') : package expired during release : bailing out"<<bbtkendl);
218                 break;
219               }
220             
221             PackageReleaseBlackBoxDescriptorInternal(pack,*descname);
222             
223           }
224
225         //
226         UnLoadDynamicLibrary(pack);
227         // Unload orphan dl packages 
228         Package::UnLoadReleasedDynamicallyLoadedPackages();
229         
230
231         
232         
233       }
234     
235     bbtkDebugMessage("package",1,"<== Package::Release('"<<
236                      packname<<"')"<<bbtkendl);
237     if (!pack.expired())
238       {
239         long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0; 
240         long ndesc = pack.lock()->GetBlackBoxMap().size();
241         long nrefs = pack.use_count();
242         
243         bbtkDebugMessage("package",1," ... Package still alive ("
244                          <<nrefs<<" refs / "
245                          <<ndesc<<" descr / dyn="
246                          <<dyn<<")"<<std::endl);
247       }
248     else 
249       {
250         bbtkDebugMessage("package",1,"   ... Package has been released"
251                          <<std::endl);
252       }
253   }
254   //==========================================================================
255
256   //==========================================================================
257   /// "Releases" the package
258   /// Signals the package that it can free the given descriptor
259   /// if they are no more used and free itself if it is no
260   /// more used
261   /// Note : Any non-weak pointer on the package must have been freed
262   void Package::ReleaseBlackBoxDescriptor(Package::WeakPointer pack,
263                                           BlackBoxDescriptor::WeakPointer descr)
264   {
265     std::string packname = pack.lock()->mName;
266     std::string dname = descr.lock()->GetTypeName();    
267     bbtkDebugMessage("package",3,"==> Package::ReleaseBlackBoxDescriptor('"<<
268                      packname<<"','"<<dname<<"')"<<bbtkendl);
269
270     long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0; 
271     long ndesc = pack.lock()->GetBlackBoxMap().size();
272     long nrefs = pack.use_count();
273
274     bbtkDebugMessage("package",3," "<<nrefs<<" refs / "
275                      <<ndesc<<" descr / dynamically loaded = "
276                      <<dyn<<std::endl);
277
278     // A package is "free" from any external reference iff :
279     // i) It is not dynamically loaded and nrefs == ndesc 
280     // (each desc references its package) or
281     // ii) It is dynamically loaded and nrefs == ndesc + 1
282     // (A dynamic library holds a static pointer on the package it contains
283     //  which is allocated when the PACKAGENAMEGetPackage() func is called,
284     //  and descallocated (reset) by PACKAGENAMEDeletePackage())
285     if (nrefs == ndesc + dyn) 
286       {
287         PackageReleaseBlackBoxDescriptorInternal(pack,dname);
288       }
289     
290     // If the package is released and dynamically loaded 
291     // then put it in the static list mReleasedDynamicallyLoadedPackages
292     UnLoadDynamicLibrary(pack,false);
293         
294     bbtkDebugMessage("package",3,"<== Package::ReleaseBlackBoxDescriptor('"<<
295                      packname<<"','"<<dname<<"')"<<bbtkendl);
296     /*
297     if (!pack.expired())
298       {
299         long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0; 
300         long ndesc = pack.lock()->GetBlackBoxMap().size();
301         long nrefs = pack.use_count();
302         
303         bbtkDebugMessage("package",3," ... Package still alive ("
304                          <<nrefs<<" refs / "
305                          <<ndesc<<" descr / dyn="
306                          <<dyn<<")"<<std::endl);
307       }
308     else 
309       {
310         bbtkDebugMessage("package",3,"   ... Package has been released"
311                          <<std::endl);
312       }  
313     */
314   }
315   //==========================================================================    
316
317   //==========================================================================
318   /// Opens a dynamic library which contains a bbtk package
319   /// Returns the handler 
320   /// Load the package management symbols from the lib
321   /// returns false if a problem occured hence can be used 
322   /// to test that a dyn lib is a valid bbtk package lib
323   /// NB : The BBTK version exported from the library 
324   ///      is tested against the current bbtk version
325   DynamicLibraryHandler Package::OpenDynamicLibrary
326   ( const std::string& libname,
327     const std::string& package_name,
328     DLGetPackageFunction& getpack,
329     DLDeletePackageFunction& delpack)
330   {
331     bbtkDebugMessage("package",3,"==> Package::OpenDynamicLibrary("
332                      <<libname<<")"<<std::endl);
333 #if defined(__GNUC__)
334
335     // Open shared lib
336     void *handler;
337     handler = dlopen(libname.c_str(),
338                      BBTK_RTLD_TIME | BBTK_RTLD_SCOPE );
339     if (!handler)
340       {
341         bbtkMessage("package",2,
342                     "Could not open shared library [" <<libname<<"] : "
343                     <<dlerror() << std::endl);
344         return 0;
345       }
346
347     bbtkDebugMessage("package",3,"* Shared lib ["<<libname<<"] open"<<std::endl);
348
349     // Loads the Package bbtk version function 
350     std::string getvername(package_name);
351     getvername += 
352       BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
353     DLGetPackageBBTKVersionFunction getbbtkversion 
354       = (DLGetPackageBBTKVersionFunction)(dlsym(handler,getvername.c_str()));
355     if (!getbbtkversion)
356       {
357         bbtkDebugMessage("package",3,"***"<<std::endl);
358         bbtkMessage("package",2,
359                     "Shared library ["<<libname
360                     <<"] is not a valid bbtk package."
361                     <<" Symbol ["<<getvername<<"] :"<<dlerror()<< std::endl);
362         dlclose(handler);
363         return 0;
364       }
365
366     bbtkDebugMessage("package",3,"* Symbol ["<<getvername
367                      <<"] found"<<std::endl);
368     // version matches ?
369     if (getbbtkversion() != bbtk::GetVersion())
370       {
371         bbtkMessage("package",2,
372                     "Shared library ["<<libname
373                     <<"] was build with bbtk version "
374                     <<getbbtkversion()
375                     <<" but the current program runs with version "
376                     <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
377         dlclose(handler);
378         return 0;
379         
380       }
381
382     bbtkDebugMessage("package",3,"* Package bbtk version '"<<getbbtkversion()<<"' matches"<<std::endl);
383             // Loads the Package get function
384     std::string getpackname(package_name);
385     getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
386     getpack = (DLGetPackageFunction)(dlsym(handler, getpackname.c_str()));
387     if (!getpack)
388       {
389         bbtkMessage("package",2,
390                     "Shared library ["<<libname
391                     <<"] is not a valid bbtk package."
392                     <<" Symbol ["<<getpackname<<"] :"<<dlerror()<< std::endl);
393         dlclose(handler);
394         return 0;
395       }
396   
397     bbtkDebugMessage("package",3,"* Symbol ["<<getpackname<<"] found"<<std::endl);
398     // Loads the Package delete function
399                                           
400     std::string delpackname(package_name);
401     delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
402     delpack = (DLDeletePackageFunction)(dlsym(handler, delpackname.c_str()));
403     if (!delpack)
404       {
405         bbtkMessage("package",2,
406                     "Shared library ["<<libname
407                     <<"] is not a valid bbtk package."
408                     <<" Symbol ["<<delpackname<<"] :"<<dlerror()<< std::endl);
409         dlclose(handler);
410         return 0;
411       }
412     bbtkDebugMessage("package",3,"* Symbol ["<<delpackname<<"] found"<<std::endl);                
413 #elif defined(_WIN32)
414     
415     HINSTANCE handler;
416     
417     SetErrorMode(0);
418     // Open shared lib
419     handler = LoadLibrary(libname.c_str());
420     if (!handler)
421       {
422         bbtkMessage("package",2,
423                     "Could not open shared library [" <<libname<<"]"
424                     << std::endl);
425         return 0;
426       }
427     
428     // Loads the Package bbtk version function 
429     std::string getvername(package_name);
430     getvername += 
431       BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
432     DLGetPackageBBTKVersionFunction getbbtkversion 
433       = (DLGetPackageBBTKVersionFunction)(GetProcAdress(handler,
434                                                         getvername.c_str()));
435     if (!getbbtkversion)
436       {
437         FreeLibrary(handler);
438         bbtkMessage("package",2,
439                     "Shared library ["<<libname
440                     <<"] is not a valid bbtk package."
441                     <<" Symbol ["<<getbbtkversion<<"] not found"<< std::endl);
442         return 0;
443       }
444     
445     // version matches ?
446     if (getbbtkversion() != bbtk::GetVersion())
447       {
448         FreeLibrary(handler);
449         bbtkMessage("package",2,
450                     "Shared library ["<<libname
451                     <<"] was build with bbtk version "
452                     <<getbbtkversion()
453                     <<" but the current program runs with version "
454                     <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
455         return 0;
456         
457       }
458
459      // Loads the Package get function
460     std::string getpackname(package_name);
461     getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
462     getpack = (DLGetPackageFunction)(GetProcAdress(handler, getpackname.c_str()));
463     if (!getpack)
464       {
465         FreeLibrary(handler);
466         bbtkMessage("package",2,
467                     "Shared library ["<<libname
468                     <<"] is not a valid bbtk package."
469                     <<" Symbol ["<<getpackname<<"] not found"<< std::endl);
470         return 0;
471       }
472     
473     // Loads the Package delete function
474     std::string delpackname(package_name);
475     delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
476     delpack = (DLDeletePackageFunction)(GetProcAdress(handler, delpackname.c_str()));
477     if (!delpack)
478       {
479         FreeLibrary(handler);
480         bbtkMessage("package",2,
481                     "Shared library ["<<libname
482                     <<"] is not a valid bbtk package."
483                     <<" Symbol ["<<delpackname<<"] not found"<< std::endl);
484         return 0;
485       }
486                                          
487 #else
488     bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
489 #endif
490     
491     return handler;
492   }
493   //==========================================================================
494   
495   //==========================================================================
496   /// Loads a package from a dynamic library
497   Package::Pointer Package::CreateFromDynamicLibrary(const std::string& libname,
498                                                      const std::string& pkgname,
499                                                      const std::string& path)
500   {
501     bbtkDebugMessage("package",1,"==> Package::CreateFromDynamicLibrary("
502                      <<libname<<")"<<std::endl);
503
504     DLGetPackageFunction gf;
505     DLDeletePackageFunction df;
506     DynamicLibraryHandler h = Package::OpenDynamicLibrary(libname,
507                                                           pkgname,
508                                                           gf,df);
509     if (h==0) return Package::Pointer(); 
510     Package::Pointer p = gf();
511     p->mDynamicLibraryHandler = h;
512     p->mDLDeletePackageFunction = df;
513     
514     std::string separator =
515       ConfigurationFile::GetInstance().Get_file_separator ();
516     //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
517     std::string docreldoc = 
518       separator + "bbdoc" + separator + pkgname + separator + "index.html";
519     std::string reldoc = 
520       ".." + separator + ".." + docreldoc;
521     std::string doc = path + separator + ".." + separator
522       + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
523       + docreldoc;
524     
525     p->SetDocURL(doc);
526     p->SetDocRelativeURL(reldoc);
527     
528     bbtkDebugMessage("package",1,"<== Package::CreateFromDynamicLibrary("
529                      <<libname<<") .. OK"<<std::endl);
530     return p;
531   }
532   //==========================================================================
533
534
535
536
537   //==========================================================================
538   /// UnLoads the package dynamic library (if any)
539   void Package::UnLoadDynamicLibrary(Package::WeakPointer pack, bool doit)
540   {
541     if (pack.expired() || (!pack.lock()->mDynamicLibraryHandler))
542       return;
543     
544     
545     std::string packname = pack.lock()->GetName();
546     bbtkDebugMessage("package",3,"==> Package::UnLoadDynamicLibrary('"
547                      <<packname<<"')"
548                      <<std::endl);
549     
550     if (!pack.lock()->GetBlackBoxMap().empty())
551       {
552         
553         bbtkDebugMessage("package",3,"   Package not empty ... abort"
554                          <<std::endl);
555         return;
556         /*
557         bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
558                         <<"BlackBoxMap not empty "
559                         <<BBTK_INTERNAL_ERROR_MESSAGE);
560         */
561         
562       }
563
564     if (pack.use_count()!=1)
565       {
566         bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
567                         <<"empty dl package with external refs"
568                         <<BBTK_INTERNAL_ERROR_MESSAGE);
569       } 
570
571     if (doit) 
572       {
573         UnLoad(pack);
574         bbtkDebugMessage("package",3,"   ... dynamic library closed"
575                          <<std::endl);    
576       }
577     else 
578       {
579         mReleasedDynamicallyLoadedPackages.insert(pack);
580         bbtkDebugMessage("package",3,
581                          "   ... package put in the 'to unload' list"
582                          <<std::endl);
583
584       }
585
586     bbtkDebugMessage("package",3,"<== Package::UnLoadDynamicLibrary('"
587                      <<packname<<"')"
588                      <<std::endl);
589     
590   }
591   //==========================================================================
592
593   //==========================================================================
594   /// UnLoads released packages that were loaded dynamically
595   /// see UnLoadDynamicLibrary and ReleaseBlackBoxDescriptor
596   void Package::UnLoadReleasedDynamicallyLoadedPackages()
597   {
598     bbtkDebugMessage("package",2,"==> Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
599
600     std::set<Package::WeakPointer>::iterator i;
601     for (i=mReleasedDynamicallyLoadedPackages.begin();
602          i!=mReleasedDynamicallyLoadedPackages.end();
603          ++i)
604       {
605         if (!i->expired()) UnLoad(*i);
606       }
607     bbtkDebugMessage("package",2,"<== Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
608   }
609   //==========================================================================
610
611   //==========================================================================
612   void Package::UnLoad(Package::WeakPointer pack)
613   {
614     std::string packname = pack.lock()->GetName();
615     bbtkDebugMessage("package",2,"==> Package::UnLoad("<<packname<<")"<<std::endl);
616
617     Package* p = pack.lock().get();
618     
619     DynamicLibraryHandler h = p->mDynamicLibraryHandler;
620     
621     // deletes the package
622     p->mDLDeletePackageFunction();
623     
624     // closes the dl handler
625 #if defined(__GNUC__)  
626     dlclose(h);  
627 #elif defined(_WIN32)
628     FreeLibrary(h);
629 #endif
630
631     bbtkDebugMessage("package",2,"   ... dynamic library unloaded"<<std::endl);
632   }
633   //==========================================================================
634
635   //==========================================================================
636   /// Creates an instance of a black box of type <type> with name <name>
637   BlackBox::Pointer Package::NewBlackBox(const std::string& type, 
638                                          const std::string& name) const
639   {
640     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::NewBlackBox(\""<<type<<"\",\""<<name<<"\")"<<bbtkendl);
641     
642     BlackBoxMapType::const_iterator i = mBlackBoxMap.find(type);
643     if (i == mBlackBoxMap.end())  
644     {
645            bbtkDebugDecTab("Kernel",8);
646            return BlackBox::Pointer();
647     }
648     BlackBox::Pointer bb =i->second->NewBlackBox(name);
649     bbtkDebugDecTab("Kernel",8);
650     return bb;   
651
652   }
653   //==========================================================================
654
655
656
657   //==========================================================================
658   /// Creates an instance of an adaptor of input type <typein> and 
659   /// output type <typeout>  with name <name>
660   BlackBox::Pointer Package::NewAdaptor(const DataInfo& typein,
661                                 const DataInfo& typeout,
662                                 const std::string& name) const
663   {
664     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
665                         ">::NewAdaptor("
666                         <<typein<<","
667                         <<typeout<<",\""
668                         <<name<<"\")"<<bbtkendl);
669
670     AdaptorKey key(typein,typeout,
671                    BlackBoxDescriptor::DEFAULT_ADAPTOR);
672     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
673     if (i == mAdaptorMap.end())  
674       {
675         bbtkDebugDecTab("Kernel",8);
676         return BlackBox::Pointer();
677       }
678     BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
679     bbtkDebugDecTab("Kernel",8);
680     return bb;   
681
682   }
683   //==========================================================================
684
685   //==========================================================================
686   /// Creates an instance of an adaptor of input type <typein> and 
687   /// output type <typeout>  with name <name>
688   BlackBox::Pointer Package::NewWidgetAdaptor(const DataInfo& typein,
689                                       const DataInfo& typeout,
690                                       const std::string& name) const
691   {
692     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
693                         ">::NewWidgetAdaptor("
694                         <<typein<<","
695                         <<typeout<<",\""
696                         <<name<<"\")"<<bbtkendl);
697
698     AdaptorKey key(typein,typeout,
699                    BlackBoxDescriptor::DEFAULT_GUI);
700     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
701     if (i == mAdaptorMap.end())  
702       {
703         bbtkDebugDecTab("Kernel",8);
704         return BlackBox::Pointer();
705       }
706     BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
707     bbtkDebugDecTab("Kernel",8);
708     return bb;   
709
710   }
711   //==========================================================================
712
713
714
715   //==========================================================================
716   /// Returns true is the package contains 
717   /// an adaptor of input type <typein> and 
718   /// output type <typeout>
719   /// If successfull then adaptor contains the black box type name
720   bool Package::FindWidgetAdaptor(const DataInfo& typein,
721                                   const DataInfo& typeout,
722                                   std::string& adaptor) const
723   {
724     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
725                         ">::FindWidgetAdaptor("
726                         <<typein<<","
727                         <<typeout<<")"<<bbtkendl);
728    
729     AdaptorKey key(/*typein*/
730                    DataInfo(typeid(void),""),
731                    typeout,
732                    BlackBoxDescriptor::DEFAULT_GUI);
733     // First try to find a single widget adaptor
734     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
735     if (i == mAdaptorMap.end())  
736       {
737         bbtkDebugDecTab("Kernel",8);
738         return false;
739       }
740     adaptor = i->second.lock()->GetTypeName();
741     bbtkDebugDecTab("Kernel",8);
742     return true;   
743
744   }
745   //==========================================================================
746
747
748
749   //==========================================================================
750   /// Returns true is the package contains 
751   /// an adaptor of input type <typein> and 
752   /// output type <typeout>
753   /// If successfull then adaptor contains the black box type name
754   bool Package::FindAdaptor(const DataInfo& typein,
755                             const DataInfo& typeout,
756                             std::string& adaptor) const
757   {
758     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
759                         ">::FindAdaptor("
760                         <<typein<<","
761                         <<typeout<<")"<<bbtkendl);
762     
763     AdaptorKey key(typein,typeout,
764                    BlackBoxDescriptor::DEFAULT_ADAPTOR);
765     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
766     if (i == mAdaptorMap.end())  
767       {
768         bbtkDebugDecTab("Kernel",8);
769         return false;
770       }
771     adaptor = i->second.lock()->GetTypeName();
772     bbtkDebugDecTab("Kernel",8);
773     return true;   
774
775   }
776   //==========================================================================
777
778
779   //==========================================================================
780   /// Registers a black box descriptor in the package
781   bool Package::RegisterBlackBox(BlackBoxDescriptor::Pointer d) 
782   {
783     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\")"<<std::endl);
784     
785     BlackBoxMapType::iterator i = mBlackBoxMap.find(d->GetTypeName());
786     if (i!=mBlackBoxMap.end())
787       {
788         bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
789                     <<d->GetTypeName()<<"> which is already in the package");
790         return false;
791       }
792
793     mBlackBoxMap[d->GetTypeName()] = d;
794     //    d->Reference();
795     d->SetPackage(GetThisPointer<Package>());
796     
797     // If it is a default adaptor, also register it in the adaptors map
798     if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
799       {
800         bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);   
801         
802         TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
803         TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
804         DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
805         DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
806         AdaptorKey key(infoin,infoout,d->GetKind());
807         
808         AdaptorMapType::const_iterator i;
809         i = mAdaptorMap.find(key);        
810         if (i == mAdaptorMap.end())  
811           {
812             mAdaptorMap[key] = d;
813           }
814         // If already an adaptor registered : error
815         else 
816           {
817             if (i->second.lock()->GetTypeName() != d->GetTypeName()) 
818               {
819                 bbtkError("Package <"<<GetName()<<
820                           "> : trying to register black box <"
821                           <<d->GetTypeName()
822                           <<"> as default adaptor but there is already a default adaptor registered (<"
823                           <<i->second.lock()->GetTypeName()<<">)");
824               }
825           }
826       }
827     // If it is a default adaptor, also register it in the adaptors map
828     else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
829       {
830         bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is a widget adaptor, inserting it in adaptors map ..."<<std::endl);   
831         
832         TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
833         DataInfo infoin(typeid(void),"");
834         DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
835         AdaptorKey key(infoin,infoout,d->GetKind());
836
837         AdaptorMapType::const_iterator i;
838         i = mAdaptorMap.find(key);        
839         if (i == mAdaptorMap.end())  
840           {
841             mAdaptorMap[key] = d;
842           }
843         // If already an adaptor registered : error
844         else 
845           {
846             if (i->second.lock()->GetTypeName() != d->GetTypeName()) 
847               {
848                 bbtkError("Package <"<<GetName()<<
849                           "> : trying to register black box <"
850                           <<d->GetTypeName()
851                           <<"> as default widget adaptor but there is already a default adaptor registered (<"
852                           <<i->second.lock()->GetTypeName()<<">)");
853               }
854           }
855       }
856     
857
858     bbtkDebugDecTab("Kernel",8);
859    
860     return true;
861   }
862   //==========================================================================
863   
864   //===================================================================
865   void Package::CheckBoxes() const
866   {
867     bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
868                 <<" ["<<GetName()<<"]"<<std::endl);
869     BlackBoxMapType::const_iterator i;
870     for (i=mBlackBoxMap.begin();
871          i!=mBlackBoxMap.end();
872          ++i) 
873       {
874         i->second->Check(true);
875       }
876     bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
877                 <<" ["<<GetName()<<"] ... OK"<<std::endl);
878   }
879   //===================================================================
880
881
882   //==========================================================================
883   /// Changes the name of a black box type
884   void Package::ChangeBlackBoxName( const std::string& oldname, const std::string& newname )
885   { 
886     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::ChangeBlackBoxName(\""<<oldname<<"\",\""<<newname<<"\")"<<std::endl);
887     // Looking into the bb map
888     BlackBoxMapType::iterator i = mBlackBoxMap.find(oldname);
889     if (i == mBlackBoxMap.end())  
890       {
891          bbtkDebugDecTab("Kernel",8);
892          bbtkError("ChangeBlackBoxName : The package <"<<GetName()<<"> does not contains the black box <"<<oldname<<">");
893       }
894
895     i->second->SetTypeName(newname);
896     mBlackBoxMap[newname] = i->second;
897     mBlackBoxMap.erase(i);
898
899     bbtkDebugDecTab("Kernel",8);    
900   }
901   //==========================================================================
902
903
904
905   //==========================================================================
906   /// Displays the list of black boxes of the package
907   void Package::PrintBlackBoxes(bool description, bool adaptors) const
908   {
909     unsigned int lmax = 0;
910     std::vector<std::string> names;
911     std::vector<std::string> kinds;
912     std::vector<std::string> descrs;
913
914     BlackBoxMapType::const_iterator i;
915     for (i=mBlackBoxMap.begin();
916          i!=mBlackBoxMap.end();
917          ++i) 
918       {
919         if ( adaptors || 
920              ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) ) 
921           {
922             std::string name("  ");
923             name += i->second->GetTypeName();
924             names.push_back(name);
925
926             std::string kind;
927             if ( i->second->GetKind() == BlackBoxDescriptor::ADAPTOR )
928               {
929                 kind = std::string("[A]");
930               }
931             else if ( i->second->GetKind() == 
932                       BlackBoxDescriptor::DEFAULT_ADAPTOR )
933               {
934                 kind = std::string("[DA]");
935               }
936             kinds.push_back(kind);
937
938             unsigned int l = name.size()+kind.size();
939             if (l>lmax) lmax = l;
940
941             std::string descr;
942             if (description) 
943               {
944                 descr += " : ";
945                 descr += i->second->GetDescription();
946               } 
947             descrs.push_back(descr);
948           }
949       } 
950     
951
952     std::string offs;
953     offs.append(lmax+3,' ');
954     std::vector<std::string>::iterator ni,ci,di;
955     for (ni = names.begin(), ci = kinds.begin(), di = descrs.begin();
956          ni != names.end(); ++ni, ++ci, ++di)
957       {
958         std::string space;
959         space.append(lmax - ni->size() - ci->size(),' ');
960         bbtkMessage("Help",1,*ni << space << *ci );
961         std::string d(*di);
962         unsigned int dmax = 75 - lmax;
963         //      while (d.size() > dmax ) 
964         //  {
965         if (d.size()>dmax) 
966           bbtkMessage("Help",1,d.substr(0,dmax) << "..." << std::endl);
967         else 
968           bbtkMessage("Help",1,d << std::endl);
969         //    d = d.substr(dmax,d.size());
970         //  }
971       }
972
973   }
974   //==========================================================================
975
976   //==========================================================================
977   /// Displays the list of adaptors of the package
978   void Package::PrintAdaptors(bool description) const
979   {
980     BlackBoxMapType::const_iterator i;
981     for (i=mBlackBoxMap.begin();
982          i!=mBlackBoxMap.end();
983          ++i) 
984       {
985         if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD ) 
986           {
987             bbtkMessage("Help",1,
988                         "  "<<i->second->GetTypeName());
989             if ( i->second->GetKind() == 
990                  BlackBoxDescriptor::DEFAULT_ADAPTOR )
991               {
992                 bbtkMessage("Help",1,
993                             " [default]");
994               }  
995             if (description) 
996               {
997                 bbtkMessage("Help",1,
998                             " : "<<i->second->GetDescription());
999
1000               } 
1001             bbtkMessage("Help",1,std::endl);
1002           }
1003       } 
1004     /*
1005     AdaptorMapType::const_iterator i;
1006     for (i=mAdaptorMap.begin();
1007          i!=mAdaptorMap.end();
1008          ++i) 
1009       {
1010         bbtkMessage("Help",1,
1011                     "  "<<i->second->GetTypeName());
1012         if (detail_level>0) 
1013           {
1014             bbtkMessage("Help",1,
1015                         " : "<<i->second->GetDescription());
1016   
1017           } 
1018         bbtkMessage("Help",1,std::endl);
1019       }
1020     */ 
1021   }
1022   //==========================================================================
1023
1024   //==========================================================================
1025   /// Prints help on a black box
1026   void Package::HelpBlackBox(const std::string& name, bool full) const
1027   {
1028     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1029                         <<name<<"\")"<<bbtkendl);
1030
1031     BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1032     if (i == mBlackBoxMap.end())  
1033       {
1034         bbtkDebugDecTab("Kernel",8);
1035         bbtkError("The package <"<<GetName()<<"> does not contains the black box <"<<name<<">");
1036       }
1037     //    bbtkMessage("Help",1,"["<<GetName()<<"] ");
1038     i->second->GetHelp(full);
1039     bbtkDebugDecTab("Kernel",8);
1040
1041   }
1042   //==========================================================================
1043
1044
1045   //==========================================================================
1046   /// Returns true iff the package contains the box of name boxname
1047   bool Package::ContainsBlackBox(const std::string& name) const 
1048   {
1049     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1050                         <<name<<"\")"<<bbtkendl);
1051     
1052     BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1053     if (i == mBlackBoxMap.end())  
1054     {
1055       bbtkDebugDecTab("Kernel",8);
1056       return false;
1057     }
1058     bbtkDebugDecTab("Kernel",8);
1059     return true;
1060   }
1061   //==========================================================================
1062
1063
1064  
1065   //==========================================================================
1066   void Package::CreateHtmlPage(const std::string& filename,
1067                                const std::string& caller,
1068                                const std::string& source,
1069                                const std::string& custom_header,
1070                                const std::string& custom_title,
1071                                int detail, 
1072                                int level,
1073                                bool relative_link ) const
1074   {
1075     bbtkDebugMessageInc("Kernel",9,"Package<"<<GetName()<<">::CreateHtmlPage(\""
1076                         <<filename<<"\")"<<bbtkendl);
1077
1078     //---------------------
1079     // Open output file
1080     std::ofstream s;
1081     s.open(filename.c_str());
1082     if (!s.good()) 
1083     {
1084        bbtkError("Package "<<GetName()<<" : CreateHtmlPage : could not open file '"<<filename<<"'");
1085     }
1086     
1087     //----------------------
1088     // Html head
1089     std::string title = "BBTK Package "+GetName()+" "+GetVersion(); 
1090
1091     if (custom_title.length() != 0) title = custom_title;
1092
1093     s << "<html lang=\"en\">\n";
1094     s << "<head>\n";
1095     s << "<title>" << title << "</title>\n";
1096     s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1097     s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1098     s << "<meta name=\"generator\" content=\"\">\n";
1099     s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1100     //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1101     s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1102     s << "pre.display { font-family:inherit }\n";
1103     s << "pre.format  { font-family:inherit }\n";
1104     s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1105     s << "pre.smallformat  { font-family:inherit; font-size:smaller }\n";
1106     s << "pre.smallexample { font-size:smaller }\n";
1107     s << "pre.smalllisp    { font-size:smaller }\n";
1108     s << "span.sc    { font-variant:small-caps }\n";
1109     s << "span.roman { font-family:serif; font-weight:normal; } \n";
1110     s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n"; 
1111     s << "--></style>\n";
1112     s << "</head>\n";
1113     //----------------------
1114
1115     //----------------------
1116     // Html body
1117     s << "<body>\n";
1118     s << "<a name=\"Top\"></a>\n"; 
1119     
1120     //----------------------
1121     // Header
1122     if ( custom_header.length() != 0) 
1123       {
1124         if ( custom_header != "none" )
1125           { 
1126             std::ifstream in;
1127             in.open(custom_header.c_str());    
1128             if (!in.good()) 
1129               {
1130                 bbtkError("Could not open file \""<<custom_header<<"\"");
1131               }
1132             char buffer[512];
1133             while (!in.eof()) 
1134               {
1135                 in.getline(buffer,512);
1136                 std::string line(buffer);
1137                 s << line;
1138               }
1139             in.close();
1140             s << "<hr>\n";
1141            
1142             /*   
1143             s << "<object data=\"" << custom_header 
1144               << "\" type = \"text/html\"\"style=\"width: 1200px; height: 400px;\"> Warning: "
1145               << custom_header <<" could not be embedded.</object>\n";
1146             
1147             s << "<hr>\n";
1148             */
1149           }
1150       }
1151
1152     else 
1153       {
1154         s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1155         s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1156         s << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
1157           << GetDescription() << "</TD></TR>\n";
1158         s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'>  " 
1159           << GetAuthor() << "</TD></TR>\n";
1160         s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'>  " 
1161           << GetCategory() << "</TD></TR>\n";
1162         s << "<TR><TD style='vertical-align: top;'><b> Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
1163           << GetVersion() << "</TD></TR>\n";
1164         s << "<TR><TD style='vertical-align: top;'><b> bbtk Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
1165           << bbtk::GetVersion() << "</TD></TR>\n";
1166         s << "</TABLE>\n";
1167       }
1168
1169     //-------------------
1170     // Table of contents
1171     // Black boxes list
1172     //  s << "<div class=\"contents\">\n";
1173     s << "<p><b> Black Boxes : </b>\n";
1174     s << "<ul>\n";
1175
1176     s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1177
1178     BlackBoxMapType::const_iterator i;
1179     for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i) 
1180       {
1181         if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD) 
1182           continue;
1183         
1184         std::string name = i->second->GetTypeName();
1185         Utilities::html_format(name);
1186         std::string descr = i->second->GetDescription();
1187         Utilities::html_format(descr);
1188
1189         s << "<TR>";
1190         s << "<TD style='vertical-align: top;'>";
1191         s << "&nbsp;&nbsp;&nbsp;<a name=\"toc_"<<name
1192           <<"\" href=\"#"<<name<<"\">"
1193           <<name<<"</a>";
1194         s << "</TD> ";
1195         s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1196         s << "</TR>\n";
1197       }    
1198     s << "</TABLE>\n";
1199     
1200     
1201     s << "</ul>\n";
1202     s << "</div>\n";
1203     
1204     //-------------------
1205     // Adaptors list
1206     if (mAdaptorMap.size()>0) 
1207       {
1208         //  s << "<div class=\"contents\">\n";
1209         s << "<p><b> Adaptors : </b>\n";
1210         s << "<ul>\n";
1211
1212         //    BlackBoxMapType::const_iterator i;
1213         s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1214         for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end();++i) 
1215           {
1216             if ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) 
1217               continue;
1218     
1219             std::string name = i->second->GetTypeName();
1220             Utilities::html_format(name);
1221             std::string descr = i->second->GetDescription();
1222     
1223             s << "<TR>";
1224             s << "<TD style='vertical-align: top;'>";
1225             s << "&nbsp;&nbsp;&nbsp;<a name=\"toc_"<<name
1226               <<"\" href=\"#"<<name<<"\">"
1227               <<name<<"</a>";
1228             s << "</TD> ";
1229             s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1230             s << "</TR>\n";
1231           }    
1232         s << "</TABLE>\n";
1233
1234         s << "</ul>\n";
1235         s << "</div>\n";
1236       }
1237     
1238     
1239     //  s << "<div class=\"node\">\n";
1240
1241     //    s << "<p><hr>\n";
1242     //    s << "<a name=\"Top\"></a>\n";
1243     //  s << "Top:&nbsp;<a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
1244     // s << "Previous:&nbsp;<a rel="previous" accesskey="p" href="#dir">(dir)</a>,
1245     // s << "Up:&nbsp;<a rel="up" accesskey="u" href="#dir">(dir)</a>
1246     
1247     //    s << "</div>\n";
1248
1249     //----------------------
1250     // Boxes doc
1251
1252     //-------------------
1253     // Computes output directory from filename to pass it to 
1254     // BlackBoxDescriptor::InsertHtmlHelp
1255     std::string dir;
1256
1257     std::string::size_type slash_position = filename.find_last_of("/\\");
1258
1259
1260         if (slash_position != std::string::npos) {
1261       if (slash_position == 0)
1262          slash_position = 1;  
1263       dir = filename.substr(0,slash_position);
1264     }
1265
1266     for (i=mBlackBoxMap.begin();
1267          i!=mBlackBoxMap.end();
1268          ++i) 
1269       {
1270         i->second->InsertHtmlHelp(s,detail,level,dir,relative_link);
1271       }    
1272
1273     //----------------------
1274     // Footer 
1275     time_t rawtime;
1276     tm * ptm;
1277     time ( &rawtime );
1278     ptm = gmtime ( &rawtime );
1279
1280     s << "<p><hr>\n";
1281     s << "Automatically generated by <b>"<<caller<<"</b> "//from <b>"
1282       //      <<source<<"</b>
1283       <<"on "
1284       << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900 
1285       << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1286     s << "</body></html>\n"; 
1287     s.close();
1288     //----------------------
1289
1290     // End
1291     bbtkDebugDecTab("Kernel",9);
1292   }
1293   //==========================================================================
1294   
1295   //==========================================================================
1296   std::string  Package::GetObjectName() const 
1297   { 
1298     return std::string("Package '")+mName+std::string("'"); 
1299   }
1300   //==========================================================================
1301
1302   //==========================================================================
1303   std::string Package::GetObjectInfo() const 
1304   {
1305     std::stringstream i;
1306     i << "  - "<<mBlackBoxMap.size() << " boxes" << std::endl;
1307     if (mDynamicLibraryHandler) 
1308       {
1309         i<< "  - Loaded from dynamic library"<<std::endl;
1310       }
1311     return i.str();
1312   }
1313   //==========================================================================
1314
1315
1316   //==========================================================================
1317   size_t  Package::GetObjectSize() const 
1318   {
1319     size_t s = Superclass::GetObjectSize();
1320     s += Package::GetObjectInternalSize();
1321     return s;
1322   }
1323   //==========================================================================
1324   //==========================================================================
1325   size_t  Package::GetObjectInternalSize() const 
1326   {
1327     size_t s = sizeof(Package);
1328     return s;
1329   }
1330   //==========================================================================
1331   //==========================================================================
1332   size_t  Package::GetObjectRecursiveSize() const 
1333   {
1334     size_t s = Superclass::GetObjectRecursiveSize();
1335     s += Package::GetObjectInternalSize();
1336     
1337     BlackBoxMapType::const_iterator i;
1338     for (i = mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i )
1339       {
1340         s += i->second->GetObjectRecursiveSize();
1341       }
1342     return s;
1343   }
1344   //==========================================================================
1345   
1346   //==========================================================================
1347   std::set<Package::WeakPointer> 
1348   Package::mReleasedDynamicallyLoadedPackages;
1349   //==========================================================================
1350 }
1351