1 /*=========================================================================
4 Module: $RCSfile: bbtkPackage.cxx,v $
6 Date: $Date: 2008/06/10 19:19:42 $
7 Version: $Revision: 1.20 $
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<<"]"
429 DWORD dwErrorCode = 0;
430 dwErrorCode = GetLastError();
431 bbtkMessage("package",2,
432 "Windows Error: [" << dwErrorCode <<"]"
438 // Loads the Package bbtk version function
439 std::string getvername(package_name);
441 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
442 DLGetPackageBBTKVersionFunction getbbtkversion
443 = (DLGetPackageBBTKVersionFunction)(GetProcAddress(handler,
444 getvername.c_str()));
447 FreeLibrary(handler);
448 bbtkMessage("package",2,
449 "Shared library ["<<libname
450 <<"] is not a valid bbtk package."
451 <<" Symbol ["<<getbbtkversion<<"] not found"<< std::endl);
456 if (getbbtkversion() != bbtk::GetVersion())
458 FreeLibrary(handler);
459 bbtkMessage("package",2,
460 "Shared library ["<<libname
461 <<"] was build with bbtk version "
463 <<" but the current program runs with version "
464 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
469 // Loads the Package get function
470 std::string getpackname(package_name);
471 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
472 getpack = (DLGetPackageFunction)(GetProcAddress(handler, getpackname.c_str()));
475 FreeLibrary(handler);
476 bbtkMessage("package",2,
477 "Shared library ["<<libname
478 <<"] is not a valid bbtk package."
479 <<" Symbol ["<<getpackname<<"] not found"<< std::endl);
483 // Loads the Package delete function
484 std::string delpackname(package_name);
485 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
486 delpack = (DLDeletePackageFunction)(GetProcAddress(handler, delpackname.c_str()));
489 FreeLibrary(handler);
490 bbtkMessage("package",2,
491 "Shared library ["<<libname
492 <<"] is not a valid bbtk package."
493 <<" Symbol ["<<delpackname<<"] not found"<< std::endl);
498 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
503 //==========================================================================
505 //==========================================================================
506 /// Loads a package from a dynamic library
507 Package::Pointer Package::CreateFromDynamicLibrary(const std::string& libname,
508 const std::string& pkgname,
509 const std::string& path)
511 bbtkDebugMessage("package",1,"==> Package::CreateFromDynamicLibrary("
512 <<libname<<")"<<std::endl);
514 DLGetPackageFunction gf;
515 DLDeletePackageFunction df;
516 DynamicLibraryHandler h = Package::OpenDynamicLibrary(libname,
519 if (h==0) return Package::Pointer();
520 Package::Pointer p = gf();
521 p->mDynamicLibraryHandler = h;
522 p->mDLDeletePackageFunction = df;
524 std::string separator =
525 ConfigurationFile::GetInstance().Get_file_separator ();
526 //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
527 std::string docreldoc =
528 separator + "bbdoc" + separator + pkgname + separator + "index.html";
530 ".." + separator + ".." + docreldoc;
531 std::string doc = path + separator + ".." + separator
532 + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
536 p->SetDocRelativeURL(reldoc);
538 bbtkDebugMessage("package",2,"<== Package::CreateFromDynamicLibrary("
539 <<libname<<") .. OK"<<std::endl);
542 //==========================================================================
547 //==========================================================================
548 /// UnLoads the package dynamic library (if any)
549 void Package::UnLoadDynamicLibrary(Package::WeakPointer pack, bool doit)
551 if (pack.expired() || (!pack.lock()->mDynamicLibraryHandler))
555 std::string packname = pack.lock()->GetName();
556 bbtkDebugMessage("package",5,"==> Package::UnLoadDynamicLibrary('"
560 if (!pack.lock()->GetBlackBoxMap().empty())
563 bbtkDebugMessage("package",5," Package not empty ... abort"
567 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
568 <<"BlackBoxMap not empty "
569 <<BBTK_INTERNAL_ERROR_MESSAGE);
574 if (pack.use_count()!=1)
576 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
577 <<"empty dl package with external refs"
578 <<BBTK_INTERNAL_ERROR_MESSAGE);
584 bbtkDebugMessage("package",5,"==> dynamic library for package '"
585 <<packname<<"' closed"
590 mReleasedDynamicallyLoadedPackages.insert(pack);
591 bbtkDebugMessage("package",1,"==> package '"<<packname
592 <<"' put in the 'to unload' list"
597 bbtkDebugMessage("package",5,"<== Package::UnLoadDynamicLibrary('"
602 //==========================================================================
604 //==========================================================================
605 /// UnLoads released packages that were loaded dynamically
606 /// see UnLoadDynamicLibrary and ReleaseBlackBoxDescriptor
607 void Package::UnLoadReleasedDynamicallyLoadedPackages()
609 bbtkDebugMessage("package",5,"==> Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
611 std::set<Package::WeakPointer>::iterator i;
612 for (i=mReleasedDynamicallyLoadedPackages.begin();
613 i!=mReleasedDynamicallyLoadedPackages.end();
616 if (!i->expired()) UnLoad(*i);
618 bbtkDebugMessage("package",5,"<== Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
620 //==========================================================================
622 //==========================================================================
623 void Package::UnLoad(Package::WeakPointer pack)
625 std::string packname = pack.lock()->GetName();
626 bbtkDebugMessage("package",6,"==> Package::UnLoad("<<packname<<")"<<std::endl);
628 Package* p = pack.lock().get();
630 DynamicLibraryHandler h = p->mDynamicLibraryHandler;
632 // deletes the package
633 p->mDLDeletePackageFunction();
635 // closes the dl handler
636 #if defined(__GNUC__)
638 #elif defined(_WIN32)
642 bbtkDebugMessage("package",1,"==> dynamic library for package '"
643 <<packname<<"' closed"
645 bbtkDebugMessage("package",6," ... dynamic library unloaded"<<std::endl);
647 //==========================================================================
649 //==========================================================================
650 /// Creates an instance of a black box of type <type> with name <name>
651 BlackBox::Pointer Package::NewBlackBox(const std::string& type,
652 const std::string& name) const
654 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::NewBlackBox(\""<<type<<"\",\""<<name<<"\")"<<bbtkendl);
656 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(type);
657 if (i == mBlackBoxMap.end())
659 bbtkDebugDecTab("Kernel",8);
660 return BlackBox::Pointer();
662 BlackBox::Pointer bb =i->second->NewBlackBox(name);
663 bbtkDebugDecTab("Kernel",8);
667 //==========================================================================
671 //==========================================================================
672 /// Creates an instance of an adaptor of input type <typein> and
673 /// output type <typeout> with name <name>
674 BlackBox::Pointer Package::NewAdaptor(const DataInfo& typein,
675 const DataInfo& typeout,
676 const std::string& name) const
678 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
682 <<name<<"\")"<<bbtkendl);
684 AdaptorKey key(typein,typeout,
685 BlackBoxDescriptor::DEFAULT_ADAPTOR);
686 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
687 if (i == mAdaptorMap.end())
689 bbtkDebugDecTab("Kernel",8);
690 return BlackBox::Pointer();
692 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
693 bbtkDebugDecTab("Kernel",8);
697 //==========================================================================
699 //==========================================================================
700 /// Creates an instance of an adaptor of input type <typein> and
701 /// output type <typeout> with name <name>
702 BlackBox::Pointer Package::NewWidgetAdaptor(const DataInfo& typein,
703 const DataInfo& typeout,
704 const std::string& name) const
706 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
707 ">::NewWidgetAdaptor("
710 <<name<<"\")"<<bbtkendl);
712 AdaptorKey key(typein,typeout,
713 BlackBoxDescriptor::DEFAULT_GUI);
714 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
715 if (i == mAdaptorMap.end())
717 bbtkDebugDecTab("Kernel",8);
718 return BlackBox::Pointer();
720 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
721 bbtkDebugDecTab("Kernel",8);
725 //==========================================================================
729 //==========================================================================
730 /// Returns true is the package contains
731 /// an adaptor of input type <typein> and
732 /// output type <typeout>
733 /// If successfull then adaptor contains the black box type name
734 bool Package::FindWidgetAdaptor(const DataInfo& typein,
735 const DataInfo& typeout,
736 std::string& adaptor) const
738 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
739 ">::FindWidgetAdaptor("
741 <<typeout<<")"<<bbtkendl);
743 AdaptorKey key(/*typein*/
744 DataInfo(typeid(void),""),
746 BlackBoxDescriptor::DEFAULT_GUI);
747 // First try to find a single widget adaptor
748 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
749 if (i == mAdaptorMap.end())
751 bbtkDebugDecTab("Kernel",8);
754 adaptor = i->second.lock()->GetTypeName();
755 bbtkDebugDecTab("Kernel",8);
759 //==========================================================================
763 //==========================================================================
764 /// Returns true is the package contains
765 /// an adaptor of input type <typein> and
766 /// output type <typeout>
767 /// If successfull then adaptor contains the black box type name
768 bool Package::FindAdaptor(const DataInfo& typein,
769 const DataInfo& typeout,
770 std::string& adaptor) const
772 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
775 <<typeout<<")"<<bbtkendl);
777 AdaptorKey key(typein,typeout,
778 BlackBoxDescriptor::DEFAULT_ADAPTOR);
779 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
780 if (i == mAdaptorMap.end())
782 bbtkDebugDecTab("Kernel",8);
785 adaptor = i->second.lock()->GetTypeName();
786 bbtkDebugDecTab("Kernel",8);
790 //==========================================================================
793 //==========================================================================
794 /// Registers a black box descriptor in the package
795 bool Package::RegisterBlackBox(BlackBoxDescriptor::Pointer d)
797 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\")"<<std::endl);
799 BlackBoxMapType::iterator i = mBlackBoxMap.find(d->GetTypeName());
800 if (i!=mBlackBoxMap.end())
802 bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
803 <<d->GetTypeName()<<"> which is already in the package");
807 mBlackBoxMap[d->GetTypeName()] = d;
809 d->SetPackage(GetThisPointer<Package>());
811 // If it is a default adaptor, also register it in the adaptors map
812 if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
814 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);
816 TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
817 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
818 DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
819 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
820 AdaptorKey key(infoin,infoout,d->GetKind());
822 AdaptorMapType::const_iterator i;
823 i = mAdaptorMap.find(key);
824 if (i == mAdaptorMap.end())
826 mAdaptorMap[key] = d;
828 // If already an adaptor registered : error
831 if (i->second.lock()->GetTypeName() != d->GetTypeName())
833 bbtkError("Package <"<<GetName()<<
834 "> : trying to register black box <"
836 <<"> as default adaptor but there is already a default adaptor registered (<"
837 <<i->second.lock()->GetTypeName()<<">)");
841 // If it is a default adaptor, also register it in the adaptors map
842 else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
844 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is a widget adaptor, inserting it in adaptors map ..."<<std::endl);
846 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
847 DataInfo infoin(typeid(void),"");
848 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
849 AdaptorKey key(infoin,infoout,d->GetKind());
851 AdaptorMapType::const_iterator i;
852 i = mAdaptorMap.find(key);
853 if (i == mAdaptorMap.end())
855 mAdaptorMap[key] = d;
857 // If already an adaptor registered : error
860 if (i->second.lock()->GetTypeName() != d->GetTypeName())
862 bbtkError("Package <"<<GetName()<<
863 "> : trying to register black box <"
865 <<"> as default widget adaptor but there is already a default adaptor registered (<"
866 <<i->second.lock()->GetTypeName()<<">)");
872 bbtkDebugDecTab("Kernel",8);
876 //==========================================================================
878 //===================================================================
879 void Package::CheckBoxes() const
881 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
882 <<" ["<<GetName()<<"]"<<std::endl);
883 BlackBoxMapType::const_iterator i;
884 for (i=mBlackBoxMap.begin();
885 i!=mBlackBoxMap.end();
888 i->second->Check(true);
890 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
891 <<" ["<<GetName()<<"] ... OK"<<std::endl);
893 //===================================================================
896 //==========================================================================
897 /// Changes the name of a black box type
898 void Package::ChangeBlackBoxName( const std::string& oldname, const std::string& newname )
900 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::ChangeBlackBoxName(\""<<oldname<<"\",\""<<newname<<"\")"<<std::endl);
901 // Looking into the bb map
902 BlackBoxMapType::iterator i = mBlackBoxMap.find(oldname);
903 if (i == mBlackBoxMap.end())
905 bbtkDebugDecTab("Kernel",8);
906 bbtkError("ChangeBlackBoxName : The package <"<<GetName()<<"> does not contains the black box <"<<oldname<<">");
909 i->second->SetTypeName(newname);
910 mBlackBoxMap[newname] = i->second;
911 mBlackBoxMap.erase(i);
913 bbtkDebugDecTab("Kernel",8);
915 //==========================================================================
919 //==========================================================================
920 /// Displays the list of black boxes of the package
921 void Package::PrintBlackBoxes(bool description, bool adaptors) const
923 unsigned int lmax = 0;
924 std::vector<std::string> names;
925 std::vector<std::string> kinds;
926 std::vector<std::string> descrs;
928 BlackBoxMapType::const_iterator i;
929 for (i=mBlackBoxMap.begin();
930 i!=mBlackBoxMap.end();
934 ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) )
936 std::string name(" ");
937 name += i->second->GetTypeName();
938 names.push_back(name);
941 if ( i->second->GetKind() == BlackBoxDescriptor::ADAPTOR )
943 kind = std::string("[A]");
945 else if ( i->second->GetKind() ==
946 BlackBoxDescriptor::DEFAULT_ADAPTOR )
948 kind = std::string("[DA]");
950 kinds.push_back(kind);
952 unsigned int l = name.size()+kind.size();
953 if (l>lmax) lmax = l;
959 descr += i->second->GetDescription();
961 descrs.push_back(descr);
967 offs.append(lmax+3,' ');
968 std::vector<std::string>::iterator ni,ci,di;
969 for (ni = names.begin(), ci = kinds.begin(), di = descrs.begin();
970 ni != names.end(); ++ni, ++ci, ++di)
973 space.append(lmax - ni->size() - ci->size(),' ');
974 bbtkMessage("Help",1,*ni << space << *ci );
976 unsigned int dmax = 75 - lmax;
977 // while (d.size() > dmax )
980 bbtkMessage("Help",1,d.substr(0,dmax) << "..." << std::endl);
982 bbtkMessage("Help",1,d << std::endl);
983 // d = d.substr(dmax,d.size());
988 //==========================================================================
990 //==========================================================================
991 /// Displays the list of adaptors of the package
992 void Package::PrintAdaptors(bool description) const
994 BlackBoxMapType::const_iterator i;
995 for (i=mBlackBoxMap.begin();
996 i!=mBlackBoxMap.end();
999 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD )
1001 bbtkMessage("Help",1,
1002 " "<<i->second->GetTypeName());
1003 if ( i->second->GetKind() ==
1004 BlackBoxDescriptor::DEFAULT_ADAPTOR )
1006 bbtkMessage("Help",1,
1011 bbtkMessage("Help",1,
1012 " : "<<i->second->GetDescription());
1015 bbtkMessage("Help",1,std::endl);
1019 AdaptorMapType::const_iterator i;
1020 for (i=mAdaptorMap.begin();
1021 i!=mAdaptorMap.end();
1024 bbtkMessage("Help",1,
1025 " "<<i->second->GetTypeName());
1028 bbtkMessage("Help",1,
1029 " : "<<i->second->GetDescription());
1032 bbtkMessage("Help",1,std::endl);
1036 //==========================================================================
1038 //==========================================================================
1039 /// Prints help on a black box
1040 void Package::HelpBlackBox(const std::string& name, bool full) const
1042 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1043 <<name<<"\")"<<bbtkendl);
1045 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1046 if (i == mBlackBoxMap.end())
1048 bbtkDebugDecTab("Kernel",8);
1049 bbtkError("The package <"<<GetName()<<"> does not contains the black box <"<<name<<">");
1051 // bbtkMessage("Help",1,"["<<GetName()<<"] ");
1052 i->second->GetHelp(full);
1053 bbtkDebugDecTab("Kernel",8);
1056 //==========================================================================
1059 //==========================================================================
1060 /// Returns true iff the package contains the box of name boxname
1061 bool Package::ContainsBlackBox(const std::string& name) const
1063 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1064 <<name<<"\")"<<bbtkendl);
1066 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1067 if (i == mBlackBoxMap.end())
1069 bbtkDebugDecTab("Kernel",8);
1072 bbtkDebugDecTab("Kernel",8);
1075 //==========================================================================
1079 //==========================================================================
1080 void Package::CreateHtmlPage(const std::string& filename,
1081 const std::string& caller,
1082 const std::string& source,
1083 const std::string& custom_header,
1084 const std::string& custom_title,
1087 bool relative_link ) const
1089 bbtkDebugMessageInc("Kernel",9,"Package<"<<GetName()<<">::CreateHtmlPage(\""
1090 <<filename<<"\")"<<bbtkendl);
1092 //---------------------
1095 s.open(filename.c_str());
1098 bbtkError("Package "<<GetName()<<" : CreateHtmlPage : could not open file '"<<filename<<"'");
1101 //----------------------
1103 std::string title = "BBTK Package "+GetName()+" "+GetVersion();
1105 if (custom_title.length() != 0) title = custom_title;
1107 s << "<html lang=\"en\">\n";
1109 s << "<title>" << title << "</title>\n";
1110 s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1111 s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1112 s << "<meta name=\"generator\" content=\"\">\n";
1113 s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1114 //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1115 s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1116 s << "pre.display { font-family:inherit }\n";
1117 s << "pre.format { font-family:inherit }\n";
1118 s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1119 s << "pre.smallformat { font-family:inherit; font-size:smaller }\n";
1120 s << "pre.smallexample { font-size:smaller }\n";
1121 s << "pre.smalllisp { font-size:smaller }\n";
1122 s << "span.sc { font-variant:small-caps }\n";
1123 s << "span.roman { font-family:serif; font-weight:normal; } \n";
1124 s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n";
1125 s << "--></style>\n";
1127 //----------------------
1129 //----------------------
1132 s << "<a name=\"Top\"></a>\n";
1134 //----------------------
1136 if ( custom_header.length() != 0)
1138 if ( custom_header != "none" )
1141 in.open(custom_header.c_str());
1144 bbtkError("Could not open file \""<<custom_header<<"\"");
1149 in.getline(buffer,512);
1150 std::string line(buffer);
1157 s << "<object data=\"" << custom_header
1158 << "\" type = \"text/html\"\"style=\"width: 1200px; height: 400px;\"> Warning: "
1159 << custom_header <<" could not be embedded.</object>\n";
1168 s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1169 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1170 s << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1171 << GetDescription() << "</TD></TR>\n";
1172 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1173 << GetAuthor() << "</TD></TR>\n";
1174 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1175 << GetCategory() << "</TD></TR>\n";
1176 s << "<TR><TD style='vertical-align: top;'><b> Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1177 << GetVersion() << "</TD></TR>\n";
1178 s << "<TR><TD style='vertical-align: top;'><b> bbtk Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1179 << bbtk::GetVersion() << "</TD></TR>\n";
1183 //-------------------
1184 // Table of contents
1186 // s << "<div class=\"contents\">\n";
1187 s << "<p><b> Black Boxes : </b>\n";
1190 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1192 BlackBoxMapType::const_iterator i;
1193 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i)
1195 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD)
1198 std::string name = i->second->GetTypeName();
1199 Utilities::html_format(name);
1200 std::string descr = i->second->GetDescription();
1201 //Utilities::html_format(descr);
1204 s << "<TD style='vertical-align: top;'>";
1205 s << " <a name=\"toc_"<<name
1206 <<"\" href=\"#"<<name<<"\">"
1209 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1218 //-------------------
1220 if (mAdaptorMap.size()>0)
1222 // s << "<div class=\"contents\">\n";
1223 s << "<p><b> Adaptors : </b>\n";
1226 // BlackBoxMapType::const_iterator i;
1227 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1228 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end();++i)
1230 if ( i->second->GetKind() == BlackBoxDescriptor::STANDARD)
1233 std::string name = i->second->GetTypeName();
1234 Utilities::html_format(name);
1235 std::string descr = i->second->GetDescription();
1238 s << "<TD style='vertical-align: top;'>";
1239 s << " <a name=\"toc_"<<name
1240 <<"\" href=\"#"<<name<<"\">"
1243 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1253 // s << "<div class=\"node\">\n";
1255 // s << "<p><hr>\n";
1256 // s << "<a name=\"Top\"></a>\n";
1257 // s << "Top: <a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
1258 // s << "Previous: <a rel="previous" accesskey="p" href="#dir">(dir)</a>,
1259 // s << "Up: <a rel="up" accesskey="u" href="#dir">(dir)</a>
1263 //----------------------
1266 //-------------------
1267 // Computes output directory from filename to pass it to
1268 // BlackBoxDescriptor::InsertHtmlHelp
1271 std::string::size_type slash_position = filename.find_last_of("/\\");
1274 if (slash_position != std::string::npos) {
1275 if (slash_position == 0)
1277 dir = filename.substr(0,slash_position);
1280 for (i=mBlackBoxMap.begin();
1281 i!=mBlackBoxMap.end();
1284 i->second->InsertHtmlHelp(s,detail,level,dir,relative_link);
1287 //----------------------
1292 ptm = gmtime ( &rawtime );
1295 s << "Automatically generated by <b>"<<caller<<"</b> "//from <b>"
1298 << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900
1299 << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1300 s << "</body></html>\n";
1302 //----------------------
1305 bbtkDebugDecTab("Kernel",9);
1307 //==========================================================================
1309 //==========================================================================
1310 std::string Package::GetObjectName() const
1312 return std::string("Package '")+mName+std::string("'");
1314 //==========================================================================
1316 //==========================================================================
1317 std::string Package::GetObjectInfo() const
1319 std::stringstream i;
1320 i << " - "<<mBlackBoxMap.size() << " boxes" << std::endl;
1321 if (mDynamicLibraryHandler)
1323 i<< " - Loaded from dynamic library"<<std::endl;
1327 //==========================================================================
1330 //==========================================================================
1331 size_t Package::GetObjectSize() const
1333 size_t s = Superclass::GetObjectSize();
1334 s += Package::GetObjectInternalSize();
1337 //==========================================================================
1338 //==========================================================================
1339 size_t Package::GetObjectInternalSize() const
1341 size_t s = sizeof(Package);
1344 //==========================================================================
1345 //==========================================================================
1346 size_t Package::GetObjectRecursiveSize() const
1348 size_t s = Superclass::GetObjectRecursiveSize();
1349 s += Package::GetObjectInternalSize();
1351 BlackBoxMapType::const_iterator i;
1352 for (i = mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i )
1354 s += i->second->GetObjectRecursiveSize();
1358 //==========================================================================
1360 //==========================================================================
1361 std::set<Package::WeakPointer>
1362 Package::mReleasedDynamicallyLoadedPackages;
1363 //==========================================================================