1 /*=========================================================================
4 Module: $RCSfile: bbtkPackage.cxx,v $
6 Date: $Date: 2008/05/14 10:26:29 $
7 Version: $Revision: 1.19 $
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.
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.
17 =========================================================================*/
20 *\brief Class bbtk::Package : registers black boxes descriptors and is able to create instances of the black boxes registered.
22 #include "bbtkPackage.h"
23 #include "bbtkMessageManager.h"
24 #include "bbtkConfigurationFile.h"
27 #include "bbtkUtilities.h"
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)
42 bbtkDebugMessage("object",1,"##> Package::New('"<<name<<"',...)"
44 Package::Pointer p = MakePointer(new Package(name,
49 bbtkDebugMessage("object",2,"<## Package::New('"<<name<<"',...)"
53 //==========================================================================
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)
63 mDynamicLibraryHandler(0),
66 mDescription(description),
69 bbtkDebugMessage("object",2,"==> Package::Package('"<<name<<"',...)"
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";
78 SetDocRelativeURL("Relative url not set");
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()
86 SetDocRelativeURL(relurl);
89 // std::cout << " url=["<<url<<"]"<<std::endl;
90 // std::cout << "relurl=["<<relurl<<"]"<<std::endl;
91 bbtkDebugMessage("object",2,"<== Package::Package('"<<name<<"',...) OK"
95 //==========================================================================
99 //==========================================================================
103 bbtkDebugMessage("object",2,"==> Package::~Package(\""<<mName<<"\")"<<bbtkendl);
104 bbtkDebugMessage("object",2,"<== Package::~Package(\""<<mName<<"\")"<<bbtkendl);
106 //==========================================================================
109 //==========================================================================
110 void PackageReleaseBlackBoxDescriptorInternal(Package::WeakPointer pack,
111 const std::string& descname)
113 // Try to release descriptor
114 std::string packname = pack.lock()->GetName();
116 bbtkDebugMessage("package",5,"--- Releasing descriptor '"
117 <<packname<<"::"<<descname<<"'"<<bbtkendl);
120 Package::BlackBoxMapType::iterator desc =
121 pack.lock()->GetBlackBoxMap().find(descname);
122 if (desc == pack.lock()->GetBlackBoxMap().end())
124 bbtkDebugMessage("package",5,
125 " Descriptor has already been released"
129 // bbtkDebugMessage("package",3,
130 // " Trying unreferencing it ... "<<std::endl);
131 BlackBoxDescriptor::WeakPointer pdesc = desc->second;
132 desc->second.reset();
133 // if it is dead : remove it
136 bbtkDebugMessage("package",2," ==> '"<<packname<<"::"<<descname<<"' Descriptor expired"<<bbtkendl);
139 bbtkDebugMessage("package",2,
140 " ... and caused its package death"
144 desc = pack.lock()->GetBlackBoxMap().find(descname);
145 if (desc != pack.lock()->GetBlackBoxMap().end())
146 pack.lock()->GetBlackBoxMap().erase(desc);
150 bbtkDebugMessage("package",5," ... Descriptor still alive ("
151 <<pdesc.use_count()<<" refs)"
153 pack.lock()->GetBlackBoxMap()[descname] = pdesc.lock();
156 //==========================================================================
159 //==========================================================================
161 void Package::Release(Package::WeakPointer pack)
163 std::string packname = pack.lock()->mName;
164 bbtkDebugMessage("package",1,"==> Package::Release('"<<
165 packname<<"')"<<bbtkendl);
167 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
168 long ndesc = pack.lock()->GetBlackBoxMap().size();
169 long nrefs = pack.use_count();
171 bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
172 <<ndesc<<" descr / dyn="
175 // A package is "free" from any external reference iff :
176 // i) It is not dynamically loaded and nrefs == ndesc
177 // (each desc references its package) or
178 // ii) It is dynamically loaded and nrefs == ndesc + 1
179 // (A dynamic library holds a static pointer on the package it contains
180 // which is allocated when the PACKAGENAMEGetPackage() func is called,
181 // and descallocated (reset) by PACKAGENAMEDeletePackage())
182 if (nrefs == ndesc + dyn)
184 bbtkDebugMessage("package",5,
185 " -> No more external ref : checking descriptors"
187 // We must take care that removing refs on descriptors
188 // can lead to their deletion which can in turn unref
189 // internal boxes which can release their descriptors hence
190 // call Package::ReleaseBlackBoxDescriptor
191 // As a consequence during descriptors release :
192 // 1) The map can change dynamically : we cannot iterate over it
193 // as any iterator can become invalid
194 // 2) The package can auto-destruct : we must test its existence
195 // after each release
196 // We must also take care of not locking the package pointer
197 // or any ref count check in Package::ReleaseBlackBoxDescriptor
200 // The list of descriptors names at start
201 std::vector<std::string> descnamelist;
202 BlackBoxMapType::iterator i;
203 for (i=pack.lock()->mBlackBoxMap.begin();
204 i!= pack.lock()->mBlackBoxMap.end();
206 descnamelist.push_back(i->first);
208 // Iterator over the initial names
209 std::vector<std::string>::iterator descname;
210 for (descname=descnamelist.begin();
211 descname!=descnamelist.end();
214 // Is package still alive ?
217 bbtkDebugMessage("package",1,"--- Package::Release('"<<
219 <<"') : package expired during release : bailing out"<<bbtkendl);
223 PackageReleaseBlackBoxDescriptorInternal(pack,*descname);
228 UnLoadDynamicLibrary(pack);
229 // Unload orphan dl packages
230 Package::UnLoadReleasedDynamicallyLoadedPackages();
237 bbtkDebugMessage("package",2,"<== Package::Release('"<<
238 packname<<"')"<<bbtkendl);
241 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
242 long ndesc = pack.lock()->GetBlackBoxMap().size();
243 long nrefs = pack.use_count();
245 bbtkDebugMessage("package",1," ... Package still alive ("
247 <<ndesc<<" descr / dyn="
248 <<dyn<<")"<<std::endl);
252 bbtkDebugMessage("package",1," ... Package has been released"
256 //==========================================================================
258 //==========================================================================
259 /// "Releases" the package
260 /// Signals the package that it can free the given descriptor
261 /// if they are no more used and free itself if it is no
263 /// Note : Any non-weak pointer on the package must have been freed
264 void Package::ReleaseBlackBoxDescriptor(Package::WeakPointer pack,
265 BlackBoxDescriptor::WeakPointer descr)
267 std::string packname = pack.lock()->mName;
268 std::string dname = descr.lock()->GetTypeName();
269 bbtkDebugMessage("package",3,"==> Package::ReleaseBlackBoxDescriptor('"<<
270 packname<<"','"<<dname<<"') : refs="
271 <<descr.use_count()<<bbtkendl);
273 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
274 long ndesc = pack.lock()->GetBlackBoxMap().size();
275 long nrefs = pack.use_count();
277 bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
278 <<ndesc<<" descr / dynamically loaded = "
281 // A package is "free" from any external reference iff :
282 // i) It is not dynamically loaded and nrefs == ndesc
283 // (each desc references its package) or
284 // ii) It is dynamically loaded and nrefs == ndesc + 1
285 // (A dynamic library holds a static pointer on the package it contains
286 // which is allocated when the PACKAGENAMEGetPackage() func is called,
287 // and descallocated (reset) by PACKAGENAMEDeletePackage())
288 if (nrefs == ndesc + dyn)
290 PackageReleaseBlackBoxDescriptorInternal(pack,dname);
293 // If the package is released and dynamically loaded
294 // then put it in the static list mReleasedDynamicallyLoadedPackages
295 UnLoadDynamicLibrary(pack,false);
297 bbtkDebugMessage("package",4,"<== Package::ReleaseBlackBoxDescriptor('"<<
298 packname<<"','"<<dname<<"'): refs="
299 <<descr.use_count()<<bbtkendl);
303 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
304 long ndesc = pack.lock()->GetBlackBoxMap().size();
305 long nrefs = pack.use_count();
307 bbtkDebugMessage("package",3," ... Package still alive ("
309 <<ndesc<<" descr / dyn="
310 <<dyn<<")"<<std::endl);
314 bbtkDebugMessage("package",3," ... Package has been released"
319 //==========================================================================
321 //==========================================================================
322 /// Opens a dynamic library which contains a bbtk package
323 /// Returns the handler
324 /// Load the package management symbols from the lib
325 /// returns false if a problem occured hence can be used
326 /// to test that a dyn lib is a valid bbtk package lib
327 /// NB : The BBTK version exported from the library
328 /// is tested against the current bbtk version
329 DynamicLibraryHandler Package::OpenDynamicLibrary
330 ( const std::string& libname,
331 const std::string& package_name,
332 DLGetPackageFunction& getpack,
333 DLDeletePackageFunction& delpack)
335 bbtkDebugMessage("package",3,"==> Package::OpenDynamicLibrary("
336 <<libname<<")"<<std::endl);
337 #if defined(__GNUC__)
341 handler = dlopen(libname.c_str(),
342 BBTK_RTLD_TIME | BBTK_RTLD_SCOPE );
345 bbtkMessage("package",2,
346 "Could not open shared library [" <<libname<<"] : "
347 <<dlerror() << std::endl);
351 bbtkDebugMessage("package",3,"* Shared lib ["<<libname<<"] open"<<std::endl);
353 // Loads the Package bbtk version function
354 std::string getvername(package_name);
356 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
357 DLGetPackageBBTKVersionFunction getbbtkversion
358 = (DLGetPackageBBTKVersionFunction)(dlsym(handler,getvername.c_str()));
361 bbtkDebugMessage("package",3,"***"<<std::endl);
362 bbtkMessage("package",2,
363 "Shared library ["<<libname
364 <<"] is not a valid bbtk package."
365 <<" Symbol ["<<getvername<<"] :"<<dlerror()<< std::endl);
370 bbtkDebugMessage("package",3,"* Symbol ["<<getvername
371 <<"] found"<<std::endl);
373 if (getbbtkversion() != bbtk::GetVersion())
375 bbtkMessage("package",2,
376 "Shared library ["<<libname
377 <<"] was build with bbtk version "
379 <<" but the current program runs with version "
380 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
386 bbtkDebugMessage("package",3,"* Package bbtk version '"<<getbbtkversion()<<"' matches"<<std::endl);
387 // Loads the Package get function
388 std::string getpackname(package_name);
389 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
390 getpack = (DLGetPackageFunction)(dlsym(handler, getpackname.c_str()));
393 bbtkMessage("package",2,
394 "Shared library ["<<libname
395 <<"] is not a valid bbtk package."
396 <<" Symbol ["<<getpackname<<"] :"<<dlerror()<< std::endl);
401 bbtkDebugMessage("package",3,"* Symbol ["<<getpackname<<"] found"<<std::endl);
402 // Loads the Package delete function
404 std::string delpackname(package_name);
405 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
406 delpack = (DLDeletePackageFunction)(dlsym(handler, delpackname.c_str()));
409 bbtkMessage("package",2,
410 "Shared library ["<<libname
411 <<"] is not a valid bbtk package."
412 <<" Symbol ["<<delpackname<<"] :"<<dlerror()<< std::endl);
416 bbtkDebugMessage("package",3,"* Symbol ["<<delpackname<<"] found"<<std::endl);
417 #elif defined(_WIN32)
423 handler = LoadLibrary(libname.c_str());
426 bbtkMessage("package",2,
427 "Could not open shared library [" <<libname<<"]"
432 // Loads the Package bbtk version function
433 std::string getvername(package_name);
435 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
436 DLGetPackageBBTKVersionFunction getbbtkversion
437 = (DLGetPackageBBTKVersionFunction)(GetProcAddress(handler,
438 getvername.c_str()));
441 FreeLibrary(handler);
442 bbtkMessage("package",2,
443 "Shared library ["<<libname
444 <<"] is not a valid bbtk package."
445 <<" Symbol ["<<getbbtkversion<<"] not found"<< std::endl);
450 if (getbbtkversion() != bbtk::GetVersion())
452 FreeLibrary(handler);
453 bbtkMessage("package",2,
454 "Shared library ["<<libname
455 <<"] was build with bbtk version "
457 <<" but the current program runs with version "
458 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
463 // Loads the Package get function
464 std::string getpackname(package_name);
465 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
466 getpack = (DLGetPackageFunction)(GetProcAddress(handler, getpackname.c_str()));
469 FreeLibrary(handler);
470 bbtkMessage("package",2,
471 "Shared library ["<<libname
472 <<"] is not a valid bbtk package."
473 <<" Symbol ["<<getpackname<<"] not found"<< std::endl);
477 // Loads the Package delete function
478 std::string delpackname(package_name);
479 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
480 delpack = (DLDeletePackageFunction)(GetProcAddress(handler, delpackname.c_str()));
483 FreeLibrary(handler);
484 bbtkMessage("package",2,
485 "Shared library ["<<libname
486 <<"] is not a valid bbtk package."
487 <<" Symbol ["<<delpackname<<"] not found"<< std::endl);
492 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
497 //==========================================================================
499 //==========================================================================
500 /// Loads a package from a dynamic library
501 Package::Pointer Package::CreateFromDynamicLibrary(const std::string& libname,
502 const std::string& pkgname,
503 const std::string& path)
505 bbtkDebugMessage("package",1,"==> Package::CreateFromDynamicLibrary("
506 <<libname<<")"<<std::endl);
508 DLGetPackageFunction gf;
509 DLDeletePackageFunction df;
510 DynamicLibraryHandler h = Package::OpenDynamicLibrary(libname,
513 if (h==0) return Package::Pointer();
514 Package::Pointer p = gf();
515 p->mDynamicLibraryHandler = h;
516 p->mDLDeletePackageFunction = df;
518 std::string separator =
519 ConfigurationFile::GetInstance().Get_file_separator ();
520 //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
521 std::string docreldoc =
522 separator + "bbdoc" + separator + pkgname + separator + "index.html";
524 ".." + separator + ".." + docreldoc;
525 std::string doc = path + separator + ".." + separator
526 + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
530 p->SetDocRelativeURL(reldoc);
532 bbtkDebugMessage("package",2,"<== Package::CreateFromDynamicLibrary("
533 <<libname<<") .. OK"<<std::endl);
536 //==========================================================================
541 //==========================================================================
542 /// UnLoads the package dynamic library (if any)
543 void Package::UnLoadDynamicLibrary(Package::WeakPointer pack, bool doit)
545 if (pack.expired() || (!pack.lock()->mDynamicLibraryHandler))
549 std::string packname = pack.lock()->GetName();
550 bbtkDebugMessage("package",5,"==> Package::UnLoadDynamicLibrary('"
554 if (!pack.lock()->GetBlackBoxMap().empty())
557 bbtkDebugMessage("package",5," Package not empty ... abort"
561 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
562 <<"BlackBoxMap not empty "
563 <<BBTK_INTERNAL_ERROR_MESSAGE);
568 if (pack.use_count()!=1)
570 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
571 <<"empty dl package with external refs"
572 <<BBTK_INTERNAL_ERROR_MESSAGE);
578 bbtkDebugMessage("package",5,"==> dynamic library for package '"
579 <<packname<<"' closed"
584 mReleasedDynamicallyLoadedPackages.insert(pack);
585 bbtkDebugMessage("package",1,"==> package '"<<packname
586 <<"' put in the 'to unload' list"
591 bbtkDebugMessage("package",5,"<== Package::UnLoadDynamicLibrary('"
596 //==========================================================================
598 //==========================================================================
599 /// UnLoads released packages that were loaded dynamically
600 /// see UnLoadDynamicLibrary and ReleaseBlackBoxDescriptor
601 void Package::UnLoadReleasedDynamicallyLoadedPackages()
603 bbtkDebugMessage("package",5,"==> Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
605 std::set<Package::WeakPointer>::iterator i;
606 for (i=mReleasedDynamicallyLoadedPackages.begin();
607 i!=mReleasedDynamicallyLoadedPackages.end();
610 if (!i->expired()) UnLoad(*i);
612 bbtkDebugMessage("package",5,"<== Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
614 //==========================================================================
616 //==========================================================================
617 void Package::UnLoad(Package::WeakPointer pack)
619 std::string packname = pack.lock()->GetName();
620 bbtkDebugMessage("package",6,"==> Package::UnLoad("<<packname<<")"<<std::endl);
622 Package* p = pack.lock().get();
624 DynamicLibraryHandler h = p->mDynamicLibraryHandler;
626 // deletes the package
627 p->mDLDeletePackageFunction();
629 // closes the dl handler
630 #if defined(__GNUC__)
632 #elif defined(_WIN32)
636 bbtkDebugMessage("package",1,"==> dynamic library for package '"
637 <<packname<<"' closed"
639 bbtkDebugMessage("package",6," ... dynamic library unloaded"<<std::endl);
641 //==========================================================================
643 //==========================================================================
644 /// Creates an instance of a black box of type <type> with name <name>
645 BlackBox::Pointer Package::NewBlackBox(const std::string& type,
646 const std::string& name) const
648 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::NewBlackBox(\""<<type<<"\",\""<<name<<"\")"<<bbtkendl);
650 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(type);
651 if (i == mBlackBoxMap.end())
653 bbtkDebugDecTab("Kernel",8);
654 return BlackBox::Pointer();
656 BlackBox::Pointer bb =i->second->NewBlackBox(name);
657 bbtkDebugDecTab("Kernel",8);
661 //==========================================================================
665 //==========================================================================
666 /// Creates an instance of an adaptor of input type <typein> and
667 /// output type <typeout> with name <name>
668 BlackBox::Pointer Package::NewAdaptor(const DataInfo& typein,
669 const DataInfo& typeout,
670 const std::string& name) const
672 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
676 <<name<<"\")"<<bbtkendl);
678 AdaptorKey key(typein,typeout,
679 BlackBoxDescriptor::DEFAULT_ADAPTOR);
680 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
681 if (i == mAdaptorMap.end())
683 bbtkDebugDecTab("Kernel",8);
684 return BlackBox::Pointer();
686 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
687 bbtkDebugDecTab("Kernel",8);
691 //==========================================================================
693 //==========================================================================
694 /// Creates an instance of an adaptor of input type <typein> and
695 /// output type <typeout> with name <name>
696 BlackBox::Pointer Package::NewWidgetAdaptor(const DataInfo& typein,
697 const DataInfo& typeout,
698 const std::string& name) const
700 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
701 ">::NewWidgetAdaptor("
704 <<name<<"\")"<<bbtkendl);
706 AdaptorKey key(typein,typeout,
707 BlackBoxDescriptor::DEFAULT_GUI);
708 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
709 if (i == mAdaptorMap.end())
711 bbtkDebugDecTab("Kernel",8);
712 return BlackBox::Pointer();
714 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
715 bbtkDebugDecTab("Kernel",8);
719 //==========================================================================
723 //==========================================================================
724 /// Returns true is the package contains
725 /// an adaptor of input type <typein> and
726 /// output type <typeout>
727 /// If successfull then adaptor contains the black box type name
728 bool Package::FindWidgetAdaptor(const DataInfo& typein,
729 const DataInfo& typeout,
730 std::string& adaptor) const
732 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
733 ">::FindWidgetAdaptor("
735 <<typeout<<")"<<bbtkendl);
737 AdaptorKey key(/*typein*/
738 DataInfo(typeid(void),""),
740 BlackBoxDescriptor::DEFAULT_GUI);
741 // First try to find a single widget adaptor
742 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
743 if (i == mAdaptorMap.end())
745 bbtkDebugDecTab("Kernel",8);
748 adaptor = i->second.lock()->GetTypeName();
749 bbtkDebugDecTab("Kernel",8);
753 //==========================================================================
757 //==========================================================================
758 /// Returns true is the package contains
759 /// an adaptor of input type <typein> and
760 /// output type <typeout>
761 /// If successfull then adaptor contains the black box type name
762 bool Package::FindAdaptor(const DataInfo& typein,
763 const DataInfo& typeout,
764 std::string& adaptor) const
766 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
769 <<typeout<<")"<<bbtkendl);
771 AdaptorKey key(typein,typeout,
772 BlackBoxDescriptor::DEFAULT_ADAPTOR);
773 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
774 if (i == mAdaptorMap.end())
776 bbtkDebugDecTab("Kernel",8);
779 adaptor = i->second.lock()->GetTypeName();
780 bbtkDebugDecTab("Kernel",8);
784 //==========================================================================
787 //==========================================================================
788 /// Registers a black box descriptor in the package
789 bool Package::RegisterBlackBox(BlackBoxDescriptor::Pointer d)
791 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\")"<<std::endl);
793 BlackBoxMapType::iterator i = mBlackBoxMap.find(d->GetTypeName());
794 if (i!=mBlackBoxMap.end())
796 bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
797 <<d->GetTypeName()<<"> which is already in the package");
801 mBlackBoxMap[d->GetTypeName()] = d;
803 d->SetPackage(GetThisPointer<Package>());
805 // If it is a default adaptor, also register it in the adaptors map
806 if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
808 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);
810 TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
811 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
812 DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
813 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
814 AdaptorKey key(infoin,infoout,d->GetKind());
816 AdaptorMapType::const_iterator i;
817 i = mAdaptorMap.find(key);
818 if (i == mAdaptorMap.end())
820 mAdaptorMap[key] = d;
822 // If already an adaptor registered : error
825 if (i->second.lock()->GetTypeName() != d->GetTypeName())
827 bbtkError("Package <"<<GetName()<<
828 "> : trying to register black box <"
830 <<"> as default adaptor but there is already a default adaptor registered (<"
831 <<i->second.lock()->GetTypeName()<<">)");
835 // If it is a default adaptor, also register it in the adaptors map
836 else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
838 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is a widget adaptor, inserting it in adaptors map ..."<<std::endl);
840 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
841 DataInfo infoin(typeid(void),"");
842 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
843 AdaptorKey key(infoin,infoout,d->GetKind());
845 AdaptorMapType::const_iterator i;
846 i = mAdaptorMap.find(key);
847 if (i == mAdaptorMap.end())
849 mAdaptorMap[key] = d;
851 // If already an adaptor registered : error
854 if (i->second.lock()->GetTypeName() != d->GetTypeName())
856 bbtkError("Package <"<<GetName()<<
857 "> : trying to register black box <"
859 <<"> as default widget adaptor but there is already a default adaptor registered (<"
860 <<i->second.lock()->GetTypeName()<<">)");
866 bbtkDebugDecTab("Kernel",8);
870 //==========================================================================
872 //===================================================================
873 void Package::CheckBoxes() const
875 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
876 <<" ["<<GetName()<<"]"<<std::endl);
877 BlackBoxMapType::const_iterator i;
878 for (i=mBlackBoxMap.begin();
879 i!=mBlackBoxMap.end();
882 i->second->Check(true);
884 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
885 <<" ["<<GetName()<<"] ... OK"<<std::endl);
887 //===================================================================
890 //==========================================================================
891 /// Changes the name of a black box type
892 void Package::ChangeBlackBoxName( const std::string& oldname, const std::string& newname )
894 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::ChangeBlackBoxName(\""<<oldname<<"\",\""<<newname<<"\")"<<std::endl);
895 // Looking into the bb map
896 BlackBoxMapType::iterator i = mBlackBoxMap.find(oldname);
897 if (i == mBlackBoxMap.end())
899 bbtkDebugDecTab("Kernel",8);
900 bbtkError("ChangeBlackBoxName : The package <"<<GetName()<<"> does not contains the black box <"<<oldname<<">");
903 i->second->SetTypeName(newname);
904 mBlackBoxMap[newname] = i->second;
905 mBlackBoxMap.erase(i);
907 bbtkDebugDecTab("Kernel",8);
909 //==========================================================================
913 //==========================================================================
914 /// Displays the list of black boxes of the package
915 void Package::PrintBlackBoxes(bool description, bool adaptors) const
917 unsigned int lmax = 0;
918 std::vector<std::string> names;
919 std::vector<std::string> kinds;
920 std::vector<std::string> descrs;
922 BlackBoxMapType::const_iterator i;
923 for (i=mBlackBoxMap.begin();
924 i!=mBlackBoxMap.end();
928 ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) )
930 std::string name(" ");
931 name += i->second->GetTypeName();
932 names.push_back(name);
935 if ( i->second->GetKind() == BlackBoxDescriptor::ADAPTOR )
937 kind = std::string("[A]");
939 else if ( i->second->GetKind() ==
940 BlackBoxDescriptor::DEFAULT_ADAPTOR )
942 kind = std::string("[DA]");
944 kinds.push_back(kind);
946 unsigned int l = name.size()+kind.size();
947 if (l>lmax) lmax = l;
953 descr += i->second->GetDescription();
955 descrs.push_back(descr);
961 offs.append(lmax+3,' ');
962 std::vector<std::string>::iterator ni,ci,di;
963 for (ni = names.begin(), ci = kinds.begin(), di = descrs.begin();
964 ni != names.end(); ++ni, ++ci, ++di)
967 space.append(lmax - ni->size() - ci->size(),' ');
968 bbtkMessage("Help",1,*ni << space << *ci );
970 unsigned int dmax = 75 - lmax;
971 // while (d.size() > dmax )
974 bbtkMessage("Help",1,d.substr(0,dmax) << "..." << std::endl);
976 bbtkMessage("Help",1,d << std::endl);
977 // d = d.substr(dmax,d.size());
982 //==========================================================================
984 //==========================================================================
985 /// Displays the list of adaptors of the package
986 void Package::PrintAdaptors(bool description) const
988 BlackBoxMapType::const_iterator i;
989 for (i=mBlackBoxMap.begin();
990 i!=mBlackBoxMap.end();
993 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD )
995 bbtkMessage("Help",1,
996 " "<<i->second->GetTypeName());
997 if ( i->second->GetKind() ==
998 BlackBoxDescriptor::DEFAULT_ADAPTOR )
1000 bbtkMessage("Help",1,
1005 bbtkMessage("Help",1,
1006 " : "<<i->second->GetDescription());
1009 bbtkMessage("Help",1,std::endl);
1013 AdaptorMapType::const_iterator i;
1014 for (i=mAdaptorMap.begin();
1015 i!=mAdaptorMap.end();
1018 bbtkMessage("Help",1,
1019 " "<<i->second->GetTypeName());
1022 bbtkMessage("Help",1,
1023 " : "<<i->second->GetDescription());
1026 bbtkMessage("Help",1,std::endl);
1030 //==========================================================================
1032 //==========================================================================
1033 /// Prints help on a black box
1034 void Package::HelpBlackBox(const std::string& name, bool full) const
1036 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1037 <<name<<"\")"<<bbtkendl);
1039 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1040 if (i == mBlackBoxMap.end())
1042 bbtkDebugDecTab("Kernel",8);
1043 bbtkError("The package <"<<GetName()<<"> does not contains the black box <"<<name<<">");
1045 // bbtkMessage("Help",1,"["<<GetName()<<"] ");
1046 i->second->GetHelp(full);
1047 bbtkDebugDecTab("Kernel",8);
1050 //==========================================================================
1053 //==========================================================================
1054 /// Returns true iff the package contains the box of name boxname
1055 bool Package::ContainsBlackBox(const std::string& name) const
1057 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1058 <<name<<"\")"<<bbtkendl);
1060 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1061 if (i == mBlackBoxMap.end())
1063 bbtkDebugDecTab("Kernel",8);
1066 bbtkDebugDecTab("Kernel",8);
1069 //==========================================================================
1073 //==========================================================================
1074 void Package::CreateHtmlPage(const std::string& filename,
1075 const std::string& caller,
1076 const std::string& source,
1077 const std::string& custom_header,
1078 const std::string& custom_title,
1081 bool relative_link ) const
1083 bbtkDebugMessageInc("Kernel",9,"Package<"<<GetName()<<">::CreateHtmlPage(\""
1084 <<filename<<"\")"<<bbtkendl);
1086 //---------------------
1089 s.open(filename.c_str());
1092 bbtkError("Package "<<GetName()<<" : CreateHtmlPage : could not open file '"<<filename<<"'");
1095 //----------------------
1097 std::string title = "BBTK Package "+GetName()+" "+GetVersion();
1099 if (custom_title.length() != 0) title = custom_title;
1101 s << "<html lang=\"en\">\n";
1103 s << "<title>" << title << "</title>\n";
1104 s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1105 s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1106 s << "<meta name=\"generator\" content=\"\">\n";
1107 s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1108 //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1109 s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1110 s << "pre.display { font-family:inherit }\n";
1111 s << "pre.format { font-family:inherit }\n";
1112 s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1113 s << "pre.smallformat { font-family:inherit; font-size:smaller }\n";
1114 s << "pre.smallexample { font-size:smaller }\n";
1115 s << "pre.smalllisp { font-size:smaller }\n";
1116 s << "span.sc { font-variant:small-caps }\n";
1117 s << "span.roman { font-family:serif; font-weight:normal; } \n";
1118 s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n";
1119 s << "--></style>\n";
1121 //----------------------
1123 //----------------------
1126 s << "<a name=\"Top\"></a>\n";
1128 //----------------------
1130 if ( custom_header.length() != 0)
1132 if ( custom_header != "none" )
1135 in.open(custom_header.c_str());
1138 bbtkError("Could not open file \""<<custom_header<<"\"");
1143 in.getline(buffer,512);
1144 std::string line(buffer);
1151 s << "<object data=\"" << custom_header
1152 << "\" type = \"text/html\"\"style=\"width: 1200px; height: 400px;\"> Warning: "
1153 << custom_header <<" could not be embedded.</object>\n";
1162 s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1163 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1164 s << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1165 << GetDescription() << "</TD></TR>\n";
1166 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1167 << GetAuthor() << "</TD></TR>\n";
1168 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1169 << GetCategory() << "</TD></TR>\n";
1170 s << "<TR><TD style='vertical-align: top;'><b> Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1171 << GetVersion() << "</TD></TR>\n";
1172 s << "<TR><TD style='vertical-align: top;'><b> bbtk Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1173 << bbtk::GetVersion() << "</TD></TR>\n";
1177 //-------------------
1178 // Table of contents
1180 // s << "<div class=\"contents\">\n";
1181 s << "<p><b> Black Boxes : </b>\n";
1184 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1186 BlackBoxMapType::const_iterator i;
1187 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i)
1189 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD)
1192 std::string name = i->second->GetTypeName();
1193 Utilities::html_format(name);
1194 std::string descr = i->second->GetDescription();
1195 //Utilities::html_format(descr);
1198 s << "<TD style='vertical-align: top;'>";
1199 s << " <a name=\"toc_"<<name
1200 <<"\" href=\"#"<<name<<"\">"
1203 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1212 //-------------------
1214 if (mAdaptorMap.size()>0)
1216 // s << "<div class=\"contents\">\n";
1217 s << "<p><b> Adaptors : </b>\n";
1220 // BlackBoxMapType::const_iterator i;
1221 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1222 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end();++i)
1224 if ( i->second->GetKind() == BlackBoxDescriptor::STANDARD)
1227 std::string name = i->second->GetTypeName();
1228 Utilities::html_format(name);
1229 std::string descr = i->second->GetDescription();
1232 s << "<TD style='vertical-align: top;'>";
1233 s << " <a name=\"toc_"<<name
1234 <<"\" href=\"#"<<name<<"\">"
1237 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1247 // s << "<div class=\"node\">\n";
1249 // s << "<p><hr>\n";
1250 // s << "<a name=\"Top\"></a>\n";
1251 // s << "Top: <a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
1252 // s << "Previous: <a rel="previous" accesskey="p" href="#dir">(dir)</a>,
1253 // s << "Up: <a rel="up" accesskey="u" href="#dir">(dir)</a>
1257 //----------------------
1260 //-------------------
1261 // Computes output directory from filename to pass it to
1262 // BlackBoxDescriptor::InsertHtmlHelp
1265 std::string::size_type slash_position = filename.find_last_of("/\\");
1268 if (slash_position != std::string::npos) {
1269 if (slash_position == 0)
1271 dir = filename.substr(0,slash_position);
1274 for (i=mBlackBoxMap.begin();
1275 i!=mBlackBoxMap.end();
1278 i->second->InsertHtmlHelp(s,detail,level,dir,relative_link);
1281 //----------------------
1286 ptm = gmtime ( &rawtime );
1289 s << "Automatically generated by <b>"<<caller<<"</b> "//from <b>"
1292 << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900
1293 << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1294 s << "</body></html>\n";
1296 //----------------------
1299 bbtkDebugDecTab("Kernel",9);
1301 //==========================================================================
1303 //==========================================================================
1304 std::string Package::GetObjectName() const
1306 return std::string("Package '")+mName+std::string("'");
1308 //==========================================================================
1310 //==========================================================================
1311 std::string Package::GetObjectInfo() const
1313 std::stringstream i;
1314 i << " - "<<mBlackBoxMap.size() << " boxes" << std::endl;
1315 if (mDynamicLibraryHandler)
1317 i<< " - Loaded from dynamic library"<<std::endl;
1321 //==========================================================================
1324 //==========================================================================
1325 size_t Package::GetObjectSize() const
1327 size_t s = Superclass::GetObjectSize();
1328 s += Package::GetObjectInternalSize();
1331 //==========================================================================
1332 //==========================================================================
1333 size_t Package::GetObjectInternalSize() const
1335 size_t s = sizeof(Package);
1338 //==========================================================================
1339 //==========================================================================
1340 size_t Package::GetObjectRecursiveSize() const
1342 size_t s = Superclass::GetObjectRecursiveSize();
1343 s += Package::GetObjectInternalSize();
1345 BlackBoxMapType::const_iterator i;
1346 for (i = mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i )
1348 s += i->second->GetObjectRecursiveSize();
1352 //==========================================================================
1354 //==========================================================================
1355 std::set<Package::WeakPointer>
1356 Package::mReleasedDynamicallyLoadedPackages;
1357 //==========================================================================