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