2 /*=========================================================================
4 Module: $RCSfile: bbtkPackage.cxx,v $
6 Date: $Date: 2009/04/21 14:36:51 $
7 Version: $Revision: 1.25 $
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::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::~Package(\""<<mName<<"\")"<<bbtkendl);
115 bbtkDebugMessage("object",2,"<== Package::~Package(\""<<mName<<"\")"<<bbtkendl);
117 //==========================================================================
120 //==========================================================================
121 void PackageReleaseBlackBoxDescriptorInternal(Package::WeakPointer pack,
122 const std::string& descname)
124 // Try to release descriptor
125 std::string packname = pack.lock()->GetName();
127 bbtkDebugMessage("package",5,"--- Releasing descriptor '"
128 <<packname<<"::"<<descname<<"'"<<bbtkendl);
131 Package::BlackBoxMapType::iterator desc =
132 pack.lock()->GetBlackBoxMap().find(descname);
133 if (desc == pack.lock()->GetBlackBoxMap().end())
135 bbtkDebugMessage("package",5,
136 " Descriptor has already been released"
140 // bbtkDebugMessage("package",3,
141 // " Trying unreferencing it ... "<<std::endl);
142 BlackBoxDescriptor::WeakPointer pdesc = desc->second;
143 desc->second.reset();
144 // if it is dead : remove it
147 bbtkDebugMessage("package",2," ==> '"<<packname<<"::"<<descname<<"' Descriptor expired"<<bbtkendl);
150 bbtkDebugMessage("package",2,
151 " ... and caused its package death"
155 desc = pack.lock()->GetBlackBoxMap().find(descname);
156 if (desc != pack.lock()->GetBlackBoxMap().end())
157 pack.lock()->GetBlackBoxMap().erase(desc);
161 bbtkDebugMessage("package",5," ... Descriptor still alive ("
162 <<pdesc.use_count()<<" refs)"
164 pack.lock()->GetBlackBoxMap()[descname] = pdesc.lock();
167 //==========================================================================
170 //==========================================================================
172 void Package::Release(Package::WeakPointer pack)
174 std::string packname = pack.lock()->mName;
175 bbtkDebugMessage("package",1,"==> Package::Release('"<<
176 packname<<"')"<<bbtkendl);
178 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
179 long ndesc = pack.lock()->GetBlackBoxMap().size();
180 long nrefs = pack.use_count();
182 bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
183 <<ndesc<<" descr / dyn="
186 // A package is "free" from any external reference iff :
187 // i) It is not dynamically loaded and nrefs == ndesc
188 // (each desc references its package) or
189 // ii) It is dynamically loaded and nrefs == ndesc + 1
190 // (A dynamic library holds a static pointer on the package it contains
191 // which is allocated when the PACKAGENAMEGetPackage() func is called,
192 // and descallocated (reset) by PACKAGENAMEDeletePackage())
193 if (nrefs == ndesc + dyn)
195 bbtkDebugMessage("package",5,
196 " -> No more external ref : checking descriptors"
198 // We must take care that removing refs on descriptors
199 // can lead to their deletion which can in turn unref
200 // internal boxes which can release their descriptors hence
201 // call Package::ReleaseBlackBoxDescriptor
202 // As a consequence during descriptors release :
203 // 1) The map can change dynamically : we cannot iterate over it
204 // as any iterator can become invalid
205 // 2) The package can auto-destruct : we must test its existence
206 // after each release
207 // We must also take care of not locking the package pointer
208 // or any ref count check in Package::ReleaseBlackBoxDescriptor
211 // The list of descriptors names at start
212 std::vector<std::string> descnamelist;
213 BlackBoxMapType::iterator i;
214 for (i=pack.lock()->mBlackBoxMap.begin();
215 i!= pack.lock()->mBlackBoxMap.end();
217 descnamelist.push_back(i->first);
219 // Iterator over the initial names
220 std::vector<std::string>::iterator descname;
221 for (descname=descnamelist.begin();
222 descname!=descnamelist.end();
225 // Is package still alive ?
228 bbtkDebugMessage("package",1,"--- Package::Release('"<<
230 <<"') : package expired during release : bailing out"<<bbtkendl);
234 PackageReleaseBlackBoxDescriptorInternal(pack,*descname);
239 UnLoadDynamicLibrary(pack);
240 // Unload orphan dl packages
241 Package::UnLoadReleasedDynamicallyLoadedPackages();
248 #ifdef BBTK_COMPILE_DEBUG_MESSAGES
250 bbtkDebugMessage("package",2,"<== Package::Release('"<<
251 packname<<"')"<<bbtkendl);
255 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
256 long ndesc = pack.lock()->GetBlackBoxMap().size();
257 long nrefs = pack.use_count();
259 bbtkDebugMessage("package",1," ... Package still alive ("
261 <<ndesc<<" descr / dyn="
262 <<dyn<<")"<<std::endl);
266 bbtkDebugMessage("package",1," ... Package has been released"
271 //==========================================================================
273 //==========================================================================
274 /// "Releases" the package
275 /// Signals the package that it can free the given descriptor
276 /// if they are no more used and free itself if it is no
278 /// Note : Any non-weak pointer on the package must have been freed
279 void Package::ReleaseBlackBoxDescriptor(Package::WeakPointer pack,
280 BlackBoxDescriptor::WeakPointer descr)
282 std::string packname = pack.lock()->mName;
283 std::string dname = descr.lock()->GetTypeName();
284 bbtkDebugMessage("package",3,"==> Package::ReleaseBlackBoxDescriptor('"<<
285 packname<<"','"<<dname<<"') : refs="
286 <<descr.use_count()<<bbtkendl);
288 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
289 long ndesc = pack.lock()->GetBlackBoxMap().size();
290 long nrefs = pack.use_count();
292 bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
293 <<ndesc<<" descr / dynamically loaded = "
296 // A package is "free" from any external reference iff :
297 // i) It is not dynamically loaded and nrefs == ndesc
298 // (each desc references its package) or
299 // ii) It is dynamically loaded and nrefs == ndesc + 1
300 // (A dynamic library holds a static pointer on the package it contains
301 // which is allocated when the PACKAGENAMEGetPackage() func is called,
302 // and descallocated (reset) by PACKAGENAMEDeletePackage())
303 if (nrefs == ndesc + dyn)
305 PackageReleaseBlackBoxDescriptorInternal(pack,dname);
308 // If the package is released and dynamically loaded
309 // then put it in the static list mReleasedDynamicallyLoadedPackages
310 UnLoadDynamicLibrary(pack,false);
312 bbtkDebugMessage("package",4,"<== Package::ReleaseBlackBoxDescriptor('"<<
313 packname<<"','"<<dname<<"'): refs="
314 <<descr.use_count()<<bbtkendl);
318 long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0;
319 long ndesc = pack.lock()->GetBlackBoxMap().size();
320 long nrefs = pack.use_count();
322 bbtkDebugMessage("package",3," ... Package still alive ("
324 <<ndesc<<" descr / dyn="
325 <<dyn<<")"<<std::endl);
329 bbtkDebugMessage("package",3," ... Package has been released"
334 //==========================================================================
336 //==========================================================================
337 /// Opens a dynamic library which contains a bbtk package
338 /// Returns the handler
339 /// Load the package management symbols from the lib
340 /// returns false if a problem occured hence can be used
341 /// to test that a dyn lib is a valid bbtk package lib
342 /// NB : The BBTK version exported from the library
343 /// is tested against the current bbtk version
344 DynamicLibraryHandler Package::OpenDynamicLibrary
345 ( const std::string& libname,
346 const std::string& package_name,
347 DLGetPackageFunction& getpack,
348 DLDeletePackageFunction& delpack)
350 bbtkDebugMessage("package",3,"==> Package::OpenDynamicLibrary("
351 <<libname<<")"<<std::endl);
352 #if defined(__GNUC__)
356 handler = dlopen(libname.c_str(),
357 BBTK_RTLD_TIME | BBTK_RTLD_SCOPE );
360 bbtkMessage("package",2,
361 "Could not open shared library [" <<libname<<"] : "
362 <<dlerror() << std::endl);
366 bbtkDebugMessage("package",3,"* Shared lib ["<<libname<<"] open"<<std::endl);
368 // Loads the Package bbtk version function
369 std::string getvername(package_name);
371 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
372 DLGetPackageBBTKVersionFunction getbbtkversion
373 = (DLGetPackageBBTKVersionFunction)(dlsym(handler,getvername.c_str()));
376 bbtkDebugMessage("package",3,"***"<<std::endl);
377 bbtkMessage("package",2,
378 "Shared library ["<<libname
379 <<"] is not a valid bbtk package."
380 <<" Symbol ["<<getvername<<"] :"<<dlerror()<< std::endl);
385 bbtkDebugMessage("package",3,"* Symbol ["<<getvername
386 <<"] found"<<std::endl);
388 if (getbbtkversion() != bbtk::GetVersion())
390 bbtkMessage("package",2,
391 "Shared library ["<<libname
392 <<"] was build with bbtk version "
394 <<" but the current program runs with version "
395 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
401 bbtkDebugMessage("package",3,"* Package bbtk version '"<<getbbtkversion()<<"' matches"<<std::endl);
402 // Loads the Package get function
403 std::string getpackname(package_name);
404 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
405 getpack = (DLGetPackageFunction)(dlsym(handler, getpackname.c_str()));
408 bbtkMessage("package",2,
409 "Shared library ["<<libname
410 <<"] is not a valid bbtk package."
411 <<" Symbol ["<<getpackname<<"] :"<<dlerror()<< std::endl);
416 bbtkDebugMessage("package",3,"* Symbol ["<<getpackname<<"] found"<<std::endl);
417 // Loads the Package delete function
419 std::string delpackname(package_name);
420 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
421 delpack = (DLDeletePackageFunction)(dlsym(handler, delpackname.c_str()));
424 bbtkMessage("package",2,
425 "Shared library ["<<libname
426 <<"] is not a valid bbtk package."
427 <<" Symbol ["<<delpackname<<"] :"<<dlerror()<< std::endl);
431 bbtkDebugMessage("package",3,"* Symbol ["<<delpackname<<"] found"<<std::endl);
432 #elif defined(_WIN32)
438 handler = LoadLibrary(libname.c_str());
441 bbtkMessage("package",2,
442 "Could not open shared library [" <<libname<<"]"
444 DWORD dwErrorCode = 0;
445 dwErrorCode = GetLastError();
446 bbtkMessage("package",2,
447 "Windows Error: [" << dwErrorCode <<"]"
453 // Loads the Package bbtk version function
454 std::string getvername(package_name);
456 BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
457 DLGetPackageBBTKVersionFunction getbbtkversion
458 = (DLGetPackageBBTKVersionFunction)(GetProcAddress(handler,
459 getvername.c_str()));
462 FreeLibrary(handler);
463 bbtkMessage("package",2,
464 "Shared library ["<<libname
465 <<"] is not a valid bbtk package."
466 <<" Symbol ["<<getbbtkversion<<"] not found"<< std::endl);
471 if (getbbtkversion() != bbtk::GetVersion())
473 FreeLibrary(handler);
474 bbtkMessage("package",2,
475 "Shared library ["<<libname
476 <<"] was build with bbtk version "
478 <<" but the current program runs with version "
479 <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
484 // Loads the Package get function
485 std::string getpackname(package_name);
486 getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
487 getpack = (DLGetPackageFunction)(GetProcAddress(handler, getpackname.c_str()));
490 FreeLibrary(handler);
491 bbtkMessage("package",2,
492 "Shared library ["<<libname
493 <<"] is not a valid bbtk package."
494 <<" Symbol ["<<getpackname<<"] not found"<< std::endl);
498 // Loads the Package delete function
499 std::string delpackname(package_name);
500 delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
501 delpack = (DLDeletePackageFunction)(GetProcAddress(handler, delpackname.c_str()));
504 FreeLibrary(handler);
505 bbtkMessage("package",2,
506 "Shared library ["<<libname
507 <<"] is not a valid bbtk package."
508 <<" Symbol ["<<delpackname<<"] not found"<< std::endl);
513 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
518 //==========================================================================
520 //==========================================================================
521 /// Loads a package from a dynamic library
522 Package::Pointer Package::CreateFromDynamicLibrary(const std::string& libname,
523 const std::string& pkgname,
524 const std::string& path)
526 bbtkDebugMessage("package",1,"==> Package::CreateFromDynamicLibrary("
527 <<libname<<")"<<std::endl);
529 DLGetPackageFunction gf;
530 DLDeletePackageFunction df;
531 DynamicLibraryHandler h = Package::OpenDynamicLibrary(libname,
534 if (h==0) return Package::Pointer();
535 Package::Pointer p = gf();
536 p->mDynamicLibraryHandler = h;
537 p->mDLDeletePackageFunction = df;
539 std::string separator =
540 ConfigurationFile::GetInstance().Get_file_separator ();
541 //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
542 std::string docreldoc =
543 separator + "bbdoc" + separator + pkgname + separator + "index.html";
545 ".." + separator + ".." + docreldoc;
546 std::string doc = path + separator + ".." + separator
547 + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
551 p->SetDocRelativeURL(reldoc);
553 bbtkDebugMessage("package",2,"<== Package::CreateFromDynamicLibrary("
554 <<libname<<") .. OK"<<std::endl);
557 //==========================================================================
562 //==========================================================================
563 /// UnLoads the package dynamic library (if any)
564 void Package::UnLoadDynamicLibrary(Package::WeakPointer pack, bool doit)
566 if (pack.expired() || (!pack.lock()->mDynamicLibraryHandler))
570 std::string packname = pack.lock()->GetName();
571 bbtkDebugMessage("package",5,"==> Package::UnLoadDynamicLibrary('"
575 if (!pack.lock()->GetBlackBoxMap().empty())
578 bbtkDebugMessage("package",5," Package not empty ... abort"
582 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
583 <<"BlackBoxMap not empty "
584 <<BBTK_INTERNAL_ERROR_MESSAGE);
589 if (pack.use_count()!=1)
591 bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
592 <<"empty dl package with external refs"
593 <<BBTK_INTERNAL_ERROR_MESSAGE);
599 bbtkDebugMessage("package",5,"==> dynamic library for package '"
600 <<packname<<"' closed"
605 mReleasedDynamicallyLoadedPackages.insert(pack);
606 bbtkDebugMessage("package",1,"==> package '"<<packname
607 <<"' put in the 'to unload' list"
612 bbtkDebugMessage("package",5,"<== Package::UnLoadDynamicLibrary('"
617 //==========================================================================
619 //==========================================================================
620 /// UnLoads released packages that were loaded dynamically
621 /// see UnLoadDynamicLibrary and ReleaseBlackBoxDescriptor
622 void Package::UnLoadReleasedDynamicallyLoadedPackages()
624 bbtkDebugMessage("package",5,"==> Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
626 std::set<Package::WeakPointer>::iterator i;
629 if(mReleasedDynamicallyLoadedPackages.size()>0){
630 for (i=mReleasedDynamicallyLoadedPackages.begin();
631 i!=mReleasedDynamicallyLoadedPackages.end();
634 if (!i->expired()) UnLoad(*i);
638 bbtkDebugMessage("package",5,"<== Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
640 //==========================================================================
642 //==========================================================================
643 void Package::UnLoad(Package::WeakPointer pack)
645 std::string packname = pack.lock()->GetName();
646 bbtkDebugMessage("package",6,"==> Package::UnLoad("<<packname<<")"<<std::endl);
648 Package* p = pack.lock().get();
650 DynamicLibraryHandler h = p->mDynamicLibraryHandler;
652 // deletes the package
653 p->mDLDeletePackageFunction();
655 // closes the dl handler
656 #if defined(__GNUC__)
658 #elif defined(_WIN32)
662 bbtkDebugMessage("package",1,"==> dynamic library for package '"
663 <<packname<<"' closed"
665 bbtkDebugMessage("package",6," ... dynamic library unloaded"<<std::endl);
667 //==========================================================================
669 //==========================================================================
670 /// Creates an instance of a black box of type <type> with name <name>
671 BlackBox::Pointer Package::NewBlackBox(const std::string& type,
672 const std::string& name) const
674 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::NewBlackBox(\""<<type<<"\",\""<<name<<"\")"<<bbtkendl);
676 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(type);
677 if (i == mBlackBoxMap.end())
679 bbtkDebugDecTab("Kernel",8);
680 return BlackBox::Pointer();
682 BlackBox::Pointer bb =i->second->NewBlackBox(name);
683 bbtkDebugDecTab("Kernel",8);
687 //==========================================================================
691 //==========================================================================
692 /// Creates an instance of an adaptor of input type <typein> and
693 /// output type <typeout> with name <name>
694 BlackBox::Pointer Package::NewAdaptor(const DataInfo& typein,
695 const DataInfo& typeout,
696 const std::string& name) const
698 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
702 <<name<<"\")"<<bbtkendl);
704 AdaptorKey key(typein,typeout,
705 BlackBoxDescriptor::DEFAULT_ADAPTOR);
706 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
707 if (i == mAdaptorMap.end())
709 bbtkDebugDecTab("Kernel",8);
710 return BlackBox::Pointer();
712 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
713 bbtkDebugDecTab("Kernel",8);
717 //==========================================================================
719 //==========================================================================
720 /// Creates an instance of an adaptor of input type <typein> and
721 /// output type <typeout> with name <name>
722 BlackBox::Pointer Package::NewWidgetAdaptor(const DataInfo& typein,
723 const DataInfo& typeout,
724 const std::string& name) const
726 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
727 ">::NewWidgetAdaptor("
730 <<name<<"\")"<<bbtkendl);
732 AdaptorKey key(typein,typeout,
733 BlackBoxDescriptor::DEFAULT_GUI);
734 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
735 if (i == mAdaptorMap.end())
737 bbtkDebugDecTab("Kernel",8);
738 return BlackBox::Pointer();
740 BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
741 bbtkDebugDecTab("Kernel",8);
745 //==========================================================================
749 //==========================================================================
750 /// Returns true is the package contains
751 /// an adaptor of input type <typein> and
752 /// output type <typeout>
753 /// If successfull then adaptor contains the black box type name
754 bool Package::FindWidgetAdaptor(const DataInfo& typein,
755 const DataInfo& typeout,
756 std::string& adaptor) const
758 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
759 ">::FindWidgetAdaptor("
761 <<typeout<<")"<<bbtkendl);
763 AdaptorKey key(/*typein*/
764 DataInfo(typeid(void),""),
766 BlackBoxDescriptor::DEFAULT_GUI);
767 // First try to find a single widget adaptor
768 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
769 if (i == mAdaptorMap.end())
771 bbtkDebugDecTab("Kernel",8);
774 adaptor = i->second.lock()->GetTypeName();
775 bbtkDebugDecTab("Kernel",8);
779 //==========================================================================
783 //==========================================================================
784 /// Returns true is the package contains
785 /// an adaptor of input type <typein> and
786 /// output type <typeout>
787 /// If successfull then adaptor contains the black box type name
788 bool Package::FindAdaptor(const DataInfo& typein,
789 const DataInfo& typeout,
790 std::string& adaptor) const
792 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
795 <<typeout<<")"<<bbtkendl);
797 AdaptorKey key(typein,typeout,
798 BlackBoxDescriptor::DEFAULT_ADAPTOR);
799 AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
800 if (i == mAdaptorMap.end())
802 bbtkDebugDecTab("Kernel",8);
805 adaptor = i->second.lock()->GetTypeName();
806 bbtkDebugDecTab("Kernel",8);
810 //==========================================================================
813 //==========================================================================
814 /// Registers a black box descriptor in the package
815 bool Package::RegisterBlackBox(BlackBoxDescriptor::Pointer d)
817 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\")"<<std::endl);
819 BlackBoxMapType::iterator i = mBlackBoxMap.find(d->GetTypeName());
820 if (i!=mBlackBoxMap.end())
822 bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
823 <<d->GetTypeName()<<"> which is already in the package");
827 mBlackBoxMap[d->GetTypeName()] = d;
829 d->SetPackage(GetThisPointer<Package>());
831 // If it is a default adaptor, also register it in the adaptors map
832 if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
834 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);
836 TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
837 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
838 DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
839 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
840 AdaptorKey key(infoin,infoout,d->GetKind());
842 AdaptorMapType::const_iterator i;
843 i = mAdaptorMap.find(key);
844 if (i == mAdaptorMap.end())
846 mAdaptorMap[key] = d;
848 // If already an adaptor registered : error
851 if (i->second.lock()->GetTypeName() != d->GetTypeName())
853 bbtkError("Package <"<<GetName()<<
854 "> : trying to register black box <"
856 <<"> as default adaptor but there is already a default adaptor registered (<"
857 <<i->second.lock()->GetTypeName()<<">)");
861 // If it is a default adaptor, also register it in the adaptors map
862 else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
864 bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is a widget adaptor, inserting it in adaptors map ..."<<std::endl);
866 TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
867 DataInfo infoin(typeid(void),"");
868 DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
869 AdaptorKey key(infoin,infoout,d->GetKind());
871 AdaptorMapType::const_iterator i;
872 i = mAdaptorMap.find(key);
873 if (i == mAdaptorMap.end())
875 mAdaptorMap[key] = d;
877 // If already an adaptor registered : error
880 if (i->second.lock()->GetTypeName() != d->GetTypeName())
882 bbtkError("Package <"<<GetName()<<
883 "> : trying to register black box <"
885 <<"> as default widget adaptor but there is already a default adaptor registered (<"
886 <<i->second.lock()->GetTypeName()<<">)");
892 bbtkDebugDecTab("Kernel",8);
896 //==========================================================================
898 //===================================================================
899 void Package::CheckBoxes() const
901 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
902 <<" ["<<GetName()<<"]"<<std::endl);
903 BlackBoxMapType::const_iterator i;
904 for (i=mBlackBoxMap.begin();
905 i!=mBlackBoxMap.end();
908 i->second->Check(true);
910 bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
911 <<" ["<<GetName()<<"] ... OK"<<std::endl);
913 //===================================================================
916 //==========================================================================
917 /// Changes the name of a black box type
918 void Package::ChangeBlackBoxName( const std::string& oldname, const std::string& newname )
920 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::ChangeBlackBoxName(\""<<oldname<<"\",\""<<newname<<"\")"<<std::endl);
921 // Looking into the bb map
922 BlackBoxMapType::iterator i = mBlackBoxMap.find(oldname);
923 if (i == mBlackBoxMap.end())
925 bbtkDebugDecTab("Kernel",8);
926 bbtkError("ChangeBlackBoxName : The package <"<<GetName()<<"> does not contains the black box <"<<oldname<<">");
929 i->second->SetTypeName(newname);
930 mBlackBoxMap[newname] = i->second;
931 mBlackBoxMap.erase(i);
933 bbtkDebugDecTab("Kernel",8);
935 //==========================================================================
939 //==========================================================================
940 /// Displays the list of black boxes of the package
941 void Package::PrintBlackBoxes(bool description, bool adaptors) const
943 unsigned int lmax = 0;
944 std::vector<std::string> names;
945 std::vector<std::string> kinds;
946 std::vector<std::string> descrs;
948 BlackBoxMapType::const_iterator i;
949 for (i=mBlackBoxMap.begin();
950 i!=mBlackBoxMap.end();
954 ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) )
956 std::string name(" ");
957 name += i->second->GetTypeName();
958 names.push_back(name);
961 if ( i->second->GetKind() == BlackBoxDescriptor::ADAPTOR )
963 kind = std::string("[A]");
965 else if ( i->second->GetKind() ==
966 BlackBoxDescriptor::DEFAULT_ADAPTOR )
968 kind = std::string("[DA]");
970 kinds.push_back(kind);
972 unsigned int l = name.size()+kind.size();
973 if (l>lmax) lmax = l;
979 descr += i->second->GetDescription();
981 descrs.push_back(descr);
987 offs.append(lmax+3,' ');
988 std::vector<std::string>::iterator ni,ci,di;
989 for (ni = names.begin(), ci = kinds.begin(), di = descrs.begin();
990 ni != names.end(); ++ni, ++ci, ++di)
993 space.append(lmax - ni->size() - ci->size(),' ');
994 bbtkMessage("Help",1,*ni << space << *ci );
996 unsigned int dmax = 75 - lmax;
997 // while (d.size() > dmax )
1000 bbtkMessage("Help",1,d.substr(0,dmax) << "..." << std::endl);
1002 bbtkMessage("Help",1,d << std::endl);
1003 // d = d.substr(dmax,d.size());
1008 //==========================================================================
1010 //==========================================================================
1011 /// Displays the list of adaptors of the package
1012 void Package::PrintAdaptors(bool description) const
1014 BlackBoxMapType::const_iterator i;
1015 for (i=mBlackBoxMap.begin();
1016 i!=mBlackBoxMap.end();
1019 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD )
1021 bbtkMessage("Help",1,
1022 " "<<i->second->GetTypeName());
1023 if ( i->second->GetKind() ==
1024 BlackBoxDescriptor::DEFAULT_ADAPTOR )
1026 bbtkMessage("Help",1,
1031 bbtkMessage("Help",1,
1032 " : "<<i->second->GetDescription());
1035 bbtkMessage("Help",1,std::endl);
1039 AdaptorMapType::const_iterator i;
1040 for (i=mAdaptorMap.begin();
1041 i!=mAdaptorMap.end();
1044 bbtkMessage("Help",1,
1045 " "<<i->second->GetTypeName());
1048 bbtkMessage("Help",1,
1049 " : "<<i->second->GetDescription());
1052 bbtkMessage("Help",1,std::endl);
1056 //==========================================================================
1058 //==========================================================================
1059 /// Prints help on a black box
1060 void Package::HelpBlackBox(const std::string& name, bool full) const
1062 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1063 <<name<<"\")"<<bbtkendl);
1065 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1066 if (i == mBlackBoxMap.end())
1068 bbtkDebugDecTab("Kernel",8);
1069 bbtkError("The package <"<<GetName()<<"> does not contains the black box <"<<name<<">");
1071 // bbtkMessage("Help",1,"["<<GetName()<<"] ");
1072 i->second->GetHelp(full);
1073 bbtkDebugDecTab("Kernel",8);
1076 //==========================================================================
1079 //==========================================================================
1080 /// Returns true iff the package contains the box of name boxname
1081 bool Package::ContainsBlackBox(const std::string& name) const
1083 bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1084 <<name<<"\")"<<bbtkendl);
1086 BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1087 if (i == mBlackBoxMap.end())
1089 bbtkDebugDecTab("Kernel",8);
1092 bbtkDebugDecTab("Kernel",8);
1095 //==========================================================================
1099 //==========================================================================
1100 void Package::CreateHtmlPage(const std::string& filename,
1101 const std::string& caller,
1102 const std::string& source,
1103 const std::string& custom_header,
1104 const std::string& custom_title,
1107 bool relative_link ) const
1109 bbtkDebugMessageInc("Kernel",9,"Package<"<<GetName()<<">::CreateHtmlPage(\""
1110 <<filename<<"\")"<<bbtkendl);
1112 //---------------------
1115 s.open(filename.c_str());
1118 bbtkError("Package "<<GetName()<<" : CreateHtmlPage : could not open file '"<<filename<<"'");
1121 //----------------------
1123 std::string title = "BBTK Package "+GetName()+" "+GetVersion();
1125 if (custom_title.length() != 0) title = custom_title;
1127 s << "<html lang=\"en\">\n";
1129 s << "<title>" << title << "</title>\n";
1130 s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1131 s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1132 s << "<meta name=\"generator\" content=\"\">\n";
1133 s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1134 //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1135 s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1136 s << "pre.display { font-family:inherit }\n";
1137 s << "pre.format { font-family:inherit }\n";
1138 s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1139 s << "pre.smallformat { font-family:inherit; font-size:smaller }\n";
1140 s << "pre.smallexample { font-size:smaller }\n";
1141 s << "pre.smalllisp { font-size:smaller }\n";
1142 s << "span.sc { font-variant:small-caps }\n";
1143 s << "span.roman { font-family:serif; font-weight:normal; } \n";
1144 s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n";
1145 s << "--></style>\n";
1147 //----------------------
1149 //----------------------
1152 s << "<a name=\"Top\"></a>\n";
1154 //----------------------
1156 if ( custom_header.length() != 0)
1158 if ( custom_header != "none" )
1161 in.open(custom_header.c_str());
1164 bbtkError("Could not open file \""<<custom_header<<"\"");
1169 in.getline(buffer,512);
1170 std::string line(buffer);
1177 s << "<object data=\"" << custom_header
1178 << "\" type = \"text/html\"\"style=\"width: 1200px; height: 400px;\"> Warning: "
1179 << custom_header <<" could not be embedded.</object>\n";
1188 s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1189 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1190 s << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1191 << GetDescription() << "</TD></TR>\n";
1192 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1193 << GetAuthor() << "</TD></TR>\n";
1194 s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1195 << GetCategory() << "</TD></TR>\n";
1196 s << "<TR><TD style='vertical-align: top;'><b> Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1197 << GetVersion() << "</TD></TR>\n";
1198 s << "<TR><TD style='vertical-align: top;'><b> bbtk Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> "
1199 << bbtk::GetVersion() << "</TD></TR>\n";
1203 //-------------------
1204 // Table of contents
1206 // s << "<div class=\"contents\">\n";
1207 s << "<p><b> Black Boxes : </b>\n";
1210 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1212 BlackBoxMapType::const_iterator i;
1213 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i)
1215 if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD)
1218 std::string name = i->second->GetTypeName();
1219 Utilities::html_format(name);
1220 std::string descr = i->second->GetDescription();
1221 //Utilities::html_format(descr);
1224 s << "<TD style='vertical-align: top;'>";
1225 s << " <a name=\"toc_"<<name
1226 <<"\" href=\"#"<<name<<"\">"
1229 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1238 //-------------------
1240 if (mAdaptorMap.size()>0)
1242 // s << "<div class=\"contents\">\n";
1243 s << "<p><b> Adaptors : </b>\n";
1246 // BlackBoxMapType::const_iterator i;
1247 s << "<p><TABLE cellspacing=0 cellpadding=3>\n";
1248 for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end();++i)
1250 if ( i->second->GetKind() == BlackBoxDescriptor::STANDARD)
1253 std::string name = i->second->GetTypeName();
1254 Utilities::html_format(name);
1255 std::string descr = i->second->GetDescription();
1258 s << "<TD style='vertical-align: top;'>";
1259 s << " <a name=\"toc_"<<name
1260 <<"\" href=\"#"<<name<<"\">"
1263 s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1273 // s << "<div class=\"node\">\n";
1275 // s << "<p><hr>\n";
1276 // s << "<a name=\"Top\"></a>\n";
1277 // s << "Top: <a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
1278 // s << "Previous: <a rel="previous" accesskey="p" href="#dir">(dir)</a>,
1279 // s << "Up: <a rel="up" accesskey="u" href="#dir">(dir)</a>
1283 //----------------------
1286 //-------------------
1287 // Computes output directory from filename to pass it to
1288 // BlackBoxDescriptor::InsertHtmlHelp
1291 std::string::size_type slash_position = filename.find_last_of("/\\");
1294 if (slash_position != std::string::npos) {
1295 if (slash_position == 0)
1297 dir = filename.substr(0,slash_position);
1300 for (i=mBlackBoxMap.begin();
1301 i!=mBlackBoxMap.end();
1304 i->second->InsertHtmlHelp(s,detail,level,dir,relative_link);
1307 //----------------------
1312 ptm = gmtime ( &rawtime );
1315 s << "Automatically generated by <b>"<<caller<<"</b> "//from <b>"
1318 << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900
1319 << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1320 s << "</body></html>\n";
1322 //----------------------
1325 bbtkDebugDecTab("Kernel",9);
1327 //==========================================================================
1329 //==========================================================================
1330 std::string Package::GetObjectName() const
1332 return std::string("Package '")+mName+std::string("'");
1334 //==========================================================================
1336 //==========================================================================
1337 std::string Package::GetObjectInfo() const
1339 std::stringstream i;
1340 i << " - "<<mBlackBoxMap.size() << " boxes" << std::endl;
1341 if (mDynamicLibraryHandler)
1343 i<< " - Loaded from dynamic library"<<std::endl;
1347 //==========================================================================
1350 //==========================================================================
1351 size_t Package::GetObjectSize() const
1353 size_t s = Superclass::GetObjectSize();
1354 s += Package::GetObjectInternalSize();
1357 //==========================================================================
1358 //==========================================================================
1359 size_t Package::GetObjectInternalSize() const
1361 size_t s = sizeof(Package);
1364 //==========================================================================
1365 //==========================================================================
1366 size_t Package::GetObjectRecursiveSize() const
1368 size_t s = Superclass::GetObjectRecursiveSize();
1369 s += Package::GetObjectInternalSize();
1371 BlackBoxMapType::const_iterator i;
1372 for (i = mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i )
1374 s += i->second->GetObjectRecursiveSize();
1378 //==========================================================================
1380 //==========================================================================
1381 std::set<Package::WeakPointer>
1382 Package::mReleasedDynamicallyLoadedPackages;
1383 //==========================================================================