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