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