2 /*=========================================================================
4 Module: $RCSfile: bbtkPackage.cxx,v $
6 Date: $Date: 2009/05/28 08:26:59 $
7 Version: $Revision: 1.27 $
8 =========================================================================*/
10 /* ---------------------------------------------------------------------
12 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
13 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
15 * This software is governed by the CeCILL-B license under French law and
16 * abiding by the rules of distribution of free software. You can use,
17 * modify and/ or redistribute the software under the terms of the CeCILL-B
18 * license as circulated by CEA, CNRS and INRIA at the following URL
19 * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
20 * or in the file LICENSE.txt.
22 * As a counterpart to the access to the source code and rights to copy,
23 * modify and redistribute granted by the license, users are provided only
24 * with a limited warranty and the software's author, the holder of the
25 * economic rights, and the successive licensors have only limited
28 * The fact that you are presently reading this means that you have had
29 * knowledge of the CeCILL-B license and that you accept its terms.
30 * ------------------------------------------------------------------------ */
34 *\brief Class bbtk::Package : registers black boxes descriptors and is able to create instances of the black boxes registered.
36 #include "bbtkPackage.h"
37 #include "bbtkMessageManager.h"
38 #include "bbtkConfigurationFile.h"
41 #include "bbtkUtilities.h"
48 //==========================================================================
49 /// Creates a new package
50 Package::Pointer Package::New(const std::string& name,
51 const std::string& author,
52 const std::string& description,
53 const std::string& version)
55 bbtkDebugMessage("object",1,"##> Package::New('"<<name<<"',...)"
57 Package::Pointer p = MakePointer(new Package(name,
61 bbtkDebugMessage("object",2,"<## Package::New('"<<name<<"',...)"
65 //==========================================================================
67 //==========================================================================
68 /// Ctor with the name of the package
69 Package::Package(const std::string& name,
70 const std::string& author,
71 const std::string& description,
72 const std::string& version)
74 mDynamicLibraryHandler(0),
77 mDescription(description),
80 bbtkDebugMessage("object",2,"==> Package('"<<name<<"',...)"
82 std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
83 char c = default_doc_dir.c_str()[strlen(default_doc_dir.c_str())-1];
84 std::string url = default_doc_dir;
85 if (c != '/' && c !='\\') url = url + "/";
86 url = url + "temp_dir/" + name + "/index.html";
89 SetDocRelativeURL("Relative url not set");
92 std::string relurl(BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH));
93 relurl += "/packages/"+name+"/bbdoc/index.html";
94 std::string url = ConfigurationFile::GetInstance().Get_url()
97 SetDocRelativeURL(relurl);
100 // std::cout << " url=["<<url<<"]"<<std::endl;
101 // std::cout << "relurl=["<<relurl<<"]"<<std::endl;
102 bbtkDebugMessage("object",2,"<== Package::Package('"<<name<<"',...) OK"
106 //==========================================================================
110 //==========================================================================
114 bbtkDebugMessage("object",2,"==> ~Package(\""<<mName<<"\")"<<bbtkendl);
116 //==========================================================================
119 //==========================================================================
120 void PackageReleaseBlackBoxDescriptorInternal(Package::WeakPointer pack,
121 const std::string& descname)
123 // Try to release descriptor
124 std::string packname = pack.lock()->GetName();
126 bbtkDebugMessage("package",5,"--- Releasing descriptor '"
127 <<packname<<"::"<<descname<<"'"<<bbtkendl);
130 Package::BlackBoxMapType::iterator desc =
131 pack.lock()->GetBlackBoxMap().find(descname);
132 if (desc == pack.lock()->GetBlackBoxMap().end())
134 bbtkDebugMessage("package",5,
135 " Descriptor has already been released"
139 // bbtkDebugMessage("package",3,
140 // " Trying unreferencing it ... "<<std::endl);
141 BlackBoxDescriptor::WeakPointer pdesc = desc->second;
142 desc->second.reset();
143 // if it is dead : remove it
146 bbtkDebugMessage("package",2," ==> '"<<packname<<"::"<<descname<<"' Descriptor expired"<<bbtkendl);
149 bbtkDebugMessage("package",2,
150 " ... and caused its package death"
154 desc = pack.lock()->GetBlackBoxMap().find(descname);
155 if (desc != pack.lock()->GetBlackBoxMap().end()) pack.lock()->GetBlackBoxMap().erase(desc);
156 } else { //pdesc.expired
157 bbtkDebugMessage("package",5," ... Descriptor still alive ("
158 <<pdesc.use_count()<<" refs)"
160 pack.lock()->GetBlackBoxMap()[descname] = pdesc.lock();
163 //==========================================================================
166 //==========================================================================
168 void Package::Release(Package::WeakPointer pack)
170 std::string packname = pack.lock()->mName;
171 bbtkDebugMessage("package",1,"==> Package::Release('"<<
172 packname<<"')"<<bbtkendl);
174 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
175 long ndesc = pack.lock()->GetBlackBoxMap().size();
176 long nrefs = pack.use_count();
178 bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
179 <<ndesc<<" descr / dyn="
182 // A package is "free" from any external reference iff :
183 // i) It is not dynamically loaded and nrefs == ndesc
184 // (each desc references its package) or
185 // ii) It is dynamically loaded and nrefs == ndesc + 1
186 // (A dynamic library holds a static pointer on the package it contains
187 // which is allocated when the PACKAGENAMEGetPackage() func is called,
188 // and descallocated (reset) by PACKAGENAMEDeletePackage())
189 if (nrefs == ndesc + dyn)
191 bbtkDebugMessage("package",5,
192 " -> No more external ref : checking descriptors"
194 // We must take care that removing refs on descriptors
195 // can lead to their deletion which can in turn unref
196 // internal boxes which can release their descriptors hence
197 // call Package::ReleaseBlackBoxDescriptor
198 // As a consequence during descriptors release :
199 // 1) The map can change dynamically : we cannot iterate over it
200 // as any iterator can become invalid
201 // 2) The package can auto-destruct : we must test its existence
202 // after each release
203 // We must also take care of not locking the package pointer
204 // or any ref count check in Package::ReleaseBlackBoxDescriptor
207 // The list of descriptors names at start
208 std::vector<std::string> descnamelist;
209 BlackBoxMapType::iterator i;
210 for (i=pack.lock()->mBlackBoxMap.begin();
211 i!= pack.lock()->mBlackBoxMap.end();
213 descnamelist.push_back(i->first);
215 // Iterator over the initial names
216 std::vector<std::string>::iterator descname;
217 for (descname=descnamelist.begin();
218 descname!=descnamelist.end();
221 // Is package still alive ?
224 bbtkDebugMessage("package",1,"--- Package::Release('"<<
226 <<"') : package expired during release : bailing out"<<bbtkendl);
231 if (dyn==0) PackageReleaseBlackBoxDescriptorInternal(pack,*descname);
233 PackageReleaseBlackBoxDescriptorInternal(pack,*descname);
239 UnLoadDynamicLibrary(pack);
240 // Unload orphan dl packages
241 Package::UnLoadReleasedDynamicallyLoadedPackages();
248 #ifdef BBTK_COMPILE_DEBUG_MESSAGES
250 bbtkDebugMessage("package",2,"<== Package::Release('"<<
251 packname<<"')"<<bbtkendl);
255 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
256 long ndesc = pack.lock()->GetBlackBoxMap().size();
257 long nrefs = pack.use_count();
259 bbtkDebugMessage("package",1," ... Package still alive ("
261 <<ndesc<<" descr / dyn="
262 <<dyn<<")"<<std::endl);
266 bbtkDebugMessage("package",1," ... Package has been released"
271 //==========================================================================
273 //==========================================================================
274 /// "Releases" the package
275 /// Signals the package that it can free the given descriptor
276 /// if they are no more used and free itself if it is no
278 /// Note : Any non-weak pointer on the package must have been freed
279 void Package::ReleaseBlackBoxDescriptor(Package::WeakPointer pack,
280 BlackBoxDescriptor::WeakPointer descr)
282 std::string packname = pack.lock()->mName;
283 std::string dname = descr.lock()->GetTypeName();
284 bbtkDebugMessage("package",3,"==> Package::ReleaseBlackBoxDescriptor('"<<
285 packname<<"','"<<dname<<"') : refs="
286 <<descr.use_count()<<bbtkendl);
288 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
289 long ndesc = pack.lock()->GetBlackBoxMap().size();
290 long nrefs = pack.use_count();
292 bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
293 <<ndesc<<" descr / dynamically loaded = "
296 // A package is "free" from any external reference iff :
297 // i) It is not dynamically loaded and nrefs == ndesc
298 // (each desc references its package) or
299 // ii) It is dynamically loaded and nrefs == ndesc + 1
300 // (A dynamic library holds a static pointer on the package it contains
301 // which is allocated when the PACKAGENAMEGetPackage() func is called,
302 // and descallocated (reset) by PACKAGENAMEDeletePackage())
303 if (nrefs == ndesc + dyn)
308 PackageReleaseBlackBoxDescriptorInternal(pack,dname);
310 PackageReleaseBlackBoxDescriptorInternal(pack,dname);
314 // If the package is released and dynamically loaded
315 // then put it in the static list mReleasedDynamicallyLoadedPackages
316 UnLoadDynamicLibrary(pack,false);
318 bbtkDebugMessage("package",4,"<== Package::ReleaseBlackBoxDescriptor('"<<
319 packname<<"','"<<dname<<"'): refs="
320 <<descr.use_count()<<bbtkendl);
324 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
325 long ndesc = pack.lock()->GetBlackBoxMap().size();
326 long nrefs = pack.use_count();
328 bbtkDebugMessage("package",3," ... Package still alive ("
330 <<ndesc<<" descr / dyn="
331 <<dyn<<")"<<std::endl);
335 bbtkDebugMessage("package",3," ... Package has been released"
340 //==========================================================================
342 //==========================================================================
343 /// Opens a dynamic library which contains a bbtk package
344 /// Returns the handler
345 /// Load the package management symbols from the lib
346 /// returns false if a problem occured hence can be used
347 /// to test that a dyn lib is a valid bbtk package lib
348 /// NB : The BBTK version exported from the library
349 /// is tested against the current bbtk version
350 DynamicLibraryHandler Package::OpenDynamicLibrary
351 ( const std::string& libname,
352 const std::string& package_name,
353 DLGetPackageFunction& getpack,
354 DLDeletePackageFunction& delpack)
356 bbtkDebugMessage("package",3,"==> Package::OpenDynamicLibrary("
357 <<libname<<")"<<std::endl);
358 #if defined(__GNUC__)
362 handler = dlopen(libname.c_str(), BBTK_RTLD_TIME | BBTK_RTLD_SCOPE );
363 //EED handler = dlopen(libname.c_str(), RTLD_LAZY | RTLD_LOCAL );
367 bbtkMessage("package",2,
368 "Could not open shared library [" <<libname<<"] : "
369 <<dlerror() << std::endl);
373 bbtkDebugMessage("package",3,"* Shared lib ["<<libname<<"] open"<<std::endl);
375 // Loads the Package bbtk version function
376 std::string getvername(package_name);
378 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
379 DLGetPackageBBTKVersionFunction getbbtkversion
380 = (DLGetPackageBBTKVersionFunction)(dlsym(handler,getvername.c_str()));
383 bbtkDebugMessage("package",3,"***"<<std::endl);
384 bbtkMessage("package",2,
385 "Shared library ["<<libname
386 <<"] is not a valid bbtk package."
387 <<" Symbol ["<<getvername<<"] :"<<dlerror()<< std::endl);
392 bbtkDebugMessage("package",3,"* Symbol ["<<getvername
393 <<"] found"<<std::endl);
395 if (getbbtkversion() != bbtk::GetVersion())
397 bbtkMessage("package",2,
398 "Shared library ["<<libname
399 <<"] was build with bbtk version "
401 <<" but the current program runs with version "
402 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
408 bbtkDebugMessage("package",3,"* Package bbtk version '"<<getbbtkversion()<<"' matches"<<std::endl);
409 // Loads the Package get function
410 std::string getpackname(package_name);
411 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
412 getpack = (DLGetPackageFunction)(dlsym(handler, getpackname.c_str()));
415 bbtkMessage("package",2,
416 "Shared library ["<<libname
417 <<"] is not a valid bbtk package."
418 <<" Symbol ["<<getpackname<<"] :"<<dlerror()<< std::endl);
423 bbtkDebugMessage("package",3,"* Symbol ["<<getpackname<<"] found"<<std::endl);
424 // Loads the Package delete function
426 std::string delpackname(package_name);
427 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
428 delpack = (DLDeletePackageFunction)(dlsym(handler, delpackname.c_str()));
431 bbtkMessage("package",2,
432 "Shared library ["<<libname
433 <<"] is not a valid bbtk package."
434 <<" Symbol ["<<delpackname<<"] :"<<dlerror()<< std::endl);
438 bbtkDebugMessage("package",3,"* Symbol ["<<delpackname<<"] found"<<std::endl);
439 #elif defined(_WIN32)
445 handler = LoadLibrary(libname.c_str());
448 bbtkMessage("package",2,
449 "Could not open shared library [" <<libname<<"]"
451 DWORD dwErrorCode = 0;
452 dwErrorCode = GetLastError();
453 bbtkMessage("package",2,
454 "Windows Error: [" << dwErrorCode <<"]"
460 // Loads the Package bbtk version function
461 std::string getvername(package_name);
463 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
464 DLGetPackageBBTKVersionFunction getbbtkversion
465 = (DLGetPackageBBTKVersionFunction)(GetProcAddress(handler,
466 getvername.c_str()));
469 FreeLibrary(handler);
470 bbtkMessage("package",2,
471 "Shared library ["<<libname
472 <<"] is not a valid bbtk package."
473 <<" Symbol ["<<getbbtkversion<<"] not found"<< std::endl);
478 if (getbbtkversion() != bbtk::GetVersion())
480 FreeLibrary(handler);
481 bbtkMessage("package",2,
482 "Shared library ["<<libname
483 <<"] was build with bbtk version "
485 <<" but the current program runs with version "
486 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
491 // Loads the Package get function
492 std::string getpackname(package_name);
493 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
494 getpack = (DLGetPackageFunction)(GetProcAddress(handler, getpackname.c_str()));
497 FreeLibrary(handler);
498 bbtkMessage("package",2,
499 "Shared library ["<<libname
500 <<"] is not a valid bbtk package."
501 <<" Symbol ["<<getpackname<<"] not found"<< std::endl);
505 // Loads the Package delete function
506 std::string delpackname(package_name);
507 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
508 delpack = (DLDeletePackageFunction)(GetProcAddress(handler, delpackname.c_str()));
511 FreeLibrary(handler);
512 bbtkMessage("package",2,
513 "Shared library ["<<libname
514 <<"] is not a valid bbtk package."
515 <<" Symbol ["<<delpackname<<"] not found"<< std::endl);
520 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
525 //==========================================================================
527 //==========================================================================
528 /// Loads a package from a dynamic library
529 Package::Pointer Package::CreateFromDynamicLibrary(const std::string& libname,
530 const std::string& pkgname,
531 const std::string& path)
533 bbtkDebugMessage("package",1,"==> Package::CreateFromDynamicLibrary("
534 <<libname<<")"<<std::endl);
536 DLGetPackageFunction gf;
537 DLDeletePackageFunction df;
538 DynamicLibraryHandler h = Package::OpenDynamicLibrary(libname,
541 if (h==0) return Package::Pointer();
542 Package::Pointer p = gf();
543 p->mDynamicLibraryHandler = h;
544 p->mDLDeletePackageFunction = df;
546 std::string separator =
547 ConfigurationFile::GetInstance().Get_file_separator ();
548 //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
549 std::string docreldoc =
550 separator + "bbdoc" + separator + pkgname + separator + "index.html";
552 ".." + separator + ".." + docreldoc;
553 std::string doc = path + separator + ".." + separator
554 + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
558 p->SetDocRelativeURL(reldoc);
560 bbtkDebugMessage("package",2,"<== Package::CreateFromDynamicLibrary("
561 <<libname<<") .. OK"<<std::endl);
564 //==========================================================================
569 //==========================================================================
570 /// UnLoads the package dynamic library (if any)
571 void Package::UnLoadDynamicLibrary(Package::WeakPointer pack, bool doit)
573 if (pack.expired() || (!pack.lock()->mDynamicLibraryHandler))
577 std::string packname = pack.lock()->GetName();
578 bbtkDebugMessage("package",5,"==> Package::UnLoadDynamicLibrary('"
582 if (!pack.lock()->GetBlackBoxMap().empty())
585 bbtkDebugMessage("package",5," Package not empty ... abort"
589 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
590 <<"BlackBoxMap not empty "
591 <<BBTK_INTERNAL_ERROR_MESSAGE);
596 if (pack.use_count()!=1)
598 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
599 <<"empty dl package with external refs"
600 <<BBTK_INTERNAL_ERROR_MESSAGE);
606 bbtkDebugMessage("package",5,"==> dynamic library for package '"
607 <<packname<<"' closed"
612 mReleasedDynamicallyLoadedPackages.insert(pack);
613 bbtkDebugMessage("package",1,"==> package '"<<packname
614 <<"' put in the 'to unload' list"
619 bbtkDebugMessage("package",5,"<== Package::UnLoadDynamicLibrary('"
624 //==========================================================================
626 //==========================================================================
627 /// UnLoads released packages that were loaded dynamically
628 /// see UnLoadDynamicLibrary and ReleaseBlackBoxDescriptor
629 void Package::UnLoadReleasedDynamicallyLoadedPackages()
631 bbtkDebugMessage("package",5,"==> Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
633 std::set<Package::WeakPointer>::iterator i;
636 if(mReleasedDynamicallyLoadedPackages.size()>0){
637 for (i=mReleasedDynamicallyLoadedPackages.begin();
638 i!=mReleasedDynamicallyLoadedPackages.end();
641 if (!i->expired()) UnLoad(*i);
645 bbtkDebugMessage("package",5,"<== Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
647 //==========================================================================
649 //==========================================================================
650 void Package::UnLoad(Package::WeakPointer pack)
652 std::string packname = pack.lock()->GetName();
653 bbtkDebugMessage("package",6,"==> Package::UnLoad("<<packname<<")"<<std::endl);
655 Package* p = pack.lock().get();
657 DynamicLibraryHandler h = p->mDynamicLibraryHandler;
659 // deletes the package
660 p->mDLDeletePackageFunction();
662 // closes the dl handler
663 #if defined(__GNUC__)
666 printf("EED Package::UnLoad ERROR %s\n", packname.c_str() );
667 bbtkWarning("Failed to close dynamic library for package '"<<packname
671 #elif defined(_WIN32)
675 bbtkDebugMessage("package",1,"==> dynamic library for package '"
676 <<packname<<"' closed"
678 bbtkDebugMessage("package",6," ... dynamic library unloaded"<<std::endl);
680 //==========================================================================
682 //==========================================================================
683 /// Creates an instance of a black box of type <type> with name <name>
684 BlackBox::Pointer Package::NewBlackBox(const std::string& type,
685 const std::string& name) const
687 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::NewBlackBox(\""<<type<<"\",\""<<name<<"\")"<<bbtkendl);
689 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(type);
690 if (i == mBlackBoxMap.end())
692 bbtkDebugDecTab("Kernel",8);
693 return BlackBox::Pointer();
695 BlackBox::Pointer bb =i->second->NewBlackBox(name);
696 bbtkDebugDecTab("Kernel",8);
700 //==========================================================================
704 //==========================================================================
705 /// Creates an instance of an adaptor of input type <typein> and
706 /// output type <typeout> with name <name>
707 BlackBox::Pointer Package::NewAdaptor(const DataInfo& typein,
708 const DataInfo& typeout,
709 const std::string& name) const
711 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
715 <<name<<"\")"<<bbtkendl);
717 AdaptorKey key(typein,typeout,
718 BlackBoxDescriptor::DEFAULT_ADAPTOR);
719 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
720 if (i == mAdaptorMap.end())
722 bbtkDebugDecTab("Kernel",8);
723 return BlackBox::Pointer();
725 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
726 bbtkDebugDecTab("Kernel",8);
730 //==========================================================================
732 //==========================================================================
733 /// Creates an instance of an adaptor of input type <typein> and
734 /// output type <typeout> with name <name>
735 BlackBox::Pointer Package::NewWidgetAdaptor(const DataInfo& typein,
736 const DataInfo& typeout,
737 const std::string& name) const
739 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
740 ">::NewWidgetAdaptor("
743 <<name<<"\")"<<bbtkendl);
745 AdaptorKey key(typein,typeout,
746 BlackBoxDescriptor::DEFAULT_GUI);
747 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
748 if (i == mAdaptorMap.end())
750 bbtkDebugDecTab("Kernel",8);
751 return BlackBox::Pointer();
753 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
754 bbtkDebugDecTab("Kernel",8);
758 //==========================================================================
762 //==========================================================================
763 /// Returns true is the package contains
764 /// an adaptor of input type <typein> and
765 /// output type <typeout>
766 /// If successfull then adaptor contains the black box type name
767 bool Package::FindWidgetAdaptor(const DataInfo& typein,
768 const DataInfo& typeout,
769 std::string& adaptor) const
771 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
772 ">::FindWidgetAdaptor("
774 <<typeout<<")"<<bbtkendl);
776 AdaptorKey key(/*typein*/
777 DataInfo(typeid(void),""),
779 BlackBoxDescriptor::DEFAULT_GUI);
780 // First try to find a single widget adaptor
781 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
782 if (i == mAdaptorMap.end())
784 bbtkDebugDecTab("Kernel",8);
787 adaptor = i->second.lock()->GetTypeName();
788 bbtkDebugDecTab("Kernel",8);
792 //==========================================================================
796 //==========================================================================
797 /// Returns true is the package contains
798 /// an adaptor of input type <typein> and
799 /// output type <typeout>
800 /// If successfull then adaptor contains the black box type name
801 bool Package::FindAdaptor(const DataInfo& typein,
802 const DataInfo& typeout,
803 std::string& adaptor) const
805 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
808 <<typeout<<")"<<bbtkendl);
810 AdaptorKey key(typein,typeout,
811 BlackBoxDescriptor::DEFAULT_ADAPTOR);
812 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
813 if (i == mAdaptorMap.end())
815 bbtkDebugDecTab("Kernel",8);
818 adaptor = i->second.lock()->GetTypeName();
819 bbtkDebugDecTab("Kernel",8);
823 //==========================================================================
826 //==========================================================================
827 /// Registers a black box descriptor in the package
828 bool Package::RegisterBlackBox(BlackBoxDescriptor::Pointer d)
830 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\")"<<std::endl);
832 BlackBoxMapType::iterator i = mBlackBoxMap.find(d->GetTypeName());
833 if (i!=mBlackBoxMap.end())
835 bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
836 <<d->GetTypeName()<<"> which is already in the package");
840 mBlackBoxMap[d->GetTypeName()] = d;
842 d->SetPackage(GetThisPointer<Package>());
844 // If it is a default adaptor, also register it in the adaptors map
845 if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
847 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);
849 TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
850 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
851 DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
852 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
853 AdaptorKey key(infoin,infoout,d->GetKind());
855 AdaptorMapType::const_iterator i;
856 i = mAdaptorMap.find(key);
857 if (i == mAdaptorMap.end())
859 mAdaptorMap[key] = d;
861 // If already an adaptor registered : error
864 if (i->second.lock()->GetTypeName() != d->GetTypeName())
866 bbtkError("Package <"<<GetName()<<
867 "> : trying to register black box <"
869 <<"> as default adaptor but there is already a default adaptor registered (<"
870 <<i->second.lock()->GetTypeName()<<">)");
874 // If it is a default adaptor, also register it in the adaptors map
875 else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
877 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is a widget adaptor, inserting it in adaptors map ..."<<std::endl);
879 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
880 DataInfo infoin(typeid(void),"");
881 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
882 AdaptorKey key(infoin,infoout,d->GetKind());
884 AdaptorMapType::const_iterator i;
885 i = mAdaptorMap.find(key);
886 if (i == mAdaptorMap.end())
888 mAdaptorMap[key] = d;
890 // If already an adaptor registered : error
893 if (i->second.lock()->GetTypeName() != d->GetTypeName())
895 bbtkError("Package <"<<GetName()<<
896 "> : trying to register black box <"
898 <<"> as default widget adaptor but there is already a default adaptor registered (<"
899 <<i->second.lock()->GetTypeName()<<">)");
905 bbtkDebugDecTab("Kernel",8);
909 //==========================================================================
911 //===================================================================
912 void Package::CheckBoxes() const
914 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
915 <<" ["<<GetName()<<"]"<<std::endl);
916 BlackBoxMapType::const_iterator i;
917 for (i=mBlackBoxMap.begin();
918 i!=mBlackBoxMap.end();
921 i->second->Check(true);
923 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
924 <<" ["<<GetName()<<"] ... OK"<<std::endl);
926 //===================================================================
929 //==========================================================================
930 /// Changes the name of a black box type
931 void Package::ChangeBlackBoxName( const std::string& oldname, const std::string& newname )
933 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::ChangeBlackBoxName(\""<<oldname<<"\",\""<<newname<<"\")"<<std::endl);
934 // Looking into the bb map
935 BlackBoxMapType::iterator i = mBlackBoxMap.find(oldname);
936 if (i == mBlackBoxMap.end())
938 bbtkDebugDecTab("Kernel",8);
939 bbtkError("ChangeBlackBoxName : The package <"<<GetName()<<"> does not contains the black box <"<<oldname<<">");
942 i->second->SetTypeName(newname);
943 mBlackBoxMap[newname] = i->second;
944 mBlackBoxMap.erase(i);
946 bbtkDebugDecTab("Kernel",8);
948 //==========================================================================
952 //==========================================================================
953 /// Displays the list of black boxes of the package
954 void Package::PrintBlackBoxes(bool description, bool adaptors) const
956 unsigned int lmax = 0;
957 std::vector<std::string> names;
958 std::vector<std::string> kinds;
959 std::vector<std::string> descrs;
961 BlackBoxMapType::const_iterator i;
962 for (i=mBlackBoxMap.begin();
963 i!=mBlackBoxMap.end();
967 ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) )
969 std::string name(" ");
970 name += i->second->GetTypeName();
971 names.push_back(name);
974 if ( i->second->GetKind() == BlackBoxDescriptor::ADAPTOR )
976 kind = std::string("[A]");
978 else if ( i->second->GetKind() ==
979 BlackBoxDescriptor::DEFAULT_ADAPTOR )
981 kind = std::string("[DA]");
983 kinds.push_back(kind);
985 unsigned int l = name.size()+kind.size();
986 if (l>lmax) lmax = l;
992 descr += i->second->GetDescription();
994 descrs.push_back(descr);
1000 offs.append(lmax+3,' ');
1001 std::vector<std::string>::iterator ni,ci,di;
1002 for (ni = names.begin(), ci = kinds.begin(), di = descrs.begin();
1003 ni != names.end(); ++ni, ++ci, ++di)
1006 space.append(lmax - ni->size() - ci->size(),' ');
1007 bbtkMessage("Help",1,*ni << space << *ci );
1009 unsigned int dmax = 75 - lmax;
1010 // while (d.size() > dmax )
1013 bbtkMessage("Help",1,d.substr(0,dmax) << "..." << std::endl);
1015 bbtkMessage("Help",1,d << std::endl);
1016 // d = d.substr(dmax,d.size());
1021 //==========================================================================
1023 //==========================================================================
1024 /// Displays the list of adaptors of the package
1025 void Package::PrintAdaptors(bool description) const
1027 BlackBoxMapType::const_iterator i;
1028 for (i=mBlackBoxMap.begin();
1029 i!=mBlackBoxMap.end();
1032 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD )
1034 bbtkMessage("Help",1,
1035 " "<<i->second->GetTypeName());
1036 if ( i->second->GetKind() ==
1037 BlackBoxDescriptor::DEFAULT_ADAPTOR )
1039 bbtkMessage("Help",1,
1044 bbtkMessage("Help",1,
1045 " : "<<i->second->GetDescription());
1048 bbtkMessage("Help",1,std::endl);
1052 AdaptorMapType::const_iterator i;
1053 for (i=mAdaptorMap.begin();
1054 i!=mAdaptorMap.end();
1057 bbtkMessage("Help",1,
1058 " "<<i->second->GetTypeName());
1061 bbtkMessage("Help",1,
1062 " : "<<i->second->GetDescription());
1065 bbtkMessage("Help",1,std::endl);
1069 //==========================================================================
1071 //==========================================================================
1072 /// Prints help on a black box
1073 void Package::HelpBlackBox(const std::string& name, bool full) const
1075 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1076 <<name<<"\")"<<bbtkendl);
1078 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1079 if (i == mBlackBoxMap.end())
1081 bbtkDebugDecTab("Kernel",8);
1082 bbtkError("The package <"<<GetName()<<"> does not contains the black box <"<<name<<">");
1084 // bbtkMessage("Help",1,"["<<GetName()<<"] ");
1085 i->second->GetHelp(full);
1086 bbtkDebugDecTab("Kernel",8);
1089 //==========================================================================
1092 //==========================================================================
1093 /// Returns true iff the package contains the box of name boxname
1094 bool Package::ContainsBlackBox(const std::string& name) const
1096 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1097 <<name<<"\")"<<bbtkendl);
1099 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1100 if (i == mBlackBoxMap.end())
1102 bbtkDebugDecTab("Kernel",8);
1105 bbtkDebugDecTab("Kernel",8);
1108 //==========================================================================
1112 //==========================================================================
1113 void Package::CreateHtmlPage(const std::string& filename,
1114 const std::string& caller,
1115 const std::string& source,
1116 const std::string& custom_header,
1117 const std::string& custom_title,
1120 bool relative_link ) const
1122 bbtkDebugMessageInc("Kernel",9,"Package<"<<GetName()<<">::CreateHtmlPage(\""
1123 <<filename<<"\")"<<bbtkendl);
1125 //---------------------
1128 s.open(filename.c_str());
1131 bbtkError("Package "<<GetName()<<" : CreateHtmlPage : could not open file '"<<filename<<"'");
1134 //----------------------
1136 std::string title = "BBTK Package "+GetName()+" "+GetVersion();
1138 if (custom_title.length() != 0) title = custom_title;
1140 s << "<html lang=\"en\">\n";
1142 s << "<title>" << title << "</title>\n";
1143 s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1144 s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1145 s << "<meta name=\"generator\" content=\"\">\n";
1146 s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1147 //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1148 s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1149 s << "pre.display { font-family:inherit }\n";
1150 s << "pre.format { font-family:inherit }\n";
1151 s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1152 s << "pre.smallformat { font-family:inherit; font-size:smaller }\n";
1153 s << "pre.smallexample { font-size:smaller }\n";
1154 s << "pre.smalllisp { font-size:smaller }\n";
1155 s << "span.sc { font-variant:small-caps }\n";
1156 s << "span.roman { font-family:serif; font-weight:normal; } \n";
1157 s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n";
1158 s << "--></style>\n";
1160 //----------------------
1162 //----------------------
1165 s << "<a name=\"Top\"></a>\n";
1167 //----------------------
1169 if ( custom_header.length() != 0)
1171 if ( custom_header != "none" )
1174 in.open(custom_header.c_str());
1177 bbtkError("Could not open file \""<<custom_header<<"\"");
1182 in.getline(buffer,512);
1183 std::string line(buffer);
1190 s << "<object data=\"" << custom_header
1191 << "\" type = \"text/html\"\"style=\"width: 1200px; height: 400px;\"> Warning: "
1192 << custom_header <<" could not be embedded.</object>\n";
1201 s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1202 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1203 s << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1204 << GetDescription() << "</TD></TR>\n";
1205 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1206 << GetAuthor() << "</TD></TR>\n";
1207 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1208 << GetCategory() << "</TD></TR>\n";
1209 s << "<TR><TD style='vertical-align: top;'><b> Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1210 << GetVersion() << "</TD></TR>\n";
1211 s << "<TR><TD style='vertical-align: top;'><b> bbtk Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1212 << bbtk::GetVersion() << "</TD></TR>\n";
1216 //-------------------
1217 // Table of contents
1219 // s << "<div class=\"contents\">\n";
1220 s << "<p><b> Black Boxes : </b>\n";
1223 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1225 BlackBoxMapType::const_iterator i;
1226 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i)
1228 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD)
1231 std::string name = i->second->GetTypeName();
1232 Utilities::html_format(name);
1233 std::string descr = i->second->GetDescription();
1234 //Utilities::html_format(descr);
1237 s << "<TD style='vertical-align: top;'>";
1238 s << " <a name=\"toc_"<<name
1239 <<"\" href=\"#"<<name<<"\">"
1242 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1251 //-------------------
1253 if (mAdaptorMap.size()>0)
1255 // s << "<div class=\"contents\">\n";
1256 s << "<p><b> Adaptors : </b>\n";
1259 // BlackBoxMapType::const_iterator i;
1260 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1261 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end();++i)
1263 if ( i->second->GetKind() == BlackBoxDescriptor::STANDARD)
1266 std::string name = i->second->GetTypeName();
1267 Utilities::html_format(name);
1268 std::string descr = i->second->GetDescription();
1271 s << "<TD style='vertical-align: top;'>";
1272 s << " <a name=\"toc_"<<name
1273 <<"\" href=\"#"<<name<<"\">"
1276 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1286 // s << "<div class=\"node\">\n";
1288 // s << "<p><hr>\n";
1289 // s << "<a name=\"Top\"></a>\n";
1290 // s << "Top: <a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
1291 // s << "Previous: <a rel="previous" accesskey="p" href="#dir">(dir)</a>,
1292 // s << "Up: <a rel="up" accesskey="u" href="#dir">(dir)</a>
1296 //----------------------
1299 //-------------------
1300 // Computes output directory from filename to pass it to
1301 // BlackBoxDescriptor::InsertHtmlHelp
1304 std::string::size_type slash_position = filename.find_last_of("/\\");
1307 if (slash_position != std::string::npos) {
1308 if (slash_position == 0)
1310 dir = filename.substr(0,slash_position);
1313 for (i=mBlackBoxMap.begin();
1314 i!=mBlackBoxMap.end();
1317 i->second->InsertHtmlHelp(s,detail,level,dir,relative_link);
1320 //----------------------
1325 ptm = gmtime ( &rawtime );
1328 s << "Automatically generated by <b>"<<caller<<"</b> "//from <b>"
1331 << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900
1332 << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1333 s << "</body></html>\n";
1335 //----------------------
1338 bbtkDebugDecTab("Kernel",9);
1340 //==========================================================================
1342 //==========================================================================
1343 std::string Package::GetObjectName() const
1345 return std::string("Package '")+mName+std::string("'");
1347 //==========================================================================
1349 //==========================================================================
1350 std::string Package::GetObjectInfo() const
1352 std::stringstream i;
1353 i << " - "<<mBlackBoxMap.size() << " boxes" << std::endl;
1354 if (mDynamicLibraryHandler)
1356 i<< " - Loaded from dynamic library"<<std::endl;
1360 //==========================================================================
1363 //==========================================================================
1364 size_t Package::GetObjectSize() const
1366 size_t s = Superclass::GetObjectSize();
1367 s += Package::GetObjectInternalSize();
1370 //==========================================================================
1371 //==========================================================================
1372 size_t Package::GetObjectInternalSize() const
1374 size_t s = sizeof(Package);
1377 //==========================================================================
1378 //==========================================================================
1379 size_t Package::GetObjectRecursiveSize() const
1381 size_t s = Superclass::GetObjectRecursiveSize();
1382 s += Package::GetObjectInternalSize();
1384 BlackBoxMapType::const_iterator i;
1385 for (i = mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i )
1387 s += i->second->GetObjectRecursiveSize();
1391 //==========================================================================
1393 //==========================================================================
1394 std::set<Package::WeakPointer>
1395 Package::mReleasedDynamicallyLoadedPackages;
1396 //==========================================================================