]> Creatis software - bbtk.git/blob - kernel/src/bbtkFactory.cxx
*** empty log message ***
[bbtk.git] / kernel / src / bbtkFactory.cxx
1 /*=========================================================================
2                                                                                 
3 Program:   bbtk
4 Module:    $RCSfile: bbtkFactory.cxx,v $
5 Language:  C++
6
7 Date:      $Date: 2008/04/09 11:16:57 $
8 Version:   $Revision: 1.32 $
9                                                                                 
10
11 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
12 l'Image). All rights reserved. See doc/license.txt or
13 http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
14
15 This software is distributed WITHOUT ANY WARRANTY; without even
16 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
17 PURPOSE.  See the above copyright notices for more information.
18
19 =========================================================================*/
20 /**
21  *\file
22  *\brief  Class bbtk::Factory : can load and unload dynamic libraries containing 
23  *        black boxes packages and create instances of the black boxes registered 
24  *       in the packages loaded.
25  */
26 #include "bbtkFactory.h"
27 #include "bbtkMessageManager.h"
28 #include "bbtkConnection.h"
29 #include "bbtkConfigurationFile.h"
30 #include "bbtkUtilities.h"
31
32 #include <sys/stat.h> // for struct stat stFileInfo
33
34 #if defined(_WIN32)
35 #include <direct.h> // for getcwd
36 #endif
37
38 #include <cctype>    // std::toupper
39
40
41 namespace bbtk
42 {
43   typedef Package* (*PackageAccessor)();
44   typedef void (*PackageDeleteFunction)();
45
46
47   //===================================================================
48   /// Default ctor
49   Factory::Factory()
50     : mExecuter(0)
51   {
52     bbtkDebugMessage("Kernel",7,"Factory::Factory()"<<std::endl);
53   }
54   //===================================================================
55
56   //===================================================================
57   /// Dtor
58   Factory::~Factory()
59   {
60     bbtkDebugMessageInc("Kernel",7,"Factory::~Factory()"<<std::endl);
61     CloseAllPackages();
62     bbtkDebugDecTab("Kernel",7);
63   }
64   //===================================================================
65
66
67   //===================================================================
68   void Factory::CloseAllPackages()
69   {
70     bbtkDebugMessageInc("Kernel",7,"Factory::CloseAllPackages()"<<std::endl);
71     while (mPackageMap.begin() != mPackageMap.end())
72       {
73         PackageMapType::iterator i = mPackageMap.begin();
74         ClosePackage(i);
75       }
76     bbtkDebugDecTab("Kernel",7);
77   }
78   //===================================================================
79
80   //===================================================================
81   void Factory::Reset()
82   {
83     bbtkDebugMessageInc("Kernel",7,"Factory::Reset()"<<std::endl);
84     CloseAllPackages();
85     bbtkDebugDecTab("Kernel",7);
86   }
87   //===================================================================
88
89
90   // ===================================================================
91   bool Factory::DoLoadPackage(std::string libname,
92                               std::string pkgname,
93                               std::string path)
94   {
95     
96 #if defined(__GNUC__)
97     
98     void *handler;
99     handler = dlopen(libname.c_str(),
100                      BBTK_RTLD_TIME | BBTK_RTLD_SCOPE );
101     if (!handler)
102       {
103         // The following is *NOT* a debug time message :
104         // It's a user intended message.
105         // Please don't remove it.
106         bbtkError("Could not open shared library [" <<libname<<"] : "
107                   <<dlerror() << std::endl);
108         
109         return false; // try next path
110       }
111     
112     // The following is *NOT* a debug time message :
113     // It's a user intended message.
114     // Please don't remove it.
115     bbtkMessage("Output",2,"   -->[" <<libname<<"] found" << std::endl);
116     
117     // Loads the Package accessor
118     
119     std::string getpackname(pkgname);
120     getpackname += "GetPackage";
121     void *getpack = dlsym(handler, getpackname.c_str());
122     if (!getpack)
123       {
124         dlclose(handler);
125         bbtkError("Shared library ["<<libname<<"] is not a valid bbtk package."
126                   <<" Symbol ["<<getpackname<<"] :"<<dlerror());
127       }
128     
129     // Verifies that the Package delete function is present
130     std::string delfname(pkgname);
131     delfname += "DeletePackage";
132     void *delf = dlsym(handler, delfname.c_str());
133     if (!delf)
134       {
135         dlclose(handler);
136         bbtkError("Shared library ["<<libname<<"] is not a valid bbtk package."
137                   <<" Symbol ["<<delfname<<"] :"<<dlerror());
138       }
139     
140 #elif defined(_WIN32)
141     
142     HINSTANCE handler;
143     
144     SetErrorMode(0);
145     handler = LoadLibrary(libname.c_str());
146     if (!handler)
147       {
148         // The following is *NOT* a debug time message :
149         // It's a user intended message.
150         // Please don't remove it.
151         bbtkError("Error loading library [" <<libname<<"]" << std::endl);
152         return false;// Problem with the found library
153       }
154     
155     bbtkMessage("Output",2,"   --->[" <<libname<<"] found" << std::endl);
156     
157     // Loads the Package accessor
158     
159     std::string getpackname(pkgname);
160     getpackname += "GetPackage";
161     void *getpack = GetProcAddress(handler, getpackname.c_str());
162     if (!getpack)
163       {
164         FreeLibrary(handler);
165         bbtkError("[1] Could not load package \""<<pkgname
166                   <<"\" : "<<getpackname<<" symbol not found (is it a bbtk package lib ?)");
167         // look how to get the error message on win
168         //<<dlerror());
169       }
170     // Verifies that the Package delete function is present
171     std::string delfname(pkgname);
172     delfname += "DeletePackage";
173     void *delf = GetProcAddress(handler, delfname.c_str());
174     if (!delf)
175       {
176         FreeLibrary(handler);
177         bbtkError("[2] Could not load package \""<<pkgname
178                   <<"\" : "<<delfname<<" symbol not found (is it a bbtk package lib ?)");
179         // look how to get the error message on win
180         //<<dlerror());
181       }
182 #else
183     bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
184 #endif
185     
186     // Stores the package
187     PackageInfoType pack;
188     pack.mDynamicLibraryHandler = handler;
189     // Invokes the accessor to the PackageUnit pointer
190     pack.mPackage = ((PackageAccessor)getpack)();
191     
192     // Test bbtk build version ok
193     if ( pack.mPackage->GetBBTKVersion() != bbtk::GetVersion() )
194       {
195         std::string v(pack.mPackage->GetBBTKVersion());
196         UnLoadPackage(pkgname);
197         bbtkError("Cannot load package ["<<libname<<"]. "
198                   <<"Package build with bbtk version "
199                   << v
200                   << " whereas application build with version "
201                   << bbtk::GetVersion());
202       }
203
204     pack.mPackage->AddFactory(this);
205     mPackageMap[pkgname] = pack;
206     
207     std::string separator =
208       ConfigurationFile::GetInstance().Get_file_separator ();
209     //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
210     std::string docreldoc = 
211       separator + "bbdoc" + separator + pkgname + separator + "index.html";
212     std::string reldoc = 
213       ".." + separator + ".." + docreldoc;
214     std::string doc = path + separator + ".." + separator
215       + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
216       + docreldoc;
217     
218     pack.mPackage->SetDocURL(doc);
219     pack.mPackage->SetDocRelativeURL(reldoc);
220     
221     //===================================================================
222     bbtkMessage("Output",2,pack.mPackage->GetName()<<" "
223                 <<pack.mPackage->GetVersion()
224                 <<" (bbtk "
225                 <<pack.mPackage->GetBBTKVersion()<<") "
226                 <<pack.mPackage->GetAuthor() << " Category(s) :"
227                 <<pack.mPackage->GetCategory()
228                 <<std::endl);
229     bbtkMessage("Output",2,pack.mPackage->GetDescription()<<std::endl);
230     //===================================================================
231     
232     bbtkDebugDecTab("Kernel",7);
233     return true;
234   }
235   
236   //===================================================================
237   /// \brief Loads a package.
238   ///
239   /// The name is the system-independant name of the package (the name of the instance of bbtk::Package).
240   /// Tries to open the dynamic library :
241   /// - "libbb<name>.so" for linux systems,
242   /// - "bb<name>.dll" for windows systems.
243   /// If it succeeds, then tries to load the symbols "<name>GetPackage" and "<name>DeletePackage".
244   /// "<name>GetPackage" is called to get the pointer on the bbtk::Package of the library
245   /// ("<name>DeletePackage" is not used, its presence is just checked before loading the package).
246   
247   /// now, filename is only the last name (no longer the full name!)
248   /// it will be searched within *all* the paths given in bbtk_config.xml
249   
250
251   
252   void Factory::LoadPackage( const std::string& name )
253   {
254   // Note : in the following :
255   // name : the user supplied name
256   //      - abreviated name    e.g.       pkg   pkg.so   libbpkg   libbbpkg.so
257   //      - relative full name e.g.       ./libbbpkg.so   ../../libbbpkg.so
258   //      - absolute full name e.g.       /home/usrname/proj/lib/libbbpkg.so
259   //          same for Windows, with      c:, d: ...
260   //
261   // lastname : string before the last / (if any), or user supplied name
262
263     bbtkDebugMessageInc("Kernel",7,"Factory::LoadPackage(\""<<name<<"\")"<<std::endl);
264     bbtkMessage("Debug",1,"Factory::LoadPackage(\""<<name<<"\")"<<std::endl);
265
266     std::vector<std::string> package_paths;
267     std::string libname;  // full path library name
268     std::string pkgname;  // e.g. libbb<pkgname>.so
269
270     std::string upath;
271     pkgname = Utilities::ExtractPackageName(name,upath);
272
273     bbtkMessage("Debug",1,"Package name ["<<pkgname<<"]"<<std::endl);
274     bbtkMessage("Debug",1,"Package path ["<<upath<<"]"<<std::endl);
275
276     // no loading package if already loaded
277     PackageMapType::iterator iUnload;
278     iUnload = mPackageMap.find(pkgname);
279     if (iUnload != mPackageMap.end())
280     {
281       bbtkMessage("Output",2,"["<< pkgname <<"] already loaded" << std::endl);
282       return;
283     }
284
285 // =================================================
286 // The following structure was checked to work
287 // with any type of relative/absolute path.
288 // Please don't modify it without checking
289 // *all* the cases. JP
290 //==================================================
291
292 //std::cout << "upath [" << upath << "]" << std::endl;
293
294     bool ok = false;
295     bool foundFile = false;
296
297     // If path provided by user will be the first scanned :
298     // push it into vector of paths
299     if (upath.length()>0)   // ------------------------------------- check user supplied location
300     {
301        if (name[0] != '.' && name[0] != '/' && name[1]!= ':')
302        {
303           bbtkError("Use absolute or relative path name! ["<<name<<"] is an illegal name");
304           return;
305        }
306
307       // std::string path = Utilities::ExpandLibName(upath, false);
308        std::string path = Utilities::ExpandLibName(name,false); // keep last item, here.
309          
310        if (path != "")
311        {
312           std::string p2;
313           Utilities::ExtractPackageName(path,p2);
314           //libname = Utilities::MakeLibnameFromPath(path, pkgname);
315           libname = Utilities::MakeLibnameFromPath(p2, pkgname); // remove last item
316           // Check if library exists
317           if ( !Utilities::FileExists(libname) )
318           {
319           // The following is *NOT* a debug time message :
320           // It's a user intended message.
321           // Please don't remove it.
322             bbtkMessage("Output",3,"   [" <<libname 
323                         <<"] : doesn't exist" <<std::endl);
324           }
325           else
326           {
327              ok = DoLoadPackage( libname, pkgname, path);         
328           }
329        }
330        else
331        {
332           bbtkError("Path ["<<upath<<"] doesn't exist");
333           return;
334        }
335     }
336     else     // ----------------------------------------------------- iterate on the paths  
337     {
338
339     std::string path;
340     package_paths = ConfigurationFile::GetInstance().Get_package_paths();
341     std::vector<std::string>::iterator i;
342     for (i=package_paths.begin();i!=package_paths.end();++i)
343     {
344         foundFile = false;
345         path = *i;
346
347         // we *really* want '.' to be the current working directory
348         if (path == ".")
349         {
350           char buf[2048]; // for getcwd
351           char * currentDir = getcwd(buf, 2048);
352           std::string cwd(currentDir);
353           path = currentDir;
354         }
355
356         libname = Utilities::MakeLibnameFromPath(path, pkgname);
357
358         bbtkMessage("Debug",2,"-> Trying to load [" << libname << "]" <<std::endl);
359
360       // Check if library exists           
361         if ( !Utilities::FileExists(libname) )
362         {
363         // The following is *NOT* a debug time message :
364         // It's a user intended message.
365         // Please don't remove it.
366           bbtkMessage("Output",3,
367                       "   [" <<libname <<"] : doesn't exist" <<std::endl);
368            continue;  // try next path
369         }
370         foundFile = true; 
371
372       // Try to Load the library
373
374         ok = DoLoadPackage( libname, pkgname, path);
375         if (ok)
376         {
377            bbtkMessage("Debug",2,"   OK"<<std::endl);
378            break; // a package was found; we stop iterating
379         }
380     } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
381
382 }
383
384     if( !ok )  // nothing was loaded
385     {
386       if (!foundFile)
387       {
388         bbtkError("Could not find package ["<<pkgname<< "]");
389       }
390       else
391       {
392 #if defined(__GNUC__)
393         bbtkError("Could not load package ["<< pkgname
394                   <<"] :" << std::endl << "   " << dlerror());
395 #elif defined(_WIN32)
396         bbtkError("Could not load package ["<<pkgname
397                  <<"] : " << std::endl << "   " <<libname<<" not found");
398
399     // look how to get the error message on win
400     //<<dlerror());
401     // it is the bordel !! (the bloody fucking bordel, you mean?)
402     // look : http://msdn2.microsoft.com/en-us/library/ms680582.aspx
403 #endif
404       }
405     }
406     bbtkMessage("Output",2,"[" << libname << "] loaded" << std::endl);
407
408   }
409
410   //===================================================================
411   /// \brief UnLoads a package.
412   ///
413   /// The package must have been previously loaded by LoadPackage.
414   /// If the entry is found in the map, calls ClosePackage
415  void Factory::UnLoadPackage( const std::string& name )
416  {
417     bbtkDebugMessageInc("Kernel",7,"Factory::UnLoadPackage(\""
418                        <<name<<"\")"<<std::endl);
419   
420     PackageMapType::iterator i;
421     i = mPackageMap.find(name);
422     if (i == mPackageMap.end()) 
423     {
424       bbtkError("cannot unload package \""<<name
425                 <<"\" : package not loaded !");
426     }
427     ClosePackage(i);
428     bbtkDebugDecTab("Kernel",7);
429   }
430   //===================================================================
431
432
433   //===================================================================
434   /// \brief Close the package referenced by the iterator 
435  ///
436  /// First removes the factory from the set of factories which use the package
437  /// If the set is empty then :
438  /// If it is a dynamically loaded package :
439  /// - Loads and calls the function "<name>DeletePackage" of the dynamic library (responsible for package desallocation)
440  /// - Closes the dynamic library
441  /// Else :
442  /// - deletes the package normally
443  /// 
444  /// Finally erases the package entry in the packages map
445  void Factory::ClosePackage(PackageMapType::iterator& i) 
446   {   
447      bbtkDebugMessageInc("Kernel",7,"Factory::ClosePackage(\""
448                          <<i->second.mPackage->GetName()
449                         <<"\")"<<std::endl);
450
451      
452      // Removes this from the set of factories which use the package
453      i->second.mPackage->RemoveFactory(this);
454      
455      // If no more factory which use it 
456      if (i->second.mPackage->GetFactorySet().empty())
457        {
458          // If it is a dynamically loaded package       
459          if (i->second.mDynamicLibraryHandler) 
460            {
461              
462              
463              // Loads the Package delete function
464              
465              std::string delfname(i->second.mPackage->GetName());
466              delfname += "DeletePackage";
467 #if defined(__GNUC__)     
468              void *delf = dlsym(i->second.mDynamicLibraryHandler, delfname.c_str());
469              if (!delf)
470                {
471                  bbtkError("could not close package \""
472                            <<i->second.mPackage->GetName()
473                            <<"\" :"<<dlerror());
474                }    
475 #elif defined(_WIN32)
476              void *delf = GetProcAddress(i->second.mDynamicLibraryHandler, 
477                                          delfname.c_str());
478              if (!delf)
479                {  
480                  bbtkError("could not close package \""
481                            <<i->second.mPackage->GetName()
482                            <<"\" : "<<delfname
483                            <<" symbol not found (how did you open it ???");
484                  //<<"\" :"<<dlerror());
485                }    
486 #endif     
487              
488              // deletes the package
489              ((PackageDeleteFunction)delf)();
490              
491              // closes the dl handler
492 #if defined(__GNUC__)  
493              dlclose(i->second.mDynamicLibraryHandler);  
494 #elif defined(_WIN32)
495              
496              FreeLibrary(i->second.mDynamicLibraryHandler);
497 #endif
498            }
499
500          else 
501            {  
502              // If it is a manually inserted package : delete it normally
503              delete i->second.mPackage;
504            }
505        }
506      
507      // in any cases remove the entry in the map
508      mPackageMap.erase(i);
509
510      bbtkDebugDecTab("Kernel",7);
511   }
512   //===================================================================
513   
514
515
516   //===================================================================  
517   /// Displays the list of packages loaded
518   void Factory::PrintPackages(bool details, bool adaptors) const
519   {
520     bbtkDebugMessageInc("Kernel",9,"Factory::PrintPackages"<<std::endl);
521
522     PackageMapType::const_iterator i;
523     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
524     {
525       bbtkMessage("Help",1, i->first << std::endl);
526       if (details) {
527          i->second.mPackage->PrintBlackBoxes(false,adaptors);
528       }
529     }
530
531     bbtkDebugDecTab("Kernel",9);
532   }
533   //===================================================================
534
535   //===================================================================  
536   /// Displays help on a package
537   void Factory::HelpPackage(const std::string& name, bool adaptors) const
538   {
539     bbtkDebugMessageInc("Kernel",9,"Factory::HelpPackage(\""<<name<<"\")"
540                         <<std::endl);
541
542     PackageMapType::const_iterator i = mPackageMap.find(name);
543     if ( i != mPackageMap.end() ) 
544       {
545       bbtkMessage("Help",1, "Package "<<i->first<<" ");
546       
547       if (i->second.mPackage->GetVersion().length()>0)
548         bbtkMessageCont("Help",1,"v" <<i->second.mPackage->GetVersion());
549         
550       if (i->second.mPackage->GetAuthor().length()>0)
551         bbtkMessageCont("Help",1,"- "<<i->second.mPackage->GetAuthor());
552         
553       if (i->second.mPackage->GetCategory().length()>0)
554         bbtkMessageCont("Help",1,"- "<<i->second.mPackage->GetCategory());        
555         
556       bbtkMessageCont("Help",1,std::endl);
557       bbtkIncTab("Help",1);
558       bbtkMessage("Help",1,i->second.mPackage->GetDescription()<<std::endl);
559       if (i->second.mPackage->GetNumberOfBlackBoxes()>0) 
560         {
561           bbtkMessage("Help",1, "Black boxes : "<<std::endl);
562           i->second.mPackage->PrintBlackBoxes(true,adaptors);
563         }
564       else 
565         {
566           bbtkMessage("Help",1, "No black boxes"<<std::endl);
567         }
568       bbtkDecTab("Help",1);
569       }
570     else 
571       {
572       bbtkDebugDecTab("Kernel",9);
573       bbtkError("package \""<<name<<"\" unknown");
574       }
575     
576     bbtkDebugDecTab("Kernel",9);
577   }
578   //===================================================================
579
580   //===================================================================
581   /// Prints help on the black box of type <name>
582   /// Returns the package to which it belongs
583   void Factory::HelpBlackBox(const std::string& name, 
584                              std::string& package,
585                              bool full) const
586   {
587     bbtkDebugMessageInc("Kernel",9,"Factory::HelpBlackBox(\""<<name<<"\")"
588                         <<std::endl);
589
590     bool found = false;
591     PackageMapType::const_iterator i;
592     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
593       {
594       if (i->second.mPackage->ContainsBlackBox(name)) 
595         {
596           i->second.mPackage->HelpBlackBox(name,full);
597               package = i->second.mPackage->GetName();
598           found = true;
599         }
600       }
601     
602     bbtkDebugDecTab("Kernel",9);
603     if (!found) 
604       {
605       bbtkError("No package of the factory contains any black box <"
606                  <<name<<">");
607       }
608   }  
609   //===================================================================
610
611
612   //=================================================================== 
613   /// Inserts a package in the factory
614   void Factory::InsertPackage( Package* p )
615   {
616     bbtkDebugMessageInc("Kernel",9,"Factory::InsertPackage(\""<<
617                         p->GetName()<<"\")"<<std::endl);
618
619     p->AddFactory(this);
620     PackageInfoType pack;
621     pack.mDynamicLibraryHandler = 0;
622     pack.mPackage = p;
623     mPackageMap[p->GetName()] = pack;
624
625     bbtkDebugDecTab("Kernel",9);
626   }
627   //===================================================================
628   
629   //=================================================================== 
630   /// Removes a package from the factory (and deletes it)
631   void Factory::RemovePackage( Package* p )
632   {
633     bbtkDebugMessageInc("Kernel",9,"Factory::RemovePackage(\""<<
634                         p->GetName()<<"\")"<<std::endl);
635
636     PackageMapType::iterator i;
637     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
638       {
639          if (i->second.mPackage == p) break;
640       };
641     
642     if (i!=mPackageMap.end())
643       {
644         ClosePackage(i);
645       }
646     else 
647       {
648         bbtkError("Factory::RemovePackage(\""<<
649                   p->GetName()<<"\") : package absent from factory");
650       }
651
652     bbtkDebugDecTab("Kernel",9);
653   }
654   //===================================================================
655   
656
657   //===================================================================
658   /// Creates an instance of a black box of type <type> with name <name>
659   BlackBox* Factory::NewBlackBox(const std::string& type, 
660                                  const std::string& name) const
661   {
662     bbtkDebugMessageInc("Kernel",7,"Factory::NewBlackBox(\""
663                         <<type<<"\",\""<<name<<"\")"<<std::endl);
664
665     BlackBox* b = 0; 
666     PackageMapType::const_iterator i;
667     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
668       {
669       b = i->second.mPackage->NewBlackBox(type,name);
670       if (b) break; 
671       }
672     if (!b) 
673       {
674        bbtkError("black box type \""<<type<<"\" unknown");
675       } 
676
677     bbtkDebugDecTab("Kernel",7);
678     return b;
679   }
680   //===================================================================
681
682   //===================================================================
683   /// Creates an instance of a black box of type <type> with name <name>
684   BlackBox* Factory::NewAdaptor(const DataInfo& typein,
685                                 const DataInfo& typeout,
686                                 const std::string& name) const
687   {
688     bbtkDebugMessageInc("Kernel",8,"Factory::NewAdaptor("
689                         <<typein<<","
690                         <<typeout<<",\""
691                         <<name<<"\")"<<bbtkendl);
692
693
694     BlackBox* b = 0; 
695     PackageMapType::const_iterator i;
696     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
697       {
698       b = i->second.mPackage->NewAdaptor(typein,typeout,name);
699       if (b) break; 
700       }
701     if (!b) 
702       {
703         bbtkError("no "<<typein<<" to "<<typeout
704                   <<" adaptor available");
705       } 
706     
707     bbtkDebugDecTab("Kernel",7);
708     return b; 
709   }
710   //===================================================================
711
712
713   //===================================================================
714   /// Creates an instance of a black box of type <type> with name <name>
715   BlackBox* Factory::NewWidgetAdaptor(const DataInfo& typein,
716                                       const DataInfo& typeout,
717                                       const std::string& name) const
718   {
719     bbtkDebugMessageInc("Kernel",8,"Factory::NewWidgetAdaptor(<"
720                         <<typein<<">,<"
721                         <<typeout<<">,\""
722                         <<name<<"\")"<<bbtkendl);
723
724
725     BlackBox* b = 0; 
726     PackageMapType::const_iterator i;
727     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
728       {
729         b = i->second.mPackage->NewWidgetAdaptor(typein,
730                                                  typeout,
731                                                  name);
732       if (b) break; 
733       }
734     if (!b) 
735       {
736         bbtkError("no "<<typein<<" to "<<typeout
737                   <<"> widget adaptor available");
738       } 
739     
740     bbtkDebugDecTab("Kernel",7);
741     return b; 
742   }
743   //===================================================================
744
745   //===================================================================
746   /// Creates an instance of a black box of type <type> with name <name>
747   bool Factory::FindAdaptor(const DataInfo& typein,
748                                   const DataInfo& typeout,
749                                   std::string& adaptor) const
750   {
751     bbtkDebugMessageInc("Kernel",8,"Factory::FindAdaptor(<"
752                         <<typein<<">,<"
753                         <<typeout<<">)"<<bbtkendl);
754     
755     bool b = false;
756     PackageMapType::const_iterator i;
757     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
758       {
759         b = i->second.mPackage->FindAdaptor(typein,
760                                             typeout,
761                                             adaptor);
762         if (b) break; 
763       }
764     /*
765     if (!b) 
766       {
767         bbtkError("no "<<typein<<" to "<<typeout
768                   <<"> widget adaptor available");
769       } 
770     */
771
772     bbtkDebugDecTab("Kernel",7);
773     return b; 
774   }
775   //===================================================================
776
777   //===================================================================
778   /// Creates an instance of a black box of type <type> with name <name>
779   bool Factory::FindWidgetAdaptor(const DataInfo& typein,
780                                   const DataInfo& typeout,
781                                   std::string& adaptor) const
782   {
783     bbtkDebugMessageInc("Kernel",8,"Factory::FindWidgetAdaptor(<"
784                         <<typein<<">,<"
785                         <<typeout<<">)"<<bbtkendl);
786     
787     bool b = false;
788     PackageMapType::const_iterator i;
789     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
790       {
791         b = i->second.mPackage->FindWidgetAdaptor(typein,
792                                                   typeout,
793                                                   adaptor);
794         if (b) break; 
795       }
796     bbtkDebugDecTab("Kernel",7);
797     return b; 
798   }
799   //===================================================================
800
801   //===================================================================
802   /// Creates an instance of a black box of type <type> with name <name>
803   bool Factory::FindWidgetAdaptor2(const DataInfo& typein,
804                                   const DataInfo& typeout,
805                                   std::string& widget,
806                                   std::string& adaptor) const
807   {
808     bbtkDebugMessageInc("Kernel",8,"Factory::FindWidgetAdaptor(<"
809                         <<typein<<">,<"
810                         <<typeout<<">)"<<bbtkendl);
811     
812     bool b = false;
813     adaptor = widget = "";
814     PackageMapType::const_iterator i;
815     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
816       {
817         b = i->second.mPackage->FindWidgetAdaptor(typein,
818                                                   typeout,
819                                                   widget);
820         if (b) break; 
821       }
822     if (!b) 
823       {
824         // Look for a widget adaptor with good nature out
825         bbtkMessage("Kernel",5,
826                     "*** Looking for a two pieces widget adaptor for : "
827                     << typein << "->"<<typeout<<std::endl);
828         for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
829           {
830             Package::AdaptorMapType::const_iterator j;
831             for (j=i->second.mPackage->GetAdaptorMap().begin();
832                  j!=i->second.mPackage->GetAdaptorMap().end();
833                  ++j)
834               {
835                 if ( ( j->first.mKind ==  
836                        BlackBoxDescriptor::DEFAULT_WIDGET_ADAPTOR) &&
837                      //(j->first.mTypeIn == typein) &&
838                      (j->first.mTypeOut.GetNature() == typeout.GetNature() ) 
839                      )
840                   {
841                     widget = j->second->GetTypeName();
842                     bbtkMessage("Kernel",5,
843                                 "===> Found first part : "<<widget
844                                 << " "<<j->first.mTypeIn<<"->"
845                                 <<j->first.mTypeOut<<std::endl);
846                     DataInfo ti( j->first.mTypeOut.GetType(), "");
847                     DataInfo to( typeout.GetType(), "");
848                     b = FindAdaptor( ti, to, adaptor );
849                     if (b) 
850                       {
851                         bbtkMessage("Kernel",5,
852                                     "===> Found second part : "<<adaptor
853                                     <<std::endl);
854                         break;
855                       }
856                     else
857                       {
858                         bbtkMessage("Kernel",5,
859                                     "===> No second part found"<<std::endl);
860                       }
861                   }
862               }
863             if (b) break;
864           }
865       }
866     bbtkDebugDecTab("Kernel",7);
867     return b; 
868   }
869   //===================================================================
870
871   //===================================================================
872   /// Creates an instance of a connection
873   Connection* Factory::NewConnection(BlackBox* from,
874                                      const std::string& output,
875                                      BlackBox* to,
876                                      const std::string& input) const
877   {
878     bbtkDebugMessage("Kernel",7,"Factory::NewConnection(\""
879                       <<from->bbGetName()<<"\",\""<<output<<"\",\""
880                       <<to->bbGetName()<<"\",\""<<input
881                       <<"\")"<<std::endl);
882     
883     return new Connection(from,output,to,input,this);
884   }
885   //===================================================================
886
887
888
889   //===================================================================
890   const Package* Factory::GetPackage(const std::string& name) const
891   {
892     bbtkDebugMessageInc("Kernel",9,"Factory::GetPackage(\""<<name<<"\")"
893                          <<std::endl);
894
895     PackageMapType::const_iterator i = mPackageMap.find(name);
896     if ( i != mPackageMap.end() ) 
897     {
898       bbtkDebugDecTab("Kernel",9); 
899       return i->second.mPackage;
900     }
901     else 
902     {
903        bbtkDebugDecTab("Kernel",9);
904        bbtkError("package \""<<name<<"\" unknown");
905     }
906     
907     bbtkDebugDecTab("Kernel",9);  
908   }
909   //===================================================================
910   
911   //===================================================================
912   Package* Factory::GetPackage(const std::string& name) 
913   {
914     bbtkDebugMessageInc("Kernel",9,"Factory::GetPackage(\""<<name<<"\")"
915                          <<std::endl);
916
917     PackageMapType::const_iterator i = mPackageMap.find(name);
918     if ( i != mPackageMap.end() ) 
919     {
920       bbtkDebugDecTab("Kernel",9); 
921       return i->second.mPackage;
922     }
923     else 
924     {
925        bbtkDebugDecTab("Kernel",9);
926        bbtkError("package \""<<name<<"\" unknown");
927     }
928     
929     bbtkDebugDecTab("Kernel",9);  
930   }
931   //===================================================================
932
933   //===================================================================
934   void Factory::CheckPackages() const
935   {
936     bbtkMessage("Debug",1,"****** Checking Factory "<<(void*)this
937                  <<std::endl);
938     PackageMapType::const_iterator i;
939     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
940       {
941         i->second.mPackage->CheckBoxes();
942       }
943     bbtkMessage("Debug",1,"****** Checking Factory "<<(void*)this
944                 <<" ... OK"<<std::endl);
945   }
946   //===================================================================
947
948   //===================================================================
949   void Factory::WriteDotFilePackagesList(FILE *ff)
950   {
951
952     bbtkDebugMessageInc("Kernel",9,"Factory::WriteDotFilePackagesList()"
953                          <<std::endl);
954
955     fprintf( ff , "\n");
956     fprintf( ff , "subgraph cluster_FACTORY {\n");
957     fprintf( ff , "  label = \"PACKAGES\"%s\n",  ";");
958     fprintf( ff , "  style=filled%s\n",";");
959     fprintf( ff , "  color=lightgrey%s\n",";");
960     fprintf( ff , "  rankdir=TB%s\n",";");
961
962     std::string url;
963     PackageMapType::const_iterator i;
964     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
965     {
966        url=GetPackage(i->first)->GetDocURL();
967        fprintf(ff,"  %s [shape=ellipse, URL=\"%s\"]%s\n",i->first.c_str(),url.c_str(),";" );
968     }
969     fprintf( ff , "}\n\n");
970     bbtkDebugDecTab("Kernel",9);
971   }
972   //===================================================================
973
974
975  void Factory::ShowGraphTypes(const std::string& name) const
976  {
977
978    bool found = false;
979    PackageMapType::const_iterator i;
980    for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
981    {
982       if (i->second.mPackage->ContainsBlackBox(name)) 
983       {
984          std::string separator = ConfigurationFile::GetInstance().Get_file_separator ();
985
986             // Don't pollute the file store with  "temp_dir" directories ...    
987          std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
988          std::string directory = "\"" + default_doc_dir + separator + "temp_dir"  +separator + "\"";
989          std::string filename2 =  default_doc_dir + separator + "temp_dir" + separator + "tmp.html"; 
990
991 #if defined(_WIN32)  
992         std::string command("start \"Titre\" /D ");
993 #else 
994         std::string command("gnome-open ");
995 #endif
996         command=command + directory +" tmp.html";
997         FILE *ff;
998         ff=fopen(filename2.c_str(),"w");
999
1000         fprintf(ff,"<html><head><title>TMP</title> <script type=\"text/javascript\"> <!--\n");
1001         fprintf(ff,"  window.location=\"%s#%s\";\n" , i->second.mPackage->GetDocURL().c_str(),name.c_str() );
1002         fprintf(ff,"//--></script></head><body></body></html>\n");
1003
1004
1005         //fprintf(ff, "<a  href=\"%s#%s\">Link</a>\n", i->second.mPackage->GetDocURL().c_str(),name.c_str() );
1006         fclose(ff);
1007         system( command.c_str() );      
1008         found = true;
1009      }
1010    }
1011     
1012    bbtkDebugDecTab("Kernel",9);
1013    if (!found) 
1014    {
1015       bbtkError("No package of the factory contains any black box <"
1016                 <<name<<">");
1017    }
1018  }
1019     
1020
1021
1022
1023   void Factory::CreateHtmlIndex(IndexEntryType type, 
1024                                 const std::string& filename)
1025   {
1026     bbtkDebugMessageInc("Kernel",9,"Factory::CreateHtmlIndex(\""
1027                         <<filename<<"\")"<<bbtkendl);
1028     
1029     std::string title;
1030
1031     typedef std::map<std::string, std::vector<BlackBoxDescriptor*> > IndexType;
1032     IndexType index;
1033     // Builds the index map
1034     PackageMapType::const_iterator i;
1035     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
1036       {
1037         Package* pack = i->second.mPackage;
1038         if (pack->GetName()=="user") continue;
1039         Package::BlackBoxMapType::const_iterator j;
1040         for (j = pack->GetBlackBoxMap().begin(); 
1041              j!= pack->GetBlackBoxMap().end(); 
1042              ++j)
1043           {
1044             
1045             // Skip adaptors 
1046             if ( type==Adaptors )
1047               {  
1048                 if (j->second->GetKind() == BlackBoxDescriptor::STANDARD )
1049                   continue;
1050               }
1051             else 
1052               if (j->second->GetKind() != BlackBoxDescriptor::STANDARD )
1053                 continue;
1054
1055             std::vector<std::string> keys;
1056             if (type==Packages)
1057               {
1058                 std::string k("");
1059                 k += pack->GetName();
1060                 keys.push_back(k);
1061                 title = "Boxes by package";
1062               }
1063             else if ((type==Initials) || (type==Adaptors))
1064               {
1065                 std::string init(" ");
1066                 init[0] =  std::toupper(j->second->GetTypeName()[0]);
1067                 keys.push_back(init);
1068                 title = "Alphabetical list";
1069               }
1070             else if (type==Categories)
1071               {
1072                 // Split the category string 
1073                 std::string delimiters = ";,";
1074                 Utilities::SplitString(j->second->GetCategory(),
1075                                        delimiters,keys);
1076                 if (keys.size()==0) 
1077                   keys.push_back(" NONE");
1078                 title = "Boxes by category";
1079               }
1080     
1081             
1082             std::vector<std::string>::const_iterator k;
1083             for (k=keys.begin(); k!=keys.end(); ++k )
1084               {
1085                 IndexType::iterator p;
1086                 p = index.find(*k);
1087                 if (p != index.end()) 
1088                   {
1089                     p->second.push_back(j->second);
1090                   }
1091                 else 
1092                   {
1093                     std::vector<BlackBoxDescriptor*> v;
1094                     v.push_back(j->second);
1095                     index[*k] = v;
1096                   }
1097               }
1098             
1099           }
1100       }   
1101     // Creates the file 
1102     //---------------------
1103     // Open output file
1104     std::ofstream s;
1105     s.open(filename.c_str());
1106     if (!s.good()) 
1107     {
1108        bbtkError("Factory::CreateHtmlIndex : could not open file '"
1109                  <<filename<<"'");
1110     }
1111     
1112     //----------------------
1113     // Html head
1114     s << "<html lang=\"en\">\n";
1115     s << "<head>\n";
1116     s << "<title>"<<title<<"</title>\n";
1117     s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1118     s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1119     s << "<meta name=\"generator\" content=\"\">\n";
1120     s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1121     //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1122     s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1123     s << "pre.display { font-family:inherit }\n";
1124     s << "pre.format  { font-family:inherit }\n";
1125     s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1126     s << "pre.smallformat  { font-family:inherit; font-size:smaller }\n";
1127     s << "pre.smallexample { font-size:smaller }\n";
1128     s << "pre.smalllisp    { font-size:smaller }\n";
1129     s << "span.sc    { font-variant:small-caps }\n";
1130     s << "span.roman { font-family:serif; font-weight:normal; } \n";
1131     s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n"; 
1132     s << "--></style>\n";
1133     s << "</head>\n";
1134     //----------------------
1135
1136     //----------------------
1137     // Html body
1138     s << "<body>\n";
1139     s << "<a name=\"Top\"></a>\n"; 
1140     s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1141     s << "<p>\n";
1142     IndexType::iterator ii;
1143     for (ii=index.begin();ii!=index.end();++ii)
1144       {
1145         s << "<a href=\"#"<<ii->first<<"\">"<<ii->first<<"</a>&nbsp;&nbsp;";    
1146       }
1147
1148     for (ii=index.begin();ii!=index.end();++ii)
1149       {
1150         s << "<p><hr>\n";
1151         s << "<p><a href=\"#Top\">Top</a>";
1152         if (type==Packages)
1153           {
1154             s << "<a name=\""<<ii->first<<"\"></a>\n"; 
1155             s << "<p><a href=\""<<ii->first<<"/index.html\">"
1156               << ii->first<<"</a>\n"; 
1157
1158             s << "&nbsp;&nbsp;-&nbsp;&nbsp;\n"; 
1159
1160             s << "<a name=\"doxygen\"></a>\n"; 
1161             s << "<a href=..\\doxygen\\" << ii->first << "/main.html>(Doxygen documentation of the source)</a>\n"; 
1162           }
1163         else 
1164           {
1165             s << "<a name=\""<<ii->first<<"\"></a>\n"; 
1166             s << "<p><b>"<<ii->first<<"</b>\n";
1167           }
1168         s << "<ul>\n";
1169
1170         s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1171
1172         std::vector<BlackBoxDescriptor*>::iterator di;
1173         for (di=ii->second.begin();di!=ii->second.end();++di)
1174           {
1175             std::string pack = (*di)->GetPackage()->GetName();
1176             std::string name = (*di)->GetTypeName();
1177             Utilities::html_format(name);
1178             std::string descr = (*di)->GetDescription();
1179             Utilities::html_format(descr);
1180             s << "<TR>";
1181             s << "<TD style='vertical-align: top;'>";
1182             s << "&nbsp;&nbsp;&nbsp;<a href=\""<<pack
1183               <<"/index.html#"<<name<<"\">"
1184               <<pack<<"::"<<name<<"</a>";
1185             s << "</TD> ";
1186             s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1187             s << "</TR>\n";
1188           }    
1189         s << "</TABLE>\n";
1190         s << "</ul>\n";
1191         s << "</div>\n";
1192       }
1193     //----------------------
1194     // Footer 
1195     time_t rawtime;
1196     tm * ptm;
1197     time ( &rawtime );
1198     ptm = gmtime ( &rawtime );
1199
1200     s << "<p><hr>\n";
1201     s << "Automatically generated by <b>bbi</b> on "
1202       << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900 
1203       << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1204     s << "</body></html>\n"; 
1205     s.close();
1206     //----------------------
1207
1208     // End
1209     bbtkDebugDecTab("Kernel",9);
1210   }
1211
1212
1213 }
1214