2 /*=========================================================================
4 Module: $RCSfile: bbtkPackage.cxx,v $
6 Date: $Date: 2009/05/28 08:12:06 $
7 Version: $Revision: 1.26 $
8 =========================================================================*/
10 /* ---------------------------------------------------------------------
12 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
13 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
15 * This software is governed by the CeCILL-B license under French law and
16 * abiding by the rules of distribution of free software. You can use,
17 * modify and/ or redistribute the software under the terms of the CeCILL-B
18 * license as circulated by CEA, CNRS and INRIA at the following URL
19 * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
20 * or in the file LICENSE.txt.
22 * As a counterpart to the access to the source code and rights to copy,
23 * modify and redistribute granted by the license, users are provided only
24 * with a limited warranty and the software's author, the holder of the
25 * economic rights, and the successive licensors have only limited
28 * The fact that you are presently reading this means that you have had
29 * knowledge of the CeCILL-B license and that you accept its terms.
30 * ------------------------------------------------------------------------ */
34 *\brief Class bbtk::Package : registers black boxes descriptors and is able to create instances of the black boxes registered.
36 #include "bbtkPackage.h"
37 #include "bbtkMessageManager.h"
38 #include "bbtkConfigurationFile.h"
41 #include "bbtkUtilities.h"
48 //==========================================================================
49 /// Creates a new package
50 Package::Pointer Package::New(const std::string& name,
51 const std::string& author,
52 const std::string& description,
53 const std::string& version)
55 bbtkDebugMessage("object",1,"##> Package::New('"<<name<<"',...)"
57 Package::Pointer p = MakePointer(new Package(name,
61 bbtkDebugMessage("object",2,"<## Package::New('"<<name<<"',...)"
65 //==========================================================================
67 //==========================================================================
68 /// Ctor with the name of the package
69 Package::Package(const std::string& name,
70 const std::string& author,
71 const std::string& description,
72 const std::string& version)
74 mDynamicLibraryHandler(0),
77 mDescription(description),
80 bbtkDebugMessage("object",2,"==> Package('"<<name<<"',...)"
82 std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
83 char c = default_doc_dir.c_str()[strlen(default_doc_dir.c_str())-1];
84 std::string url = default_doc_dir;
85 if (c != '/' && c !='\\') url = url + "/";
86 url = url + "temp_dir/" + name + "/index.html";
89 SetDocRelativeURL("Relative url not set");
92 std::string relurl(BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH));
93 relurl += "/packages/"+name+"/bbdoc/index.html";
94 std::string url = ConfigurationFile::GetInstance().Get_url()
97 SetDocRelativeURL(relurl);
100 // std::cout << " url=["<<url<<"]"<<std::endl;
101 // std::cout << "relurl=["<<relurl<<"]"<<std::endl;
102 bbtkDebugMessage("object",2,"<== Package::Package('"<<name<<"',...) OK"
106 //==========================================================================
110 //==========================================================================
114 bbtkDebugMessage("object",2,"==> ~Package(\""<<mName<<"\")"<<bbtkendl);
116 //==========================================================================
119 //==========================================================================
120 void PackageReleaseBlackBoxDescriptorInternal(Package::WeakPointer pack,
121 const std::string& descname)
123 // Try to release descriptor
124 std::string packname = pack.lock()->GetName();
126 bbtkDebugMessage("package",5,"--- Releasing descriptor '"
127 <<packname<<"::"<<descname<<"'"<<bbtkendl);
130 Package::BlackBoxMapType::iterator desc =
131 pack.lock()->GetBlackBoxMap().find(descname);
132 if (desc == pack.lock()->GetBlackBoxMap().end())
134 bbtkDebugMessage("package",5,
135 " Descriptor has already been released"
139 // bbtkDebugMessage("package",3,
140 // " Trying unreferencing it ... "<<std::endl);
141 BlackBoxDescriptor::WeakPointer pdesc = desc->second;
142 desc->second.reset();
143 // if it is dead : remove it
146 bbtkDebugMessage("package",2," ==> '"<<packname<<"::"<<descname<<"' Descriptor expired"<<bbtkendl);
149 bbtkDebugMessage("package",2,
150 " ... and caused its package death"
154 desc = pack.lock()->GetBlackBoxMap().find(descname);
155 if (desc != pack.lock()->GetBlackBoxMap().end())
156 pack.lock()->GetBlackBoxMap().erase(desc);
160 bbtkDebugMessage("package",5," ... Descriptor still alive ("
161 <<pdesc.use_count()<<" refs)"
163 pack.lock()->GetBlackBoxMap()[descname] = pdesc.lock();
166 //==========================================================================
169 //==========================================================================
171 void Package::Release(Package::WeakPointer pack)
173 std::string packname = pack.lock()->mName;
174 bbtkDebugMessage("package",1,"==> Package::Release('"<<
175 packname<<"')"<<bbtkendl);
177 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
178 long ndesc = pack.lock()->GetBlackBoxMap().size();
179 long nrefs = pack.use_count();
181 bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
182 <<ndesc<<" descr / dyn="
185 // A package is "free" from any external reference iff :
186 // i) It is not dynamically loaded and nrefs == ndesc
187 // (each desc references its package) or
188 // ii) It is dynamically loaded and nrefs == ndesc + 1
189 // (A dynamic library holds a static pointer on the package it contains
190 // which is allocated when the PACKAGENAMEGetPackage() func is called,
191 // and descallocated (reset) by PACKAGENAMEDeletePackage())
192 if (nrefs == ndesc + dyn)
194 bbtkDebugMessage("package",5,
195 " -> No more external ref : checking descriptors"
197 // We must take care that removing refs on descriptors
198 // can lead to their deletion which can in turn unref
199 // internal boxes which can release their descriptors hence
200 // call Package::ReleaseBlackBoxDescriptor
201 // As a consequence during descriptors release :
202 // 1) The map can change dynamically : we cannot iterate over it
203 // as any iterator can become invalid
204 // 2) The package can auto-destruct : we must test its existence
205 // after each release
206 // We must also take care of not locking the package pointer
207 // or any ref count check in Package::ReleaseBlackBoxDescriptor
210 // The list of descriptors names at start
211 std::vector<std::string> descnamelist;
212 BlackBoxMapType::iterator i;
213 for (i=pack.lock()->mBlackBoxMap.begin();
214 i!= pack.lock()->mBlackBoxMap.end();
216 descnamelist.push_back(i->first);
218 // Iterator over the initial names
219 std::vector<std::string>::iterator descname;
220 for (descname=descnamelist.begin();
221 descname!=descnamelist.end();
224 // Is package still alive ?
227 bbtkDebugMessage("package",1,"--- Package::Release('"<<
229 <<"') : package expired during release : bailing out"<<bbtkendl);
233 PackageReleaseBlackBoxDescriptorInternal(pack,*descname);
238 UnLoadDynamicLibrary(pack);
239 // Unload orphan dl packages
240 Package::UnLoadReleasedDynamicallyLoadedPackages();
247 #ifdef BBTK_COMPILE_DEBUG_MESSAGES
249 bbtkDebugMessage("package",2,"<== Package::Release('"<<
250 packname<<"')"<<bbtkendl);
254 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
255 long ndesc = pack.lock()->GetBlackBoxMap().size();
256 long nrefs = pack.use_count();
258 bbtkDebugMessage("package",1," ... Package still alive ("
260 <<ndesc<<" descr / dyn="
261 <<dyn<<")"<<std::endl);
265 bbtkDebugMessage("package",1," ... Package has been released"
270 //==========================================================================
272 //==========================================================================
273 /// "Releases" the package
274 /// Signals the package that it can free the given descriptor
275 /// if they are no more used and free itself if it is no
277 /// Note : Any non-weak pointer on the package must have been freed
278 void Package::ReleaseBlackBoxDescriptor(Package::WeakPointer pack,
279 BlackBoxDescriptor::WeakPointer descr)
281 std::string packname = pack.lock()->mName;
282 std::string dname = descr.lock()->GetTypeName();
283 bbtkDebugMessage("package",3,"==> Package::ReleaseBlackBoxDescriptor('"<<
284 packname<<"','"<<dname<<"') : refs="
285 <<descr.use_count()<<bbtkendl);
287 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
288 long ndesc = pack.lock()->GetBlackBoxMap().size();
289 long nrefs = pack.use_count();
291 bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
292 <<ndesc<<" descr / dynamically loaded = "
295 // A package is "free" from any external reference iff :
296 // i) It is not dynamically loaded and nrefs == ndesc
297 // (each desc references its package) or
298 // ii) It is dynamically loaded and nrefs == ndesc + 1
299 // (A dynamic library holds a static pointer on the package it contains
300 // which is allocated when the PACKAGENAMEGetPackage() func is called,
301 // and descallocated (reset) by PACKAGENAMEDeletePackage())
302 if (nrefs == ndesc + dyn)
304 PackageReleaseBlackBoxDescriptorInternal(pack,dname);
307 // If the package is released and dynamically loaded
308 // then put it in the static list mReleasedDynamicallyLoadedPackages
309 UnLoadDynamicLibrary(pack,false);
311 bbtkDebugMessage("package",4,"<== Package::ReleaseBlackBoxDescriptor('"<<
312 packname<<"','"<<dname<<"'): refs="
313 <<descr.use_count()<<bbtkendl);
317 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
318 long ndesc = pack.lock()->GetBlackBoxMap().size();
319 long nrefs = pack.use_count();
321 bbtkDebugMessage("package",3," ... Package still alive ("
323 <<ndesc<<" descr / dyn="
324 <<dyn<<")"<<std::endl);
328 bbtkDebugMessage("package",3," ... Package has been released"
333 //==========================================================================
335 //==========================================================================
336 /// Opens a dynamic library which contains a bbtk package
337 /// Returns the handler
338 /// Load the package management symbols from the lib
339 /// returns false if a problem occured hence can be used
340 /// to test that a dyn lib is a valid bbtk package lib
341 /// NB : The BBTK version exported from the library
342 /// is tested against the current bbtk version
343 DynamicLibraryHandler Package::OpenDynamicLibrary
344 ( const std::string& libname,
345 const std::string& package_name,
346 DLGetPackageFunction& getpack,
347 DLDeletePackageFunction& delpack)
349 bbtkDebugMessage("package",3,"==> Package::OpenDynamicLibrary("
350 <<libname<<")"<<std::endl);
351 #if defined(__GNUC__)
355 handler = dlopen(libname.c_str(),
356 BBTK_RTLD_TIME | BBTK_RTLD_SCOPE );
359 bbtkMessage("package",2,
360 "Could not open shared library [" <<libname<<"] : "
361 <<dlerror() << std::endl);
365 bbtkDebugMessage("package",3,"* Shared lib ["<<libname<<"] open"<<std::endl);
367 // Loads the Package bbtk version function
368 std::string getvername(package_name);
370 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
371 DLGetPackageBBTKVersionFunction getbbtkversion
372 = (DLGetPackageBBTKVersionFunction)(dlsym(handler,getvername.c_str()));
375 bbtkDebugMessage("package",3,"***"<<std::endl);
376 bbtkMessage("package",2,
377 "Shared library ["<<libname
378 <<"] is not a valid bbtk package."
379 <<" Symbol ["<<getvername<<"] :"<<dlerror()<< std::endl);
384 bbtkDebugMessage("package",3,"* Symbol ["<<getvername
385 <<"] found"<<std::endl);
387 if (getbbtkversion() != bbtk::GetVersion())
389 bbtkMessage("package",2,
390 "Shared library ["<<libname
391 <<"] was build with bbtk version "
393 <<" but the current program runs with version "
394 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
400 bbtkDebugMessage("package",3,"* Package bbtk version '"<<getbbtkversion()<<"' matches"<<std::endl);
401 // Loads the Package get function
402 std::string getpackname(package_name);
403 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
404 getpack = (DLGetPackageFunction)(dlsym(handler, getpackname.c_str()));
407 bbtkMessage("package",2,
408 "Shared library ["<<libname
409 <<"] is not a valid bbtk package."
410 <<" Symbol ["<<getpackname<<"] :"<<dlerror()<< std::endl);
415 bbtkDebugMessage("package",3,"* Symbol ["<<getpackname<<"] found"<<std::endl);
416 // Loads the Package delete function
418 std::string delpackname(package_name);
419 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
420 delpack = (DLDeletePackageFunction)(dlsym(handler, delpackname.c_str()));
423 bbtkMessage("package",2,
424 "Shared library ["<<libname
425 <<"] is not a valid bbtk package."
426 <<" Symbol ["<<delpackname<<"] :"<<dlerror()<< std::endl);
430 bbtkDebugMessage("package",3,"* Symbol ["<<delpackname<<"] found"<<std::endl);
431 #elif defined(_WIN32)
437 handler = LoadLibrary(libname.c_str());
440 bbtkMessage("package",2,
441 "Could not open shared library [" <<libname<<"]"
443 DWORD dwErrorCode = 0;
444 dwErrorCode = GetLastError();
445 bbtkMessage("package",2,
446 "Windows Error: [" << dwErrorCode <<"]"
452 // Loads the Package bbtk version function
453 std::string getvername(package_name);
455 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
456 DLGetPackageBBTKVersionFunction getbbtkversion
457 = (DLGetPackageBBTKVersionFunction)(GetProcAddress(handler,
458 getvername.c_str()));
461 FreeLibrary(handler);
462 bbtkMessage("package",2,
463 "Shared library ["<<libname
464 <<"] is not a valid bbtk package."
465 <<" Symbol ["<<getbbtkversion<<"] not found"<< std::endl);
470 if (getbbtkversion() != bbtk::GetVersion())
472 FreeLibrary(handler);
473 bbtkMessage("package",2,
474 "Shared library ["<<libname
475 <<"] was build with bbtk version "
477 <<" but the current program runs with version "
478 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
483 // Loads the Package get function
484 std::string getpackname(package_name);
485 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
486 getpack = (DLGetPackageFunction)(GetProcAddress(handler, getpackname.c_str()));
489 FreeLibrary(handler);
490 bbtkMessage("package",2,
491 "Shared library ["<<libname
492 <<"] is not a valid bbtk package."
493 <<" Symbol ["<<getpackname<<"] not found"<< std::endl);
497 // Loads the Package delete function
498 std::string delpackname(package_name);
499 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
500 delpack = (DLDeletePackageFunction)(GetProcAddress(handler, delpackname.c_str()));
503 FreeLibrary(handler);
504 bbtkMessage("package",2,
505 "Shared library ["<<libname
506 <<"] is not a valid bbtk package."
507 <<" Symbol ["<<delpackname<<"] not found"<< std::endl);
512 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
517 //==========================================================================
519 //==========================================================================
520 /// Loads a package from a dynamic library
521 Package::Pointer Package::CreateFromDynamicLibrary(const std::string& libname,
522 const std::string& pkgname,
523 const std::string& path)
525 bbtkDebugMessage("package",1,"==> Package::CreateFromDynamicLibrary("
526 <<libname<<")"<<std::endl);
528 DLGetPackageFunction gf;
529 DLDeletePackageFunction df;
530 DynamicLibraryHandler h = Package::OpenDynamicLibrary(libname,
533 if (h==0) return Package::Pointer();
534 Package::Pointer p = gf();
535 p->mDynamicLibraryHandler = h;
536 p->mDLDeletePackageFunction = df;
538 std::string separator =
539 ConfigurationFile::GetInstance().Get_file_separator ();
540 //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
541 std::string docreldoc =
542 separator + "bbdoc" + separator + pkgname + separator + "index.html";
544 ".." + separator + ".." + docreldoc;
545 std::string doc = path + separator + ".." + separator
546 + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
550 p->SetDocRelativeURL(reldoc);
552 bbtkDebugMessage("package",2,"<== Package::CreateFromDynamicLibrary("
553 <<libname<<") .. OK"<<std::endl);
556 //==========================================================================
561 //==========================================================================
562 /// UnLoads the package dynamic library (if any)
563 void Package::UnLoadDynamicLibrary(Package::WeakPointer pack, bool doit)
565 if (pack.expired() || (!pack.lock()->mDynamicLibraryHandler))
569 std::string packname = pack.lock()->GetName();
570 bbtkDebugMessage("package",5,"==> Package::UnLoadDynamicLibrary('"
574 if (!pack.lock()->GetBlackBoxMap().empty())
577 bbtkDebugMessage("package",5," Package not empty ... abort"
581 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
582 <<"BlackBoxMap not empty "
583 <<BBTK_INTERNAL_ERROR_MESSAGE);
588 if (pack.use_count()!=1)
590 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
591 <<"empty dl package with external refs"
592 <<BBTK_INTERNAL_ERROR_MESSAGE);
598 bbtkDebugMessage("package",5,"==> dynamic library for package '"
599 <<packname<<"' closed"
604 mReleasedDynamicallyLoadedPackages.insert(pack);
605 bbtkDebugMessage("package",1,"==> package '"<<packname
606 <<"' put in the 'to unload' list"
611 bbtkDebugMessage("package",5,"<== Package::UnLoadDynamicLibrary('"
616 //==========================================================================
618 //==========================================================================
619 /// UnLoads released packages that were loaded dynamically
620 /// see UnLoadDynamicLibrary and ReleaseBlackBoxDescriptor
621 void Package::UnLoadReleasedDynamicallyLoadedPackages()
623 bbtkDebugMessage("package",5,"==> Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
625 std::set<Package::WeakPointer>::iterator i;
628 if(mReleasedDynamicallyLoadedPackages.size()>0){
629 for (i=mReleasedDynamicallyLoadedPackages.begin();
630 i!=mReleasedDynamicallyLoadedPackages.end();
633 if (!i->expired()) UnLoad(*i);
637 bbtkDebugMessage("package",5,"<== Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
639 //==========================================================================
641 //==========================================================================
642 void Package::UnLoad(Package::WeakPointer pack)
644 std::string packname = pack.lock()->GetName();
645 bbtkDebugMessage("package",6,"==> Package::UnLoad("<<packname<<")"<<std::endl);
647 Package* p = pack.lock().get();
649 DynamicLibraryHandler h = p->mDynamicLibraryHandler;
651 // deletes the package
652 p->mDLDeletePackageFunction();
654 // closes the dl handler
655 #if defined(__GNUC__)
657 #elif defined(_WIN32)
661 bbtkDebugMessage("package",1,"==> dynamic library for package '"
662 <<packname<<"' closed"
664 bbtkDebugMessage("package",6," ... dynamic library unloaded"<<std::endl);
666 //==========================================================================
668 //==========================================================================
669 /// Creates an instance of a black box of type <type> with name <name>
670 BlackBox::Pointer Package::NewBlackBox(const std::string& type,
671 const std::string& name) const
673 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::NewBlackBox(\""<<type<<"\",\""<<name<<"\")"<<bbtkendl);
675 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(type);
676 if (i == mBlackBoxMap.end())
678 bbtkDebugDecTab("Kernel",8);
679 return BlackBox::Pointer();
681 BlackBox::Pointer bb =i->second->NewBlackBox(name);
682 bbtkDebugDecTab("Kernel",8);
686 //==========================================================================
690 //==========================================================================
691 /// Creates an instance of an adaptor of input type <typein> and
692 /// output type <typeout> with name <name>
693 BlackBox::Pointer Package::NewAdaptor(const DataInfo& typein,
694 const DataInfo& typeout,
695 const std::string& name) const
697 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
701 <<name<<"\")"<<bbtkendl);
703 AdaptorKey key(typein,typeout,
704 BlackBoxDescriptor::DEFAULT_ADAPTOR);
705 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
706 if (i == mAdaptorMap.end())
708 bbtkDebugDecTab("Kernel",8);
709 return BlackBox::Pointer();
711 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
712 bbtkDebugDecTab("Kernel",8);
716 //==========================================================================
718 //==========================================================================
719 /// Creates an instance of an adaptor of input type <typein> and
720 /// output type <typeout> with name <name>
721 BlackBox::Pointer Package::NewWidgetAdaptor(const DataInfo& typein,
722 const DataInfo& typeout,
723 const std::string& name) const
725 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
726 ">::NewWidgetAdaptor("
729 <<name<<"\")"<<bbtkendl);
731 AdaptorKey key(typein,typeout,
732 BlackBoxDescriptor::DEFAULT_GUI);
733 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
734 if (i == mAdaptorMap.end())
736 bbtkDebugDecTab("Kernel",8);
737 return BlackBox::Pointer();
739 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
740 bbtkDebugDecTab("Kernel",8);
744 //==========================================================================
748 //==========================================================================
749 /// Returns true is the package contains
750 /// an adaptor of input type <typein> and
751 /// output type <typeout>
752 /// If successfull then adaptor contains the black box type name
753 bool Package::FindWidgetAdaptor(const DataInfo& typein,
754 const DataInfo& typeout,
755 std::string& adaptor) const
757 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
758 ">::FindWidgetAdaptor("
760 <<typeout<<")"<<bbtkendl);
762 AdaptorKey key(/*typein*/
763 DataInfo(typeid(void),""),
765 BlackBoxDescriptor::DEFAULT_GUI);
766 // First try to find a single widget 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 //==========================================================================
782 //==========================================================================
783 /// Returns true is the package contains
784 /// an adaptor of input type <typein> and
785 /// output type <typeout>
786 /// If successfull then adaptor contains the black box type name
787 bool Package::FindAdaptor(const DataInfo& typein,
788 const DataInfo& typeout,
789 std::string& adaptor) const
791 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
794 <<typeout<<")"<<bbtkendl);
796 AdaptorKey key(typein,typeout,
797 BlackBoxDescriptor::DEFAULT_ADAPTOR);
798 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
799 if (i == mAdaptorMap.end())
801 bbtkDebugDecTab("Kernel",8);
804 adaptor = i->second.lock()->GetTypeName();
805 bbtkDebugDecTab("Kernel",8);
809 //==========================================================================
812 //==========================================================================
813 /// Registers a black box descriptor in the package
814 bool Package::RegisterBlackBox(BlackBoxDescriptor::Pointer d)
816 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\")"<<std::endl);
818 BlackBoxMapType::iterator i = mBlackBoxMap.find(d->GetTypeName());
819 if (i!=mBlackBoxMap.end())
821 bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
822 <<d->GetTypeName()<<"> which is already in the package");
826 mBlackBoxMap[d->GetTypeName()] = d;
828 d->SetPackage(GetThisPointer<Package>());
830 // If it is a default adaptor, also register it in the adaptors map
831 if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
833 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);
835 TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
836 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
837 DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
838 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
839 AdaptorKey key(infoin,infoout,d->GetKind());
841 AdaptorMapType::const_iterator i;
842 i = mAdaptorMap.find(key);
843 if (i == mAdaptorMap.end())
845 mAdaptorMap[key] = d;
847 // If already an adaptor registered : error
850 if (i->second.lock()->GetTypeName() != d->GetTypeName())
852 bbtkError("Package <"<<GetName()<<
853 "> : trying to register black box <"
855 <<"> as default adaptor but there is already a default adaptor registered (<"
856 <<i->second.lock()->GetTypeName()<<">)");
860 // If it is a default adaptor, also register it in the adaptors map
861 else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
863 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is a widget adaptor, inserting it in adaptors map ..."<<std::endl);
865 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
866 DataInfo infoin(typeid(void),"");
867 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
868 AdaptorKey key(infoin,infoout,d->GetKind());
870 AdaptorMapType::const_iterator i;
871 i = mAdaptorMap.find(key);
872 if (i == mAdaptorMap.end())
874 mAdaptorMap[key] = d;
876 // If already an adaptor registered : error
879 if (i->second.lock()->GetTypeName() != d->GetTypeName())
881 bbtkError("Package <"<<GetName()<<
882 "> : trying to register black box <"
884 <<"> as default widget adaptor but there is already a default adaptor registered (<"
885 <<i->second.lock()->GetTypeName()<<">)");
891 bbtkDebugDecTab("Kernel",8);
895 //==========================================================================
897 //===================================================================
898 void Package::CheckBoxes() const
900 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
901 <<" ["<<GetName()<<"]"<<std::endl);
902 BlackBoxMapType::const_iterator i;
903 for (i=mBlackBoxMap.begin();
904 i!=mBlackBoxMap.end();
907 i->second->Check(true);
909 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
910 <<" ["<<GetName()<<"] ... OK"<<std::endl);
912 //===================================================================
915 //==========================================================================
916 /// Changes the name of a black box type
917 void Package::ChangeBlackBoxName( const std::string& oldname, const std::string& newname )
919 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::ChangeBlackBoxName(\""<<oldname<<"\",\""<<newname<<"\")"<<std::endl);
920 // Looking into the bb map
921 BlackBoxMapType::iterator i = mBlackBoxMap.find(oldname);
922 if (i == mBlackBoxMap.end())
924 bbtkDebugDecTab("Kernel",8);
925 bbtkError("ChangeBlackBoxName : The package <"<<GetName()<<"> does not contains the black box <"<<oldname<<">");
928 i->second->SetTypeName(newname);
929 mBlackBoxMap[newname] = i->second;
930 mBlackBoxMap.erase(i);
932 bbtkDebugDecTab("Kernel",8);
934 //==========================================================================
938 //==========================================================================
939 /// Displays the list of black boxes of the package
940 void Package::PrintBlackBoxes(bool description, bool adaptors) const
942 unsigned int lmax = 0;
943 std::vector<std::string> names;
944 std::vector<std::string> kinds;
945 std::vector<std::string> descrs;
947 BlackBoxMapType::const_iterator i;
948 for (i=mBlackBoxMap.begin();
949 i!=mBlackBoxMap.end();
953 ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) )
955 std::string name(" ");
956 name += i->second->GetTypeName();
957 names.push_back(name);
960 if ( i->second->GetKind() == BlackBoxDescriptor::ADAPTOR )
962 kind = std::string("[A]");
964 else if ( i->second->GetKind() ==
965 BlackBoxDescriptor::DEFAULT_ADAPTOR )
967 kind = std::string("[DA]");
969 kinds.push_back(kind);
971 unsigned int l = name.size()+kind.size();
972 if (l>lmax) lmax = l;
978 descr += i->second->GetDescription();
980 descrs.push_back(descr);
986 offs.append(lmax+3,' ');
987 std::vector<std::string>::iterator ni,ci,di;
988 for (ni = names.begin(), ci = kinds.begin(), di = descrs.begin();
989 ni != names.end(); ++ni, ++ci, ++di)
992 space.append(lmax - ni->size() - ci->size(),' ');
993 bbtkMessage("Help",1,*ni << space << *ci );
995 unsigned int dmax = 75 - lmax;
996 // while (d.size() > dmax )
999 bbtkMessage("Help",1,d.substr(0,dmax) << "..." << std::endl);
1001 bbtkMessage("Help",1,d << std::endl);
1002 // d = d.substr(dmax,d.size());
1007 //==========================================================================
1009 //==========================================================================
1010 /// Displays the list of adaptors of the package
1011 void Package::PrintAdaptors(bool description) const
1013 BlackBoxMapType::const_iterator i;
1014 for (i=mBlackBoxMap.begin();
1015 i!=mBlackBoxMap.end();
1018 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD )
1020 bbtkMessage("Help",1,
1021 " "<<i->second->GetTypeName());
1022 if ( i->second->GetKind() ==
1023 BlackBoxDescriptor::DEFAULT_ADAPTOR )
1025 bbtkMessage("Help",1,
1030 bbtkMessage("Help",1,
1031 " : "<<i->second->GetDescription());
1034 bbtkMessage("Help",1,std::endl);
1038 AdaptorMapType::const_iterator i;
1039 for (i=mAdaptorMap.begin();
1040 i!=mAdaptorMap.end();
1043 bbtkMessage("Help",1,
1044 " "<<i->second->GetTypeName());
1047 bbtkMessage("Help",1,
1048 " : "<<i->second->GetDescription());
1051 bbtkMessage("Help",1,std::endl);
1055 //==========================================================================
1057 //==========================================================================
1058 /// Prints help on a black box
1059 void Package::HelpBlackBox(const std::string& name, bool full) const
1061 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1062 <<name<<"\")"<<bbtkendl);
1064 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1065 if (i == mBlackBoxMap.end())
1067 bbtkDebugDecTab("Kernel",8);
1068 bbtkError("The package <"<<GetName()<<"> does not contains the black box <"<<name<<">");
1070 // bbtkMessage("Help",1,"["<<GetName()<<"] ");
1071 i->second->GetHelp(full);
1072 bbtkDebugDecTab("Kernel",8);
1075 //==========================================================================
1078 //==========================================================================
1079 /// Returns true iff the package contains the box of name boxname
1080 bool Package::ContainsBlackBox(const std::string& name) const
1082 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1083 <<name<<"\")"<<bbtkendl);
1085 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1086 if (i == mBlackBoxMap.end())
1088 bbtkDebugDecTab("Kernel",8);
1091 bbtkDebugDecTab("Kernel",8);
1094 //==========================================================================
1098 //==========================================================================
1099 void Package::CreateHtmlPage(const std::string& filename,
1100 const std::string& caller,
1101 const std::string& source,
1102 const std::string& custom_header,
1103 const std::string& custom_title,
1106 bool relative_link ) const
1108 bbtkDebugMessageInc("Kernel",9,"Package<"<<GetName()<<">::CreateHtmlPage(\""
1109 <<filename<<"\")"<<bbtkendl);
1111 //---------------------
1114 s.open(filename.c_str());
1117 bbtkError("Package "<<GetName()<<" : CreateHtmlPage : could not open file '"<<filename<<"'");
1120 //----------------------
1122 std::string title = "BBTK Package "+GetName()+" "+GetVersion();
1124 if (custom_title.length() != 0) title = custom_title;
1126 s << "<html lang=\"en\">\n";
1128 s << "<title>" << title << "</title>\n";
1129 s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1130 s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1131 s << "<meta name=\"generator\" content=\"\">\n";
1132 s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1133 //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1134 s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1135 s << "pre.display { font-family:inherit }\n";
1136 s << "pre.format { font-family:inherit }\n";
1137 s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1138 s << "pre.smallformat { font-family:inherit; font-size:smaller }\n";
1139 s << "pre.smallexample { font-size:smaller }\n";
1140 s << "pre.smalllisp { font-size:smaller }\n";
1141 s << "span.sc { font-variant:small-caps }\n";
1142 s << "span.roman { font-family:serif; font-weight:normal; } \n";
1143 s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n";
1144 s << "--></style>\n";
1146 //----------------------
1148 //----------------------
1151 s << "<a name=\"Top\"></a>\n";
1153 //----------------------
1155 if ( custom_header.length() != 0)
1157 if ( custom_header != "none" )
1160 in.open(custom_header.c_str());
1163 bbtkError("Could not open file \""<<custom_header<<"\"");
1168 in.getline(buffer,512);
1169 std::string line(buffer);
1176 s << "<object data=\"" << custom_header
1177 << "\" type = \"text/html\"\"style=\"width: 1200px; height: 400px;\"> Warning: "
1178 << custom_header <<" could not be embedded.</object>\n";
1187 s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1188 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1189 s << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1190 << GetDescription() << "</TD></TR>\n";
1191 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1192 << GetAuthor() << "</TD></TR>\n";
1193 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1194 << GetCategory() << "</TD></TR>\n";
1195 s << "<TR><TD style='vertical-align: top;'><b> Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1196 << GetVersion() << "</TD></TR>\n";
1197 s << "<TR><TD style='vertical-align: top;'><b> bbtk Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1198 << bbtk::GetVersion() << "</TD></TR>\n";
1202 //-------------------
1203 // Table of contents
1205 // s << "<div class=\"contents\">\n";
1206 s << "<p><b> Black Boxes : </b>\n";
1209 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1211 BlackBoxMapType::const_iterator i;
1212 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i)
1214 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD)
1217 std::string name = i->second->GetTypeName();
1218 Utilities::html_format(name);
1219 std::string descr = i->second->GetDescription();
1220 //Utilities::html_format(descr);
1223 s << "<TD style='vertical-align: top;'>";
1224 s << " <a name=\"toc_"<<name
1225 <<"\" href=\"#"<<name<<"\">"
1228 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1237 //-------------------
1239 if (mAdaptorMap.size()>0)
1241 // s << "<div class=\"contents\">\n";
1242 s << "<p><b> Adaptors : </b>\n";
1245 // BlackBoxMapType::const_iterator i;
1246 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1247 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end();++i)
1249 if ( i->second->GetKind() == BlackBoxDescriptor::STANDARD)
1252 std::string name = i->second->GetTypeName();
1253 Utilities::html_format(name);
1254 std::string descr = i->second->GetDescription();
1257 s << "<TD style='vertical-align: top;'>";
1258 s << " <a name=\"toc_"<<name
1259 <<"\" href=\"#"<<name<<"\">"
1262 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1272 // s << "<div class=\"node\">\n";
1274 // s << "<p><hr>\n";
1275 // s << "<a name=\"Top\"></a>\n";
1276 // s << "Top: <a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
1277 // s << "Previous: <a rel="previous" accesskey="p" href="#dir">(dir)</a>,
1278 // s << "Up: <a rel="up" accesskey="u" href="#dir">(dir)</a>
1282 //----------------------
1285 //-------------------
1286 // Computes output directory from filename to pass it to
1287 // BlackBoxDescriptor::InsertHtmlHelp
1290 std::string::size_type slash_position = filename.find_last_of("/\\");
1293 if (slash_position != std::string::npos) {
1294 if (slash_position == 0)
1296 dir = filename.substr(0,slash_position);
1299 for (i=mBlackBoxMap.begin();
1300 i!=mBlackBoxMap.end();
1303 i->second->InsertHtmlHelp(s,detail,level,dir,relative_link);
1306 //----------------------
1311 ptm = gmtime ( &rawtime );
1314 s << "Automatically generated by <b>"<<caller<<"</b> "//from <b>"
1317 << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900
1318 << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1319 s << "</body></html>\n";
1321 //----------------------
1324 bbtkDebugDecTab("Kernel",9);
1326 //==========================================================================
1328 //==========================================================================
1329 std::string Package::GetObjectName() const
1331 return std::string("Package '")+mName+std::string("'");
1333 //==========================================================================
1335 //==========================================================================
1336 std::string Package::GetObjectInfo() const
1338 std::stringstream i;
1339 i << " - "<<mBlackBoxMap.size() << " boxes" << std::endl;
1340 if (mDynamicLibraryHandler)
1342 i<< " - Loaded from dynamic library"<<std::endl;
1346 //==========================================================================
1349 //==========================================================================
1350 size_t Package::GetObjectSize() const
1352 size_t s = Superclass::GetObjectSize();
1353 s += Package::GetObjectInternalSize();
1356 //==========================================================================
1357 //==========================================================================
1358 size_t Package::GetObjectInternalSize() const
1360 size_t s = sizeof(Package);
1363 //==========================================================================
1364 //==========================================================================
1365 size_t Package::GetObjectRecursiveSize() const
1367 size_t s = Superclass::GetObjectRecursiveSize();
1368 s += Package::GetObjectInternalSize();
1370 BlackBoxMapType::const_iterator i;
1371 for (i = mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i )
1373 s += i->second->GetObjectRecursiveSize();
1377 //==========================================================================
1379 //==========================================================================
1380 std::set<Package::WeakPointer>
1381 Package::mReleasedDynamicallyLoadedPackages;
1382 //==========================================================================