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