1 /*=========================================================================
4 Module: $RCSfile: bbtkPackage.cxx,v $
6 Date: $Date: 2008/04/25 13:37:49 $
7 Version: $Revision: 1.16 $
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 bbtkDebugMessage("package",3,"--- Trying to release descriptor '"
115 <<descname<<"'"<<bbtkendl);
116 std::string packname = pack.lock()->GetName();
118 Package::BlackBoxMapType::iterator desc =
119 pack.lock()->GetBlackBoxMap().find(descname);
120 if (desc == pack.lock()->GetBlackBoxMap().end())
122 bbtkDebugMessage("package",3,
123 " Descriptor has already been released"
127 // bbtkDebugMessage("package",3,
128 // " Trying unreferencing it ... "<<std::endl);
129 BlackBoxDescriptor::WeakPointer pdesc = desc->second;
130 desc->second.reset();
131 // if it is dead : remove it
134 bbtkDebugMessage("package",2," '"<<packname<<"::"<<descname<<"' Descriptor expired"<<bbtkendl);
137 bbtkDebugMessage("package",2,
138 " ... and caused its package death"
142 desc = pack.lock()->GetBlackBoxMap().find(descname);
143 if (desc != pack.lock()->GetBlackBoxMap().end())
144 pack.lock()->GetBlackBoxMap().erase(desc);
148 bbtkDebugMessage("package",3," ... Descriptor still alive ("
149 <<pdesc.use_count()<<" refs)"
151 pack.lock()->GetBlackBoxMap()[descname] = pdesc.lock();
154 //==========================================================================
157 //==========================================================================
159 void Package::Release(Package::WeakPointer pack)
161 std::string packname = pack.lock()->mName;
162 bbtkDebugMessage("package",1,"==> Package::Release('"<<
163 packname<<"')"<<bbtkendl);
165 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
166 long ndesc = pack.lock()->GetBlackBoxMap().size();
167 long nrefs = pack.use_count();
169 bbtkDebugMessage("package",2," "<<nrefs<<" refs / "
170 <<ndesc<<" descr / dyn="
173 // A package is "free" from any external reference iff :
174 // i) It is not dynamically loaded and nrefs == ndesc
175 // (each desc references its package) or
176 // ii) It is dynamically loaded and nrefs == ndesc + 1
177 // (A dynamic library holds a static pointer on the package it contains
178 // which is allocated when the PACKAGENAMEGetPackage() func is called,
179 // and descallocated (reset) by PACKAGENAMEDeletePackage())
180 if (nrefs == ndesc + dyn)
182 bbtkDebugMessage("package",2,
183 " -> No more external ref : checking descriptors"
185 // We must take care that removing refs on descriptors
186 // can lead to their deletion which can in turn unref
187 // internal boxes which can release their descriptors hence
188 // call Package::ReleaseBlackBoxDescriptor
189 // As a consequence during descriptors release :
190 // 1) The map can change dynamically : we cannot iterate over it
191 // as any iterator can become invalid
192 // 2) The package can auto-destruct : we must test its existence
193 // after each release
194 // We must also take care of not locking the package pointer
195 // or any ref count check in Package::ReleaseBlackBoxDescriptor
198 // The list of descriptors names at start
199 std::vector<std::string> descnamelist;
200 BlackBoxMapType::iterator i;
201 for (i=pack.lock()->mBlackBoxMap.begin();
202 i!= pack.lock()->mBlackBoxMap.end();
204 descnamelist.push_back(i->first);
206 // Iterator over the initial names
207 std::vector<std::string>::iterator descname;
208 for (descname=descnamelist.begin();
209 descname!=descnamelist.end();
212 // Is package still alive ?
215 bbtkDebugMessage("package",2,"--- Package::Release('"<<
217 <<"') : package expired during release : bailing out"<<bbtkendl);
221 PackageReleaseBlackBoxDescriptorInternal(pack,*descname);
226 UnLoadDynamicLibrary(pack);
227 // Unload orphan dl packages
228 Package::UnLoadReleasedDynamicallyLoadedPackages();
235 bbtkDebugMessage("package",1,"<== Package::Release('"<<
236 packname<<"')"<<bbtkendl);
239 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
240 long ndesc = pack.lock()->GetBlackBoxMap().size();
241 long nrefs = pack.use_count();
243 bbtkDebugMessage("package",1," ... Package still alive ("
245 <<ndesc<<" descr / dyn="
246 <<dyn<<")"<<std::endl);
250 bbtkDebugMessage("package",1," ... Package has been released"
254 //==========================================================================
256 //==========================================================================
257 /// "Releases" the package
258 /// Signals the package that it can free the given descriptor
259 /// if they are no more used and free itself if it is no
261 /// Note : Any non-weak pointer on the package must have been freed
262 void Package::ReleaseBlackBoxDescriptor(Package::WeakPointer pack,
263 BlackBoxDescriptor::WeakPointer descr)
265 std::string packname = pack.lock()->mName;
266 std::string dname = descr.lock()->GetTypeName();
267 bbtkDebugMessage("package",3,"==> Package::ReleaseBlackBoxDescriptor('"<<
268 packname<<"','"<<dname<<"') : refs="
269 <<descr.use_count()<<bbtkendl);
271 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
272 long ndesc = pack.lock()->GetBlackBoxMap().size();
273 long nrefs = pack.use_count();
275 bbtkDebugMessage("package",3," "<<nrefs<<" refs / "
276 <<ndesc<<" descr / dynamically loaded = "
279 // A package is "free" from any external reference iff :
280 // i) It is not dynamically loaded and nrefs == ndesc
281 // (each desc references its package) or
282 // ii) It is dynamically loaded and nrefs == ndesc + 1
283 // (A dynamic library holds a static pointer on the package it contains
284 // which is allocated when the PACKAGENAMEGetPackage() func is called,
285 // and descallocated (reset) by PACKAGENAMEDeletePackage())
286 if (nrefs == ndesc + dyn)
288 PackageReleaseBlackBoxDescriptorInternal(pack,dname);
291 // If the package is released and dynamically loaded
292 // then put it in the static list mReleasedDynamicallyLoadedPackages
293 UnLoadDynamicLibrary(pack,false);
295 bbtkDebugMessage("package",3,"<== Package::ReleaseBlackBoxDescriptor('"<<
296 packname<<"','"<<dname<<"'): refs="
297 <<descr.use_count()<<bbtkendl);
301 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
302 long ndesc = pack.lock()->GetBlackBoxMap().size();
303 long nrefs = pack.use_count();
305 bbtkDebugMessage("package",3," ... Package still alive ("
307 <<ndesc<<" descr / dyn="
308 <<dyn<<")"<<std::endl);
312 bbtkDebugMessage("package",3," ... Package has been released"
317 //==========================================================================
319 //==========================================================================
320 /// Opens a dynamic library which contains a bbtk package
321 /// Returns the handler
322 /// Load the package management symbols from the lib
323 /// returns false if a problem occured hence can be used
324 /// to test that a dyn lib is a valid bbtk package lib
325 /// NB : The BBTK version exported from the library
326 /// is tested against the current bbtk version
327 DynamicLibraryHandler Package::OpenDynamicLibrary
328 ( const std::string& libname,
329 const std::string& package_name,
330 DLGetPackageFunction& getpack,
331 DLDeletePackageFunction& delpack)
333 bbtkDebugMessage("package",3,"==> Package::OpenDynamicLibrary("
334 <<libname<<")"<<std::endl);
335 #if defined(__GNUC__)
339 handler = dlopen(libname.c_str(),
340 BBTK_RTLD_TIME | BBTK_RTLD_SCOPE );
343 bbtkMessage("package",2,
344 "Could not open shared library [" <<libname<<"] : "
345 <<dlerror() << std::endl);
349 bbtkDebugMessage("package",3,"* Shared lib ["<<libname<<"] open"<<std::endl);
351 // Loads the Package bbtk version function
352 std::string getvername(package_name);
354 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
355 DLGetPackageBBTKVersionFunction getbbtkversion
356 = (DLGetPackageBBTKVersionFunction)(dlsym(handler,getvername.c_str()));
359 bbtkDebugMessage("package",3,"***"<<std::endl);
360 bbtkMessage("package",2,
361 "Shared library ["<<libname
362 <<"] is not a valid bbtk package."
363 <<" Symbol ["<<getvername<<"] :"<<dlerror()<< std::endl);
368 bbtkDebugMessage("package",3,"* Symbol ["<<getvername
369 <<"] found"<<std::endl);
371 if (getbbtkversion() != bbtk::GetVersion())
373 bbtkMessage("package",2,
374 "Shared library ["<<libname
375 <<"] was build with bbtk version "
377 <<" but the current program runs with version "
378 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
384 bbtkDebugMessage("package",3,"* Package bbtk version '"<<getbbtkversion()<<"' matches"<<std::endl);
385 // Loads the Package get function
386 std::string getpackname(package_name);
387 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
388 getpack = (DLGetPackageFunction)(dlsym(handler, getpackname.c_str()));
391 bbtkMessage("package",2,
392 "Shared library ["<<libname
393 <<"] is not a valid bbtk package."
394 <<" Symbol ["<<getpackname<<"] :"<<dlerror()<< std::endl);
399 bbtkDebugMessage("package",3,"* Symbol ["<<getpackname<<"] found"<<std::endl);
400 // Loads the Package delete function
402 std::string delpackname(package_name);
403 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
404 delpack = (DLDeletePackageFunction)(dlsym(handler, delpackname.c_str()));
407 bbtkMessage("package",2,
408 "Shared library ["<<libname
409 <<"] is not a valid bbtk package."
410 <<" Symbol ["<<delpackname<<"] :"<<dlerror()<< std::endl);
414 bbtkDebugMessage("package",3,"* Symbol ["<<delpackname<<"] found"<<std::endl);
415 #elif defined(_WIN32)
421 handler = LoadLibrary(libname.c_str());
424 bbtkMessage("package",2,
425 "Could not open shared library [" <<libname<<"]"
430 // Loads the Package bbtk version function
431 std::string getvername(package_name);
433 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
434 DLGetPackageBBTKVersionFunction getbbtkversion
435 = (DLGetPackageBBTKVersionFunction)(GetProcAdress(handler,
436 getvername.c_str()));
439 FreeLibrary(handler);
440 bbtkMessage("package",2,
441 "Shared library ["<<libname
442 <<"] is not a valid bbtk package."
443 <<" Symbol ["<<getbbtkversion<<"] not found"<< std::endl);
448 if (getbbtkversion() != bbtk::GetVersion())
450 FreeLibrary(handler);
451 bbtkMessage("package",2,
452 "Shared library ["<<libname
453 <<"] was build with bbtk version "
455 <<" but the current program runs with version "
456 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
461 // Loads the Package get function
462 std::string getpackname(package_name);
463 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
464 getpack = (DLGetPackageFunction)(GetProcAdress(handler, getpackname.c_str()));
467 FreeLibrary(handler);
468 bbtkMessage("package",2,
469 "Shared library ["<<libname
470 <<"] is not a valid bbtk package."
471 <<" Symbol ["<<getpackname<<"] not found"<< std::endl);
475 // Loads the Package delete function
476 std::string delpackname(package_name);
477 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
478 delpack = (DLDeletePackageFunction)(GetProcAdress(handler, delpackname.c_str()));
481 FreeLibrary(handler);
482 bbtkMessage("package",2,
483 "Shared library ["<<libname
484 <<"] is not a valid bbtk package."
485 <<" Symbol ["<<delpackname<<"] not found"<< std::endl);
490 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
495 //==========================================================================
497 //==========================================================================
498 /// Loads a package from a dynamic library
499 Package::Pointer Package::CreateFromDynamicLibrary(const std::string& libname,
500 const std::string& pkgname,
501 const std::string& path)
503 bbtkDebugMessage("package",1,"==> Package::CreateFromDynamicLibrary("
504 <<libname<<")"<<std::endl);
506 DLGetPackageFunction gf;
507 DLDeletePackageFunction df;
508 DynamicLibraryHandler h = Package::OpenDynamicLibrary(libname,
511 if (h==0) return Package::Pointer();
512 Package::Pointer p = gf();
513 p->mDynamicLibraryHandler = h;
514 p->mDLDeletePackageFunction = df;
516 std::string separator =
517 ConfigurationFile::GetInstance().Get_file_separator ();
518 //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
519 std::string docreldoc =
520 separator + "bbdoc" + separator + pkgname + separator + "index.html";
522 ".." + separator + ".." + docreldoc;
523 std::string doc = path + separator + ".." + separator
524 + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
528 p->SetDocRelativeURL(reldoc);
530 bbtkDebugMessage("package",1,"<== Package::CreateFromDynamicLibrary("
531 <<libname<<") .. OK"<<std::endl);
534 //==========================================================================
539 //==========================================================================
540 /// UnLoads the package dynamic library (if any)
541 void Package::UnLoadDynamicLibrary(Package::WeakPointer pack, bool doit)
543 if (pack.expired() || (!pack.lock()->mDynamicLibraryHandler))
547 std::string packname = pack.lock()->GetName();
548 bbtkDebugMessage("package",3,"==> Package::UnLoadDynamicLibrary('"
552 if (!pack.lock()->GetBlackBoxMap().empty())
555 bbtkDebugMessage("package",3," Package not empty ... abort"
559 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
560 <<"BlackBoxMap not empty "
561 <<BBTK_INTERNAL_ERROR_MESSAGE);
566 if (pack.use_count()!=1)
568 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
569 <<"empty dl package with external refs"
570 <<BBTK_INTERNAL_ERROR_MESSAGE);
576 bbtkDebugMessage("package",3," ... dynamic library closed"
581 mReleasedDynamicallyLoadedPackages.insert(pack);
582 bbtkDebugMessage("package",3,
583 " ... package put in the 'to unload' list"
588 bbtkDebugMessage("package",3,"<== Package::UnLoadDynamicLibrary('"
593 //==========================================================================
595 //==========================================================================
596 /// UnLoads released packages that were loaded dynamically
597 /// see UnLoadDynamicLibrary and ReleaseBlackBoxDescriptor
598 void Package::UnLoadReleasedDynamicallyLoadedPackages()
600 bbtkDebugMessage("package",2,"==> Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
602 std::set<Package::WeakPointer>::iterator i;
603 for (i=mReleasedDynamicallyLoadedPackages.begin();
604 i!=mReleasedDynamicallyLoadedPackages.end();
607 if (!i->expired()) UnLoad(*i);
609 bbtkDebugMessage("package",2,"<== Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
611 //==========================================================================
613 //==========================================================================
614 void Package::UnLoad(Package::WeakPointer pack)
616 std::string packname = pack.lock()->GetName();
617 bbtkDebugMessage("package",2,"==> Package::UnLoad("<<packname<<")"<<std::endl);
619 Package* p = pack.lock().get();
621 DynamicLibraryHandler h = p->mDynamicLibraryHandler;
623 // deletes the package
624 p->mDLDeletePackageFunction();
626 // closes the dl handler
627 #if defined(__GNUC__)
629 #elif defined(_WIN32)
633 bbtkDebugMessage("package",2," ... dynamic library unloaded"<<std::endl);
635 //==========================================================================
637 //==========================================================================
638 /// Creates an instance of a black box of type <type> with name <name>
639 BlackBox::Pointer Package::NewBlackBox(const std::string& type,
640 const std::string& name) const
642 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::NewBlackBox(\""<<type<<"\",\""<<name<<"\")"<<bbtkendl);
644 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(type);
645 if (i == mBlackBoxMap.end())
647 bbtkDebugDecTab("Kernel",8);
648 return BlackBox::Pointer();
650 BlackBox::Pointer bb =i->second->NewBlackBox(name);
651 bbtkDebugDecTab("Kernel",8);
655 //==========================================================================
659 //==========================================================================
660 /// Creates an instance of an adaptor of input type <typein> and
661 /// output type <typeout> with name <name>
662 BlackBox::Pointer Package::NewAdaptor(const DataInfo& typein,
663 const DataInfo& typeout,
664 const std::string& name) const
666 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
670 <<name<<"\")"<<bbtkendl);
672 AdaptorKey key(typein,typeout,
673 BlackBoxDescriptor::DEFAULT_ADAPTOR);
674 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
675 if (i == mAdaptorMap.end())
677 bbtkDebugDecTab("Kernel",8);
678 return BlackBox::Pointer();
680 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
681 bbtkDebugDecTab("Kernel",8);
685 //==========================================================================
687 //==========================================================================
688 /// Creates an instance of an adaptor of input type <typein> and
689 /// output type <typeout> with name <name>
690 BlackBox::Pointer Package::NewWidgetAdaptor(const DataInfo& typein,
691 const DataInfo& typeout,
692 const std::string& name) const
694 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
695 ">::NewWidgetAdaptor("
698 <<name<<"\")"<<bbtkendl);
700 AdaptorKey key(typein,typeout,
701 BlackBoxDescriptor::DEFAULT_GUI);
702 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
703 if (i == mAdaptorMap.end())
705 bbtkDebugDecTab("Kernel",8);
706 return BlackBox::Pointer();
708 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
709 bbtkDebugDecTab("Kernel",8);
713 //==========================================================================
717 //==========================================================================
718 /// Returns true is the package contains
719 /// an adaptor of input type <typein> and
720 /// output type <typeout>
721 /// If successfull then adaptor contains the black box type name
722 bool Package::FindWidgetAdaptor(const DataInfo& typein,
723 const DataInfo& typeout,
724 std::string& adaptor) const
726 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
727 ">::FindWidgetAdaptor("
729 <<typeout<<")"<<bbtkendl);
731 AdaptorKey key(/*typein*/
732 DataInfo(typeid(void),""),
734 BlackBoxDescriptor::DEFAULT_GUI);
735 // First try to find a single widget adaptor
736 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
737 if (i == mAdaptorMap.end())
739 bbtkDebugDecTab("Kernel",8);
742 adaptor = i->second.lock()->GetTypeName();
743 bbtkDebugDecTab("Kernel",8);
747 //==========================================================================
751 //==========================================================================
752 /// Returns true is the package contains
753 /// an adaptor of input type <typein> and
754 /// output type <typeout>
755 /// If successfull then adaptor contains the black box type name
756 bool Package::FindAdaptor(const DataInfo& typein,
757 const DataInfo& typeout,
758 std::string& adaptor) const
760 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
763 <<typeout<<")"<<bbtkendl);
765 AdaptorKey key(typein,typeout,
766 BlackBoxDescriptor::DEFAULT_ADAPTOR);
767 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
768 if (i == mAdaptorMap.end())
770 bbtkDebugDecTab("Kernel",8);
773 adaptor = i->second.lock()->GetTypeName();
774 bbtkDebugDecTab("Kernel",8);
778 //==========================================================================
781 //==========================================================================
782 /// Registers a black box descriptor in the package
783 bool Package::RegisterBlackBox(BlackBoxDescriptor::Pointer d)
785 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\")"<<std::endl);
787 BlackBoxMapType::iterator i = mBlackBoxMap.find(d->GetTypeName());
788 if (i!=mBlackBoxMap.end())
790 bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
791 <<d->GetTypeName()<<"> which is already in the package");
795 mBlackBoxMap[d->GetTypeName()] = d;
797 d->SetPackage(GetThisPointer<Package>());
799 // If it is a default adaptor, also register it in the adaptors map
800 if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
802 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);
804 TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
805 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
806 DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
807 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
808 AdaptorKey key(infoin,infoout,d->GetKind());
810 AdaptorMapType::const_iterator i;
811 i = mAdaptorMap.find(key);
812 if (i == mAdaptorMap.end())
814 mAdaptorMap[key] = d;
816 // If already an adaptor registered : error
819 if (i->second.lock()->GetTypeName() != d->GetTypeName())
821 bbtkError("Package <"<<GetName()<<
822 "> : trying to register black box <"
824 <<"> as default adaptor but there is already a default adaptor registered (<"
825 <<i->second.lock()->GetTypeName()<<">)");
829 // If it is a default adaptor, also register it in the adaptors map
830 else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
832 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is a widget adaptor, inserting it in adaptors map ..."<<std::endl);
834 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
835 DataInfo infoin(typeid(void),"");
836 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
837 AdaptorKey key(infoin,infoout,d->GetKind());
839 AdaptorMapType::const_iterator i;
840 i = mAdaptorMap.find(key);
841 if (i == mAdaptorMap.end())
843 mAdaptorMap[key] = d;
845 // If already an adaptor registered : error
848 if (i->second.lock()->GetTypeName() != d->GetTypeName())
850 bbtkError("Package <"<<GetName()<<
851 "> : trying to register black box <"
853 <<"> as default widget adaptor but there is already a default adaptor registered (<"
854 <<i->second.lock()->GetTypeName()<<">)");
860 bbtkDebugDecTab("Kernel",8);
864 //==========================================================================
866 //===================================================================
867 void Package::CheckBoxes() const
869 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
870 <<" ["<<GetName()<<"]"<<std::endl);
871 BlackBoxMapType::const_iterator i;
872 for (i=mBlackBoxMap.begin();
873 i!=mBlackBoxMap.end();
876 i->second->Check(true);
878 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
879 <<" ["<<GetName()<<"] ... OK"<<std::endl);
881 //===================================================================
884 //==========================================================================
885 /// Changes the name of a black box type
886 void Package::ChangeBlackBoxName( const std::string& oldname, const std::string& newname )
888 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::ChangeBlackBoxName(\""<<oldname<<"\",\""<<newname<<"\")"<<std::endl);
889 // Looking into the bb map
890 BlackBoxMapType::iterator i = mBlackBoxMap.find(oldname);
891 if (i == mBlackBoxMap.end())
893 bbtkDebugDecTab("Kernel",8);
894 bbtkError("ChangeBlackBoxName : The package <"<<GetName()<<"> does not contains the black box <"<<oldname<<">");
897 i->second->SetTypeName(newname);
898 mBlackBoxMap[newname] = i->second;
899 mBlackBoxMap.erase(i);
901 bbtkDebugDecTab("Kernel",8);
903 //==========================================================================
907 //==========================================================================
908 /// Displays the list of black boxes of the package
909 void Package::PrintBlackBoxes(bool description, bool adaptors) const
911 unsigned int lmax = 0;
912 std::vector<std::string> names;
913 std::vector<std::string> kinds;
914 std::vector<std::string> descrs;
916 BlackBoxMapType::const_iterator i;
917 for (i=mBlackBoxMap.begin();
918 i!=mBlackBoxMap.end();
922 ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) )
924 std::string name(" ");
925 name += i->second->GetTypeName();
926 names.push_back(name);
929 if ( i->second->GetKind() == BlackBoxDescriptor::ADAPTOR )
931 kind = std::string("[A]");
933 else if ( i->second->GetKind() ==
934 BlackBoxDescriptor::DEFAULT_ADAPTOR )
936 kind = std::string("[DA]");
938 kinds.push_back(kind);
940 unsigned int l = name.size()+kind.size();
941 if (l>lmax) lmax = l;
947 descr += i->second->GetDescription();
949 descrs.push_back(descr);
955 offs.append(lmax+3,' ');
956 std::vector<std::string>::iterator ni,ci,di;
957 for (ni = names.begin(), ci = kinds.begin(), di = descrs.begin();
958 ni != names.end(); ++ni, ++ci, ++di)
961 space.append(lmax - ni->size() - ci->size(),' ');
962 bbtkMessage("Help",1,*ni << space << *ci );
964 unsigned int dmax = 75 - lmax;
965 // while (d.size() > dmax )
968 bbtkMessage("Help",1,d.substr(0,dmax) << "..." << std::endl);
970 bbtkMessage("Help",1,d << std::endl);
971 // d = d.substr(dmax,d.size());
976 //==========================================================================
978 //==========================================================================
979 /// Displays the list of adaptors of the package
980 void Package::PrintAdaptors(bool description) const
982 BlackBoxMapType::const_iterator i;
983 for (i=mBlackBoxMap.begin();
984 i!=mBlackBoxMap.end();
987 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD )
989 bbtkMessage("Help",1,
990 " "<<i->second->GetTypeName());
991 if ( i->second->GetKind() ==
992 BlackBoxDescriptor::DEFAULT_ADAPTOR )
994 bbtkMessage("Help",1,
999 bbtkMessage("Help",1,
1000 " : "<<i->second->GetDescription());
1003 bbtkMessage("Help",1,std::endl);
1007 AdaptorMapType::const_iterator i;
1008 for (i=mAdaptorMap.begin();
1009 i!=mAdaptorMap.end();
1012 bbtkMessage("Help",1,
1013 " "<<i->second->GetTypeName());
1016 bbtkMessage("Help",1,
1017 " : "<<i->second->GetDescription());
1020 bbtkMessage("Help",1,std::endl);
1024 //==========================================================================
1026 //==========================================================================
1027 /// Prints help on a black box
1028 void Package::HelpBlackBox(const std::string& name, bool full) const
1030 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1031 <<name<<"\")"<<bbtkendl);
1033 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1034 if (i == mBlackBoxMap.end())
1036 bbtkDebugDecTab("Kernel",8);
1037 bbtkError("The package <"<<GetName()<<"> does not contains the black box <"<<name<<">");
1039 // bbtkMessage("Help",1,"["<<GetName()<<"] ");
1040 i->second->GetHelp(full);
1041 bbtkDebugDecTab("Kernel",8);
1044 //==========================================================================
1047 //==========================================================================
1048 /// Returns true iff the package contains the box of name boxname
1049 bool Package::ContainsBlackBox(const std::string& name) const
1051 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1052 <<name<<"\")"<<bbtkendl);
1054 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1055 if (i == mBlackBoxMap.end())
1057 bbtkDebugDecTab("Kernel",8);
1060 bbtkDebugDecTab("Kernel",8);
1063 //==========================================================================
1067 //==========================================================================
1068 void Package::CreateHtmlPage(const std::string& filename,
1069 const std::string& caller,
1070 const std::string& source,
1071 const std::string& custom_header,
1072 const std::string& custom_title,
1075 bool relative_link ) const
1077 bbtkDebugMessageInc("Kernel",9,"Package<"<<GetName()<<">::CreateHtmlPage(\""
1078 <<filename<<"\")"<<bbtkendl);
1080 //---------------------
1083 s.open(filename.c_str());
1086 bbtkError("Package "<<GetName()<<" : CreateHtmlPage : could not open file '"<<filename<<"'");
1089 //----------------------
1091 std::string title = "BBTK Package "+GetName()+" "+GetVersion();
1093 if (custom_title.length() != 0) title = custom_title;
1095 s << "<html lang=\"en\">\n";
1097 s << "<title>" << title << "</title>\n";
1098 s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1099 s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1100 s << "<meta name=\"generator\" content=\"\">\n";
1101 s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1102 //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1103 s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1104 s << "pre.display { font-family:inherit }\n";
1105 s << "pre.format { font-family:inherit }\n";
1106 s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1107 s << "pre.smallformat { font-family:inherit; font-size:smaller }\n";
1108 s << "pre.smallexample { font-size:smaller }\n";
1109 s << "pre.smalllisp { font-size:smaller }\n";
1110 s << "span.sc { font-variant:small-caps }\n";
1111 s << "span.roman { font-family:serif; font-weight:normal; } \n";
1112 s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n";
1113 s << "--></style>\n";
1115 //----------------------
1117 //----------------------
1120 s << "<a name=\"Top\"></a>\n";
1122 //----------------------
1124 if ( custom_header.length() != 0)
1126 if ( custom_header != "none" )
1129 in.open(custom_header.c_str());
1132 bbtkError("Could not open file \""<<custom_header<<"\"");
1137 in.getline(buffer,512);
1138 std::string line(buffer);
1145 s << "<object data=\"" << custom_header
1146 << "\" type = \"text/html\"\"style=\"width: 1200px; height: 400px;\"> Warning: "
1147 << custom_header <<" could not be embedded.</object>\n";
1156 s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1157 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1158 s << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1159 << GetDescription() << "</TD></TR>\n";
1160 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1161 << GetAuthor() << "</TD></TR>\n";
1162 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1163 << GetCategory() << "</TD></TR>\n";
1164 s << "<TR><TD style='vertical-align: top;'><b> Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1165 << GetVersion() << "</TD></TR>\n";
1166 s << "<TR><TD style='vertical-align: top;'><b> bbtk Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1167 << bbtk::GetVersion() << "</TD></TR>\n";
1171 //-------------------
1172 // Table of contents
1174 // s << "<div class=\"contents\">\n";
1175 s << "<p><b> Black Boxes : </b>\n";
1178 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1180 BlackBoxMapType::const_iterator i;
1181 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i)
1183 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD)
1186 std::string name = i->second->GetTypeName();
1187 Utilities::html_format(name);
1188 std::string descr = i->second->GetDescription();
1189 Utilities::html_format(descr);
1192 s << "<TD style='vertical-align: top;'>";
1193 s << " <a name=\"toc_"<<name
1194 <<"\" href=\"#"<<name<<"\">"
1197 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1206 //-------------------
1208 if (mAdaptorMap.size()>0)
1210 // s << "<div class=\"contents\">\n";
1211 s << "<p><b> Adaptors : </b>\n";
1214 // BlackBoxMapType::const_iterator i;
1215 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1216 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end();++i)
1218 if ( i->second->GetKind() == BlackBoxDescriptor::STANDARD)
1221 std::string name = i->second->GetTypeName();
1222 Utilities::html_format(name);
1223 std::string descr = i->second->GetDescription();
1226 s << "<TD style='vertical-align: top;'>";
1227 s << " <a name=\"toc_"<<name
1228 <<"\" href=\"#"<<name<<"\">"
1231 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1241 // s << "<div class=\"node\">\n";
1243 // s << "<p><hr>\n";
1244 // s << "<a name=\"Top\"></a>\n";
1245 // s << "Top: <a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
1246 // s << "Previous: <a rel="previous" accesskey="p" href="#dir">(dir)</a>,
1247 // s << "Up: <a rel="up" accesskey="u" href="#dir">(dir)</a>
1251 //----------------------
1254 //-------------------
1255 // Computes output directory from filename to pass it to
1256 // BlackBoxDescriptor::InsertHtmlHelp
1259 std::string::size_type slash_position = filename.find_last_of("/\\");
1262 if (slash_position != std::string::npos) {
1263 if (slash_position == 0)
1265 dir = filename.substr(0,slash_position);
1268 for (i=mBlackBoxMap.begin();
1269 i!=mBlackBoxMap.end();
1272 i->second->InsertHtmlHelp(s,detail,level,dir,relative_link);
1275 //----------------------
1280 ptm = gmtime ( &rawtime );
1283 s << "Automatically generated by <b>"<<caller<<"</b> "//from <b>"
1286 << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900
1287 << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1288 s << "</body></html>\n";
1290 //----------------------
1293 bbtkDebugDecTab("Kernel",9);
1295 //==========================================================================
1297 //==========================================================================
1298 std::string Package::GetObjectName() const
1300 return std::string("Package '")+mName+std::string("'");
1302 //==========================================================================
1304 //==========================================================================
1305 std::string Package::GetObjectInfo() const
1307 std::stringstream i;
1308 i << " - "<<mBlackBoxMap.size() << " boxes" << std::endl;
1309 if (mDynamicLibraryHandler)
1311 i<< " - Loaded from dynamic library"<<std::endl;
1315 //==========================================================================
1318 //==========================================================================
1319 size_t Package::GetObjectSize() const
1321 size_t s = Superclass::GetObjectSize();
1322 s += Package::GetObjectInternalSize();
1325 //==========================================================================
1326 //==========================================================================
1327 size_t Package::GetObjectInternalSize() const
1329 size_t s = sizeof(Package);
1332 //==========================================================================
1333 //==========================================================================
1334 size_t Package::GetObjectRecursiveSize() const
1336 size_t s = Superclass::GetObjectRecursiveSize();
1337 s += Package::GetObjectInternalSize();
1339 BlackBoxMapType::const_iterator i;
1340 for (i = mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i )
1342 s += i->second->GetObjectRecursiveSize();
1346 //==========================================================================
1348 //==========================================================================
1349 std::set<Package::WeakPointer>
1350 Package::mReleasedDynamicallyLoadedPackages;
1351 //==========================================================================