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