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