]> Creatis software - bbtk.git/blob - kernel/src/bbtkFactory.cxx
Abs paths on Windows
[bbtk.git] / kernel / src / bbtkFactory.cxx
1 /*=========================================================================
2                                                                                 
3 Program:   bbtk
4 Module:    $RCSfile: bbtkFactory.cxx,v $
5 Language:  C++
6
7 Date:      $Date: 2008/01/29 10:56:03 $
8 Version:   $Revision: 1.5 $
9                                                                                 
10
11 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
12 l'Image). All rights reserved. See doc/license.txt or
13 http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
14
15 This software is distributed WITHOUT ANY WARRANTY; without even
16 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
17 PURPOSE.  See the above copyright notices for more information.
18
19 =========================================================================*/
20 /**
21  *\file
22  *\brief  Class bbtk::Factory : can load and unload dynamic libraries containing 
23  *        black boxes packages and create instances of the black boxes registered 
24  *       in the packages loaded.
25  */
26 #include "bbtkFactory.h"
27 #include "bbtkMessageManager.h"
28 #include "bbtkConnection.h"
29 #include "bbtkConfigurationFile.h"
30 #include "bbtkUtilities.h"
31
32 #include <sys/stat.h> // for struct stat stFileInfo
33
34 #if defined(_WIN32)
35 #include <direct.h> // for getcwd
36 #endif
37
38
39 // was in gdcm ...
40 /*
41 #ifdef _MSC_VER
42 #   define getcwd _getcwd
43 #endif
44
45 #if defined(_MSC_VER) || defined(__BORLANDC__)
46 #   include <direct.h>
47 #else
48 #   include <unistd.h>
49 #endif
50
51 */
52
53
54 namespace bbtk
55 {
56   typedef Package* (*PackageAccessor)();
57   typedef void (*PackageDeleteFunction)();
58
59
60   //===================================================================
61   /// Default ctor
62   Factory::Factory()
63   {
64     bbtkDebugMessage("Core",7,"Factory::Factory()"<<std::endl);
65   }
66   //===================================================================
67
68   //===================================================================
69   /// Dtor
70   Factory::~Factory()
71   {
72     bbtkDebugMessageInc("Core",7,"Factory::~Factory()"<<std::endl);
73     CloseAllPackages();
74     bbtkDebugDecTab("Core",7);
75   }
76   //===================================================================
77
78
79   //===================================================================
80   void Factory::CloseAllPackages()
81   {
82     bbtkDebugMessageInc("Core",7,"Factory::CloseAllPackages()"<<std::endl);
83     while (mPackageMap.begin() != mPackageMap.end())
84       {
85         PackageMapType::iterator i = mPackageMap.begin();
86         ClosePackage(i);
87       }
88     bbtkDebugDecTab("Core",7);
89   }
90   //===================================================================
91
92   //===================================================================
93   void Factory::Reset()
94   {
95     bbtkDebugMessageInc("Core",7,"Factory::Reset()"<<std::endl);
96     CloseAllPackages();
97     bbtkDebugDecTab("Core",7);
98   }
99   //===================================================================
100
101
102 // ===================================================================================
103
104   bool Factory::DoLoadPackage(std::string libname,
105                               std::string pkgname,
106                               std::string path,
107                               bool verbose)
108   {
109
110 #if defined(__GNUC__)
111
112         void *handler;
113         handler = dlopen(libname.c_str(),
114                                      BBTK_RTLD_TIME | BBTK_RTLD_SCOPE );
115         if (!handler)
116         {
117         // The following is *NOT* a debug time message :
118         // It's a user intended message.
119         // Please don't remove it.
120           if (verbose) {
121             std::cout <<"[" <<libname<<"] can't be open" << std::endl;
122             std::cout << "   " <<dlerror() << std::endl;
123           }
124           return false; // try next path
125         }
126
127         // The following is *NOT* a debug time message :
128         // It's a user intended message.
129         // Please don't remove it.
130         if (verbose)
131           std::cout <<"   -->[" <<libname<<"] found" << std::endl;
132
133       // Loads the Package accessor
134
135         std::string getpackname(pkgname);
136         getpackname += "GetPackage";
137         void *getpack = dlsym(handler, getpackname.c_str());
138         if (!getpack)
139         {
140           dlclose(handler);
141           bbtkError("GetPackage : could not load package \""<<pkgname
142                    <<"\" [symbol "<<getpackname<<"] :"<<dlerror());
143         }
144
145         // Verifies that the Package delete function is present
146         std::string delfname(pkgname);
147         delfname += "DeletePackage";
148         void *delf = dlsym(handler, delfname.c_str());
149         if (!delf)
150         {
151           dlclose(handler);
152           bbtkError("DeletePackage : could not load package \""<<pkgname
153                     <<"\" [symbol "<<delfname<<"] :"<<dlerror());
154         }
155
156 #elif defined(_WIN32)
157
158         HINSTANCE handler;
159
160         SetErrorMode(0);
161         handler = LoadLibrary(libname.c_str());
162         if (!handler){
163           if (verbose)
164         // The following is *NOT* a debug time message :
165         // It's a user intended message.
166         // Please don't remove it.
167             std::cout <<"   no handler for [" <<libname<<"];" << std::endl;
168           return false;// Problem with the found library
169         }
170         if (verbose)
171           std::cout <<"   --->[" <<libname<<"] found" << std::endl;
172
173     // Loads the Package accessor
174
175         std::string getpackname(pkgname);
176         getpackname += "GetPackage";
177         void *getpack = GetProcAddress(handler, getpackname.c_str());
178         if (!getpack)
179         {
180           FreeLibrary(handler);
181           bbtkError("[1]could not load package \""<<pkgname
182           <<"\" : "<<getpackname<<" symbol not found (is it a bbtk package lib ?)");
183           // look how to get the error message on win
184               //<<dlerror());
185         }
186         // Verifies that the Package delete function is present
187         std::string delfname(pkgname);
188         delfname += "DeletePackage";
189         void *delf = GetProcAddress(handler, delfname.c_str());
190         if (!delf)
191         {
192           FreeLibrary(handler);
193           bbtkError("[2]could not load package \""<<pkgname
194                      <<"\" : "<<delfname<<" symbol not found (is it a bbtk package lib ?)");
195           // look how to get the error message on win
196           //<<dlerror());
197         }
198 #else
199         bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
200 #endif
201
202     // Stores the package
203         PackageInfoType pack;
204         pack.mDynamicLibraryHandler = handler;
205     // Invokes the accessor to the PackageUnit pointer
206         pack.mPackage = ((PackageAccessor)getpack)();
207
208         mPackageMap[pkgname] = pack;
209
210     // Test bbtk build version ok
211         if ( pack.mPackage->GetBBTKVersion() != bbtk::GetVersion() )
212         {
213           std::string v(pack.mPackage->GetBBTKVersion());
214           UnLoadPackage(pkgname);
215           bbtkError(" package build with bbtk version "
216                     << v
217                     << " whereas application build with version "
218                     << bbtk::GetVersion());
219         }
220
221         std::string separator =
222         ConfigurationFile::GetInstance().Get_file_separator ();
223         //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
224         std::string docreldoc = separator + "packages" + separator + pkgname
225          + separator + "bbdoc" + separator + "index.html";
226         std::string reldoc = ".." + separator + ".." + separator
227          + ".." + docreldoc;
228         std::string doc = path + separator + ".." + separator
229          + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
230          + docreldoc;
231
232         pack.mPackage->SetDocURL(doc);
233         pack.mPackage->SetDocRelativeURL(reldoc);
234
235     //===================================================================
236         bbtkMessage("Output",2,pack.mPackage->GetName()<<" "
237            <<pack.mPackage->GetVersion()
238            <<" (bbtk "
239            <<pack.mPackage->GetBBTKVersion()<<") "
240            <<pack.mPackage->GetAuthor()
241            <<std::endl);
242         bbtkMessage("Output",2,pack.mPackage->GetDescription()<<std::endl);
243     //===================================================================
244
245         bbtkDebugDecTab("Core",7);
246         return true;
247   }
248
249   //===================================================================
250   /// \brief Loads a package.
251   ///
252   /// The name is the system-independant name of the package (the name of the instance of bbtk::Package).
253   /// Tries to open the dynamic library :
254   /// - "libbb<name>.so" for linux systems,
255   /// - "bb<name>.dll" for windows systems.
256   /// If it succeeds, then tries to load the symbols "<name>GetPackage" and "<name>DeletePackage".
257   /// "<name>GetPackage" is called to get the pointer on the bbtk::Package of the library
258   /// ("<name>DeletePackage" is not used, its presence is just checked before loading the package).
259
260   /// now, filename is only the last name (no longer the full name!)
261   /// it will be searched within *all* the paths given in bbtk_config.xml
262
263   /// verbose = true (set by "config v") displays the loading process
264
265   void Factory::LoadPackage( const std::string& name,
266                              bool use_configuration_file, bool verbose)
267   {
268   // Note : in the following :
269   // name : the user supplied name
270   //      - abreviated name    e.g.       pkg   pkg.so   libbpkg   libbbpkg.so
271   //      - relative full name e.g.       ./libbbpkg.so   ../../libbbpkg.so
272   //      - absolute full name e.g.       /home/usrname/proj/lib/libbbpkg.so
273   //          same for Windows, with      c:, d: ...
274   //
275   // lastname : string before the last / (if any), or user supplied name
276
277     bbtkDebugMessageInc("Core",7,"Factory::LoadPackage(\""<<name<<"\")"<<std::endl);
278     bbtkMessage("Debug",1,"Factory::LoadPackage(\""<<name<<"\")"<<std::endl);
279     bbtkMessage("Debug",1,"use_configuration_file ["
280                  << use_configuration_file << "]" << std::endl);
281
282     std::vector<std::string> package_paths;
283     std::string libname;  // full path library name
284     std::string pkgname;  // e.g. libbb<pkgname>.so
285
286     std::string upath;
287     pkgname = Utilities::ExtractPackageName(name,upath);
288
289     bbtkMessage("Debug",1,"Package name ["<<pkgname<<"]"<<std::endl);
290     bbtkMessage("Debug",1,"Package path ["<<upath<<"]"<<std::endl);
291
292     // no loading package if already loaded
293     PackageMapType::iterator iUnload;
294     iUnload = mPackageMap.find(pkgname);
295     if (iUnload != mPackageMap.end())
296     {
297       bbtkMessage("Output",2,"["<< pkgname <<"] already loaded" << std::endl);
298       return;
299     }
300
301
302 // =================================================
303 // The following structure was checked to work
304 // with any type of relative/absolute path.
305 // Please don't modify it without checking
306 // *all* the cases. JP
307 //==================================================
308
309 //std::cout << "upath [" << upath << "]" << std::endl;
310
311     bool ok = false;
312     bool foundFile = false;
313
314     // If path provided by user will be the first scanned :
315     // push it into vector of paths
316     if (upath.length()>0)   // ------------------------------------- check user supplied location
317     {
318        if (name[0] != '.' && name[0] != '/' && name[1]!= ':')
319        {
320           bbtkError("Use absolute or relative path name! ["<<name<<"] is an illegal name");
321           return;
322        }
323        
324       // std::string path = Utilities::ExpandLibName(upath, verbose);
325        std::string path;
326        if (name[1]!= ':')  // Absolute name, under Windows
327           path = Utilities::ExpandLibName(name, verbose); // keep last item, here.
328           
329        if (path != "")
330        {
331           std::string p2;
332           Utilities::ExtractPackageName(path,p2);
333           //libname = Utilities::MakeLibnameFromPath(path, pkgname);
334           libname = Utilities::MakeLibnameFromPath(p2, pkgname); // remove last item
335           // Check if library exists
336           if ( !Utilities::FileExists(libname) )
337           {
338           // The following is *NOT* a debug time message :
339           // It's a user intended message.
340           // Please don't remove it.
341              if (verbose)
342                 std::cout <<"   [" <<libname <<"] : doesn't exist" <<std::endl;
343           }
344           else
345           {
346              ok = DoLoadPackage( libname, pkgname, path, verbose);         
347           }
348        }
349        else
350        {
351           bbtkError("Path ["<<upath<<"] doesn't exist");
352           return;
353        }
354     }
355     else     // ----------------------------------------------------- iterate on the paths  
356     {
357
358     std::string path;
359     package_paths = ConfigurationFile::GetInstance().Get_package_paths();
360     std::vector<std::string>::iterator i;
361     for (i=package_paths.begin();i!=package_paths.end();++i)
362     {
363         foundFile = false;
364         path = *i;
365
366         // we *really* want '.' to be the current working directory
367         if (path == ".")
368         {
369           char buf[2048]; // for getcwd
370           char * currentDir = getcwd(buf, 2048);
371           std::string cwd(currentDir);
372           path = currentDir;
373         }
374
375         libname = Utilities::MakeLibnameFromPath(path, pkgname);
376
377         bbtkMessage("Debug",2,"-> Trying to load [" << libname << "]" <<std::endl);
378
379       // Check if library exists           
380         if ( !Utilities::FileExists(libname) )
381         {
382         // The following is *NOT* a debug time message :
383         // It's a user intended message.
384         // Please don't remove it.
385            if (verbose)
386               std::cout <<"   [" <<libname <<"] : doesn't exist" <<std::endl;
387            continue;  // try next path
388         }
389         foundFile = true; 
390
391       // Try to Load the library
392
393         ok = DoLoadPackage( libname, pkgname, path, verbose);
394         if (ok)
395         {
396            bbtkMessage("Debug",2,"   OK"<<std::endl);
397            break; // a package was found; we stop iterating
398         }
399     } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
400
401 }
402
403     if( !ok )  // nothing was loaded
404     {
405       if (!foundFile)
406       {
407         bbtkError("could not find package ["<<pkgname<< "]");
408       }
409       else
410       {
411 #if defined(__GNUC__)
412         bbtkError("could not load package ["<< pkgname
413                   <<"] :" << std::endl << "   " << dlerror());
414 #elif defined(_WIN32)
415         bbtkError("could not load package ["<<pkgname
416                  <<"] : " << std::endl << "   " <<libname<<" not found");
417
418     // look how to get the error message on win
419     //<<dlerror());
420     // it is the bordel !! (the bloody fucking bordel, you mean?)
421     // look : http://msdn2.microsoft.com/en-us/library/ms680582.aspx
422 #endif
423       }
424     }
425     bbtkMessage("Output",2,"[" << libname << "] loaded" << std::endl);
426
427   }
428
429   //===================================================================
430   /// \brief UnLoads a package.
431   ///
432   /// The package must have been previously loaded by LoadPackage.
433   /// If the entry is found in the map, calls ClosePackage
434  void Factory::UnLoadPackage( const std::string& name )
435  {
436     bbtkDebugMessageInc("Core",7,"Factory::UnLoadPackage(\""
437                        <<name<<"\")"<<std::endl);
438   
439     PackageMapType::iterator i;
440     i = mPackageMap.find(name);
441     if (i == mPackageMap.end()) 
442     {
443       bbtkError("cannot unload package \""<<name
444                 <<"\" : package not loaded !");
445     }
446     ClosePackage(i);
447     bbtkDebugDecTab("Core",7);
448   }
449   //===================================================================
450
451
452   //===================================================================
453   /// \brief Close the package referenced by the iterator 
454   ///
455   /// If it is a dynamically loaded package 
456   /// - Loads and calls the function "<name>DeletePackage" of the dynamic library (responsible for package desallocation)
457   /// - Closes the dynamic library
458   /// - Erases the package entry in the packages map
459   ///
460   /// Else simply erases the package entry in the packages map
461   void Factory::ClosePackage(PackageMapType::iterator& i) 
462   {   
463      bbtkDebugMessageInc("Core",7,"Factory::ClosePackage(\""
464                          <<i->second.mPackage->GetName()
465                         <<"\")"<<std::endl);
466
467      if (i->second.mDynamicLibraryHandler) 
468      {
469  
470       // If it is a dynamically loaded package
471       // Loads the Package delete function
472
473         std::string delfname(i->second.mPackage->GetName());
474         delfname += "DeletePackage";
475 #if defined(__GNUC__)     
476         void *delf = dlsym(i->second.mDynamicLibraryHandler, delfname.c_str());
477         if (!delf)
478         {
479            bbtkError("could not close package \""
480                      <<i->second.mPackage->GetName()
481                      <<"\" :"<<dlerror());
482         }    
483 #elif defined(_WIN32)
484    void *delf = GetProcAddress(i->second.mDynamicLibraryHandler, 
485                                  delfname.c_str());
486      if (!delf)
487      {  
488        bbtkError("could not close package \""
489                 <<i->second.mPackage->GetName()
490                 <<"\" : "<<delfname
491                 <<" symbol not found (how did you open it ???");
492                //<<"\" :"<<dlerror());
493      }    
494 #endif     
495
496    // deletes the package
497    ((PackageDeleteFunction)delf)();
498
499    // closes the dl handler
500 #if defined(__GNUC__)  
501     dlclose(i->second.mDynamicLibraryHandler);  
502 #elif defined(_WIN32)
503
504     FreeLibrary(i->second.mDynamicLibraryHandler);
505 #endif
506     }
507     else 
508     {  
509        // If it is a manually inserted package 
510        delete i->second.mPackage;
511     }
512
513     // remove the entry in the map
514     mPackageMap.erase(i);
515     bbtkDebugDecTab("Core",7);
516  }
517   //===================================================================
518
519
520
521   //===================================================================  
522   /// Displays the list of packages loaded
523   void Factory::PrintPackages(bool details, bool adaptors) const
524   {
525     bbtkDebugMessageInc("Core",9,"Factory::PrintPackages"<<std::endl);
526
527     PackageMapType::const_iterator i;
528     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
529     {
530       bbtkMessage("Help",1, i->first << std::endl);
531       if (details) {
532          i->second.mPackage->PrintBlackBoxes(false,adaptors);
533       }
534     }
535
536     bbtkDebugDecTab("Core",9);
537   }
538   //===================================================================
539
540   //===================================================================  
541   /// Displays help on a package
542   void Factory::HelpPackage(const std::string& name, bool adaptors) const
543   {
544     bbtkDebugMessageInc("Core",9,"Factory::HelpPackage(\""<<name<<"\")"
545                         <<std::endl);
546
547     PackageMapType::const_iterator i = mPackageMap.find(name);
548     if ( i != mPackageMap.end() ) 
549       {
550       bbtkMessage("Help",1, "Package "<<i->first<<" ");
551       if (i->second.mPackage->GetVersion().length()>0)
552         bbtkMessageCont("Help",1,"v" <<i->second.mPackage->GetVersion());
553       if (i->second.mPackage->GetAuthor().length()>0)
554         bbtkMessageCont("Help",1,"- "<<i->second.mPackage->GetAuthor());
555       bbtkMessageCont("Help",1,std::endl);
556       bbtkIncTab("Help",1);
557       bbtkMessage("Help",1,i->second.mPackage->GetDescription()<<std::endl);
558       if (i->second.mPackage->GetNumberOfBlackBoxes()>0) 
559         {
560           bbtkMessage("Help",1, "Black boxes : "<<std::endl);
561           i->second.mPackage->PrintBlackBoxes(true,adaptors);
562         }
563       else 
564         {
565           bbtkMessage("Help",1, "No black boxes"<<std::endl);
566         }
567       bbtkDecTab("Help",1);
568       }
569     else 
570       {
571       bbtkDebugDecTab("Core",9);
572       bbtkError("package \""<<name<<"\" unknown");
573       }
574     
575     bbtkDebugDecTab("Core",9);
576   }
577   //===================================================================
578
579   //===================================================================
580   /// Prints help on the black box of type <name>
581   void Factory::HelpBlackBox(const std::string& name, bool full) const
582   {
583     bbtkDebugMessageInc("Core",9,"Factory::HelpBlackBox(\""<<name<<"\")"
584                         <<std::endl);
585
586     bool found = false;
587     PackageMapType::const_iterator i;
588     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
589       {
590       if (i->second.mPackage->ContainsBlackBox(name)) 
591         {
592           i->second.mPackage->HelpBlackBox(name,full);
593           found = true;
594         }
595       }
596     
597     bbtkDebugDecTab("Core",9);
598     if (!found) 
599       {
600       bbtkError("No package of the factory contains any black box <"
601                  <<name<<">");
602       }
603   }  
604   //===================================================================
605
606
607   //=================================================================== 
608   /// Inserts a package in the factory
609   void Factory::InsertPackage( Package* p )
610   {
611     bbtkDebugMessageInc("Core",9,"Factory::InsertPackage(\""<<
612                         p->GetName()<<"\")"<<std::endl);
613
614     PackageInfoType pack;
615     pack.mDynamicLibraryHandler = 0;
616     
617     pack.mPackage = p;
618
619     mPackageMap[p->GetName()] = pack;
620     bbtkDebugDecTab("Core",9);
621   }
622   //===================================================================
623   
624   //=================================================================== 
625   /// Removes a package from the factory (and deletes it)
626   void Factory::RemovePackage( Package* p )
627   {
628     bbtkDebugMessageInc("Core",9,"Factory::RemovePackage(\""<<
629                         p->GetName()<<"\")"<<std::endl);
630
631     PackageMapType::iterator i;
632     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
633       {
634          if (i->second.mPackage == p) break;
635       };
636     
637     if (i!=mPackageMap.end())
638       {
639       ClosePackage(i);
640       }
641     else 
642       {
643       bbtkError("Factory::RemovePackage(\""<<
644                  p->GetName()<<"\") : package absent from factory");
645       }
646
647     bbtkDebugDecTab("Core",9);
648   }
649   //===================================================================
650   
651
652   //===================================================================
653   /// Creates an instance of a black box of type <type> with name <name>
654   BlackBox* Factory::NewBlackBox(const std::string& type, 
655                                  const std::string& name) const
656   {
657     bbtkDebugMessageInc("Core",7,"Factory::NewBlackBox(\""
658                         <<type<<"\",\""<<name<<"\")"<<std::endl);
659
660     BlackBox* b = 0; 
661     PackageMapType::const_iterator i;
662     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
663       {
664       b = i->second.mPackage->NewBlackBox(type,name);
665       if (b) break; 
666       }
667     if (!b) 
668       {
669        bbtkError("black box type \""<<type<<"\" unknown");
670       } 
671
672     bbtkDebugDecTab("Core",7);
673     return b;
674   }
675   //===================================================================
676
677   //===================================================================
678   /// Creates an instance of a black box of type <type> with name <name>
679   BlackBox* Factory::NewAdaptor(TypeInfo typein,
680                      TypeInfo typeout,
681                      const std::string& name) const
682   {
683     bbtkDebugMessageInc("Core",8,"Factory::NewAdaptor(<"
684                         <<TypeName(typein)<<">,<"
685                         <<TypeName(typeout)<<">,\""
686                         <<name<<"\")"<<bbtkendl);
687
688
689     BlackBox* b = 0; 
690     PackageMapType::const_iterator i;
691     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
692       {
693       b = i->second.mPackage->NewAdaptor(typein,typeout,name);
694       if (b) break; 
695       }
696     if (!b) 
697       {
698       bbtkError("no <"
699           <<TypeName(typein)<<"> to <"
700           <<TypeName(typeout)
701           <<"> adaptor available");
702       } 
703     
704     bbtkDebugDecTab("Core",7);
705     return b; 
706   }
707   //===================================================================
708
709   //===================================================================
710   /// Creates an instance of a connection
711   Connection* Factory::NewConnection(BlackBox* from,
712                                      const std::string& output,
713                                      BlackBox* to,
714                                      const std::string& input) const
715   {
716     bbtkDebugMessage("Core",7,"Factory::NewConnection(\""
717                       <<from->bbGetName()<<"\",\""<<output<<"\",\""
718                       <<to->bbGetName()<<"\",\""<<input
719                       <<"\")"<<std::endl);
720     
721     return new Connection(from,output,to,input);
722     /*  
723        Connection* c;
724     // !!! WARNING : WE NEED TO TEST THE TYPE NAME EQUALITY 
725     // BECAUSE IN DIFFERENT DYN LIBS THE type_info EQUALITY CAN 
726     // BE FALSE (DIFFERENT INSTANCES !)
727   
728     std::string t1 ( from->bbGetOutputType(output).name() );
729     std::string t2 ( to->bbGetInputType(input).name() );
730
731
732     if ( t1 == t2 ) 
733        //from->bbGetOutputType(output) ==
734        // to->bbGetInputType(input) )
735       {
736          c = new Connection(from,output,to,input);
737       }
738     else 
739       {
740          //   std::cout << "Adaptive connection "<<std::endl;
741          std::string name;
742          name = from->bbGetName() + "." + output + "-" 
743                                   + to->bbGetName() + "." + input; 
744
745          BlackBox* b = 0; 
746          PackageMapType::const_iterator i;
747          for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
748          {
749              b = i->second.mPackage->NewAdaptor(from->bbGetOutputType(output),
750                                                   to->bbGetInputType(input),
751                                                   name);
752              if (b) break; 
753          } 
754          if (!b)  
755          {  
756             bbtkError("did not find any <"
757                        <<TypeName(from->bbGetOutputType(output))
758                        <<"> to <"
759                        <<TypeName(to->bbGetInputType(input))
760                        <<"> adaptor");
761          } 
762          c = new AdaptiveConnection(from,output,to,input,b);
763       }
764       bbtkDebugDecTab("Core",7);
765     
766       return c;
767     */
768   }
769   //===================================================================
770
771
772
773   //===================================================================
774   const Package* Factory::GetPackage(const std::string& name) const
775   {
776     bbtkDebugMessageInc("Core",9,"Factory::GetPackage(\""<<name<<"\")"
777                          <<std::endl);
778
779     PackageMapType::const_iterator i = mPackageMap.find(name);
780     if ( i != mPackageMap.end() ) 
781     {
782       bbtkDebugDecTab("Core",9); 
783       return i->second.mPackage;
784     }
785     else 
786     {
787        bbtkDebugDecTab("Core",9);
788        bbtkError("package \""<<name<<"\" unknown");
789     }
790     
791     bbtkDebugDecTab("Core",9);  
792   }
793   //===================================================================
794   
795   //===================================================================
796   Package* Factory::GetPackage(const std::string& name) 
797   {
798     bbtkDebugMessageInc("Core",9,"Factory::GetPackage(\""<<name<<"\")"
799                          <<std::endl);
800
801     PackageMapType::const_iterator i = mPackageMap.find(name);
802     if ( i != mPackageMap.end() ) 
803     {
804       bbtkDebugDecTab("Core",9); 
805       return i->second.mPackage;
806     }
807     else 
808     {
809        bbtkDebugDecTab("Core",9);
810        bbtkError("package \""<<name<<"\" unknown");
811     }
812     
813     bbtkDebugDecTab("Core",9);  
814   }
815   //===================================================================
816
817   //===================================================================
818   void Factory::WriteDotFilePackagesList(FILE *ff)
819   {
820     bbtkDebugMessageInc("Core",9,"Factory::WriteDotFilePackagesList()"
821                          <<std::endl);
822
823     fprintf( ff , "\n");
824     fprintf( ff , "subgraph cluster_FACTORY {\n");
825     fprintf( ff , "  label = \"PACKAGES\"%s\n",  ";");
826     fprintf( ff , "  style=filled%s\n",";");
827     fprintf( ff , "  color=lightgrey%s\n",";");
828     fprintf( ff , "  rankdir=TB%s\n",";");
829
830     std::string url;
831     PackageMapType::const_iterator i;
832     for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
833     {
834        url=GetPackage(i->first)->GetDocURL();
835        fprintf(ff,"  %s [shape=ellipse, URL=\"%s\"]%s\n",i->first.c_str(),url.c_str(),";" );
836     }
837     fprintf( ff , "}\n\n");
838     bbtkDebugDecTab("Core",9);
839   }
840   //===================================================================
841
842
843  void Factory::ShowGraphTypes(const std::string& name) const
844  {
845    bool found = false;
846    PackageMapType::const_iterator i;
847    for (i = mPackageMap.begin(); i!=mPackageMap.end(); ++i )
848    {
849       if (i->second.mPackage->ContainsBlackBox(name)) 
850       {
851          std::string separator = ConfigurationFile::GetInstance().Get_file_separator ();
852
853             // Don't pollute the file store with  "doc_tmp" directories ...    
854          std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_doc_tmp();
855          std::string directory = "\"" + default_doc_dir + separator + "doc_tmp"  +separator + "\"";
856          std::string filename2 =  default_doc_dir + separator + "doc_tmp" + separator + "tmp.html"; 
857
858 #if defined(_WIN32)  
859         std::string command("start \"Titre\" /D ");
860 #else 
861         std::string command("gnome-open ");
862 #endif
863         command=command + directory +" tmp.html";
864         FILE *ff;
865         ff=fopen(filename2.c_str(),"w");
866
867         fprintf(ff,"<html><head><title>TMP</title> <script type=\"text/javascript\"> <!--\n");
868         fprintf(ff,"  window.location=\"%s#%s\";\n" , i->second.mPackage->GetDocURL().c_str(),name.c_str() );
869         fprintf(ff,"//--></script></head><body></body></html>\n");
870
871
872         //fprintf(ff, "<a  href=\"%s#%s\">Link</a>\n", i->second.mPackage->GetDocURL().c_str(),name.c_str() );
873         fclose(ff);
874         system( command.c_str() );      
875         found = true;
876      }
877    }
878     
879    bbtkDebugDecTab("Core",9);
880    if (!found) 
881    {
882       bbtkError("No package of the factory contains any black box <"
883                 <<name<<">");
884    }
885  }
886
887 }
888