]> Creatis software - bbtk.git/blob - kernel/src/bbtkFactory.cxx
Compiles de nuevo with no global factory
[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 10:21:30 $
8 Version:   $Revision: 1.28 $
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,this);
727   }
728   //===================================================================
729
730
731
732   //===================================================================
733   const Package* Factory::GetPackage(const std::string& name) const
734   {
735     bbtkDebugMessageInc("Kernel",9,"Factory::GetPackage(\""<<name<<"\")"
736                          <<std::endl);
737
738     PackageMapType::const_iterator i = mPackageMap.find(name);
739     if ( i != mPackageMap.end() ) 
740     {
741       bbtkDebugDecTab("Kernel",9); 
742       return i->second.mPackage;
743     }
744     else 
745     {
746        bbtkDebugDecTab("Kernel",9);
747        bbtkError("package \""<<name<<"\" unknown");
748     }
749     
750     bbtkDebugDecTab("Kernel",9);  
751   }
752   //===================================================================
753   
754   //===================================================================
755   Package* Factory::GetPackage(const std::string& name) 
756   {
757     bbtkDebugMessageInc("Kernel",9,"Factory::GetPackage(\""<<name<<"\")"
758                          <<std::endl);
759
760     PackageMapType::const_iterator i = mPackageMap.find(name);
761     if ( i != mPackageMap.end() ) 
762     {
763       bbtkDebugDecTab("Kernel",9); 
764       return i->second.mPackage;
765     }
766     else 
767     {
768        bbtkDebugDecTab("Kernel",9);
769        bbtkError("package \""<<name<<"\" unknown");
770     }
771     
772     bbtkDebugDecTab("Kernel",9);  
773   }
774   //===================================================================
775
776   //===================================================================
777   void Factory::WriteDotFilePackagesList(FILE *ff)
778   {
779
780     bbtkDebugMessageInc("Kernel",9,"Factory::WriteDotFilePackagesList()"
781                          <<std::endl);
782
783     fprintf( ff , "\n");
784     fprintf( ff , "subgraph cluster_FACTORY {\n");
785     fprintf( ff , "  label = \"PACKAGES\"%s\n",  ";");
786     fprintf( ff , "  style=filled%s\n",";");
787     fprintf( ff , "  color=lightgrey%s\n",";");
788     fprintf( ff , "  rankdir=TB%s\n",";");
789
790     std::string url;
791     PackageMapType::const_iterator i;
792     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
793     {
794        url=GetPackage(i->first)->GetDocURL();
795        fprintf(ff,"  %s [shape=ellipse, URL=\"%s\"]%s\n",i->first.c_str(),url.c_str(),";" );
796     }
797     fprintf( ff , "}\n\n");
798     bbtkDebugDecTab("Kernel",9);
799   }
800   //===================================================================
801
802
803  void Factory::ShowGraphTypes(const std::string& name) const
804  {
805
806    bool found = false;
807    PackageMapType::const_iterator i;
808    for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
809    {
810       if (i->second.mPackage->ContainsBlackBox(name)) 
811       {
812          std::string separator = ConfigurationFile::GetInstance().Get_file_separator ();
813
814             // Don't pollute the file store with  "temp_dir" directories ...    
815          std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
816          std::string directory = "\"" + default_doc_dir + separator + "temp_dir"  +separator + "\"";
817          std::string filename2 =  default_doc_dir + separator + "temp_dir" + separator + "tmp.html"; 
818
819 #if defined(_WIN32)  
820         std::string command("start \"Titre\" /D ");
821 #else 
822         std::string command("gnome-open ");
823 #endif
824         command=command + directory +" tmp.html";
825         FILE *ff;
826         ff=fopen(filename2.c_str(),"w");
827
828         fprintf(ff,"<html><head><title>TMP</title> <script type=\"text/javascript\"> <!--\n");
829         fprintf(ff,"  window.location=\"%s#%s\";\n" , i->second.mPackage->GetDocURL().c_str(),name.c_str() );
830         fprintf(ff,"//--></script></head><body></body></html>\n");
831
832
833         //fprintf(ff, "<a  href=\"%s#%s\">Link</a>\n", i->second.mPackage->GetDocURL().c_str(),name.c_str() );
834         fclose(ff);
835         system( command.c_str() );      
836         found = true;
837      }
838    }
839     
840    bbtkDebugDecTab("Kernel",9);
841    if (!found) 
842    {
843       bbtkError("No package of the factory contains any black box <"
844                 <<name<<">");
845    }
846  }
847     
848
849
850
851   void Factory::CreateHtmlIndex(IndexEntryType type, 
852                                 const std::string& filename)
853   {
854     bbtkDebugMessageInc("Kernel",9,"Factory::CreateHtmlIndex(\""
855                         <<filename<<"\")"<<bbtkendl);
856     
857     std::string title;
858
859     typedef std::map<std::string, std::vector<BlackBoxDescriptor*> > IndexType;
860     IndexType index;
861     // Builds the index map
862     PackageMapType::const_iterator i;
863     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
864       {
865         Package* pack = i->second.mPackage;
866         if (pack->GetName()=="user") continue;
867         Package::BlackBoxMapType::const_iterator j;
868         for (j = pack->GetBlackBoxMap().begin(); 
869              j!= pack->GetBlackBoxMap().end(); 
870              ++j)
871           {
872             
873             // Skip adaptors 
874             if ( type==Adaptors )
875               {  
876                 if (j->second->GetKind() == BlackBoxDescriptor::STANDARD )
877                   continue;
878               }
879             else 
880               if (j->second->GetKind() != BlackBoxDescriptor::STANDARD )
881                 continue;
882
883             std::vector<std::string> keys;
884             if (type==Packages)
885               {
886                 std::string k("");
887                 k += pack->GetName();
888                 keys.push_back(k);
889                 title = "Boxes by package";
890               }
891             else if ((type==Initials) || (type==Adaptors))
892               {
893                 std::string init(" ");
894                 init[0] =  std::toupper(j->second->GetTypeName()[0]);
895                 keys.push_back(init);
896                 title = "Alphabetical list";
897               }
898             else if (type==Categories)
899               {
900                 // Split the category string 
901                 std::string delimiters = ";,";
902                 Utilities::SplitString(j->second->GetCategory(),
903                                        delimiters,keys);
904                 if (keys.size()==0) 
905                   keys.push_back(" NONE");
906                 title = "Boxes by category";
907               }
908     
909             
910             std::vector<std::string>::const_iterator k;
911             for (k=keys.begin(); k!=keys.end(); ++k )
912               {
913                 IndexType::iterator p;
914                 p = index.find(*k);
915                 if (p != index.end()) 
916                   {
917                     p->second.push_back(j->second);
918                   }
919                 else 
920                   {
921                     std::vector<BlackBoxDescriptor*> v;
922                     v.push_back(j->second);
923                     index[*k] = v;
924                   }
925               }
926             
927           }
928       }   
929     // Creates the file 
930     //---------------------
931     // Open output file
932     std::ofstream s;
933     s.open(filename.c_str());
934     if (!s.good()) 
935     {
936        bbtkError("Factory::CreateHtmlIndex : could not open file '"
937                  <<filename<<"'");
938     }
939     
940     //----------------------
941     // Html head
942     s << "<html lang=\"en\">\n";
943     s << "<head>\n";
944     s << "<title>"<<title<<"</title>\n";
945     s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
946     s << "<meta name=\"description\" content=\""<<title<<"\">\n";
947     s << "<meta name=\"generator\" content=\"\">\n";
948     s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
949     //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
950     s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
951     s << "pre.display { font-family:inherit }\n";
952     s << "pre.format  { font-family:inherit }\n";
953     s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
954     s << "pre.smallformat  { font-family:inherit; font-size:smaller }\n";
955     s << "pre.smallexample { font-size:smaller }\n";
956     s << "pre.smalllisp    { font-size:smaller }\n";
957     s << "span.sc    { font-variant:small-caps }\n";
958     s << "span.roman { font-family:serif; font-weight:normal; } \n";
959     s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n"; 
960     s << "--></style>\n";
961     s << "</head>\n";
962     //----------------------
963
964     //----------------------
965     // Html body
966     s << "<body>\n";
967     s << "<a name=\"Top\"></a>\n"; 
968     s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
969     s << "<p>\n";
970     IndexType::iterator ii;
971     for (ii=index.begin();ii!=index.end();++ii)
972       {
973         s << "<a href=\"#"<<ii->first<<"\">"<<ii->first<<"</a>&nbsp;&nbsp;";    
974       }
975
976     for (ii=index.begin();ii!=index.end();++ii)
977       {
978         s << "<p><hr>\n";
979         s << "<p><a href=\"#Top\">Top</a>";
980         if (type==Packages)
981           {
982             s << "<a name=\""<<ii->first<<"\"></a>\n"; 
983             s << "<p><a href=\""<<ii->first<<"/index.html\">"
984               << ii->first<<"</a>\n"; 
985
986             s << "&nbsp;&nbsp;-&nbsp;&nbsp;\n"; 
987
988             s << "<a name=\"doxygen\"></a>\n"; 
989             s << "<a href=..\\doxygen\\" << ii->first << "/main.html>(Doxygen documentation of the source)</a>\n"; 
990           }
991         else 
992           {
993             s << "<a name=\""<<ii->first<<"\"></a>\n"; 
994             s << "<p><b>"<<ii->first<<"</b>\n";
995           }
996         s << "<ul>\n";
997
998         s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
999
1000         std::vector<BlackBoxDescriptor*>::iterator di;
1001         for (di=ii->second.begin();di!=ii->second.end();++di)
1002           {
1003             std::string pack = (*di)->GetPackage()->GetName();
1004             std::string name = (*di)->GetTypeName();
1005             Utilities::html_format(name);
1006             std::string descr = (*di)->GetDescription();
1007             Utilities::html_format(descr);
1008             s << "<TR>";
1009             s << "<TD style='vertical-align: top;'>";
1010             s << "&nbsp;&nbsp;&nbsp;<a href=\""<<pack
1011               <<"/index.html#"<<name<<"\">"
1012               <<pack<<"::"<<name<<"</a>";
1013             s << "</TD> ";
1014             s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1015             s << "</TR>\n";
1016           }    
1017         s << "</TABLE>\n";
1018         s << "</ul>\n";
1019         s << "</div>\n";
1020       }
1021     //----------------------
1022     // Footer 
1023     time_t rawtime;
1024     tm * ptm;
1025     time ( &rawtime );
1026     ptm = gmtime ( &rawtime );
1027
1028     s << "<p><hr>\n";
1029     s << "Automatically generated by <b>bbi</b> on "
1030       << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900 
1031       << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1032     s << "</body></html>\n"; 
1033     s.close();
1034     //----------------------
1035
1036     // End
1037     bbtkDebugDecTab("Kernel",9);
1038   }
1039
1040
1041 }
1042