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