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