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