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