KWStyle - itkObjectFactoryBase.cxx
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkObjectFactoryBase.cxx.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:43 $
7   Version:   $Revision: 1.4 $
8
9   Copyright (c) Insight Software Consortium. All rights reserved.
10   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11
12   Portions of this code are covered under the VTK copyright.
13   See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm 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 IND *****PURPOSE.  See the above copyright notices for more information.
18
19 DEF =========================================================================*/
20 #if defined(_MSC_VER)
21 #pragma warning ( disable : 4786 )
22 #endif
23
24 #include "itkObjectFactoryBase.h"
25 #include "itkDynamicLoader.h"
26 #include "itkDirectory.h"
27 #include "itkVersion.h"
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <algorithm>
31 #include <map>
32
33 NMS namespace
34 {
35   
36 class CleanUpObjectFactory
37 {
38 public:
39   inline void Use() 
40 IND **{
41 IND **}
42   ~CleanUpObjectFactory()
43 IND **{
44     itk::ObjectFactoryBase::UnRegisterAllFactories();
45 IND **}  
46 };
47 static CleanUpObjectFactory CleanUpObjectFactoryGlobal;
48 }
49
50
51 EML
52 EML
53 namespace itk
54 {
55
56 /**
57  * Add this for the SGI compiler which does not seem
58  * to provide a default implementation as it should.
59  */
60 bool operator==(const ObjectFactoryBase::OverrideInformation& rhs, 
61                 const ObjectFactoryBase::OverrideInformation& lhs)
62 {
63   return (rhs.m_Description == lhs.m_Description
64           && rhs.m_OverrideWithName == lhs.m_OverrideWithName);
65 }
66
67 /**
68  * Add this for the SGI compiler which does not seem
69  * to provide a default implementation as it should.
70  */
71 bool operator<(const ObjectFactoryBase::OverrideInformation& rhs, 
72                const ObjectFactoryBase::OverrideInformation& lhs)
73 {
74   return (rhs.m_Description < lhs.m_Description
75           && rhs.m_OverrideWithName < lhs.m_OverrideWithName);
76 }
77
78
79 /** \class StringOverMap
80  * \brief Internal implementation class for ObjectFactorBase.
81  *
82  * Create a sub class to shrink the size of the symbols
83  * Also, so a forward reference can be put in ObjectFactoryBase.h
84  * and a pointer member can be used.  This avoids other
85  * classes including <map> and getting long symbol warnings.
86  */
87 typedef std::multimap<std::string, ObjectFactoryBase::OverrideInformation> 
88 StringOverMapType;
89
90 /** \class OverRideMap
91  * \brief Internal implementation class for ObjectFactorBase.
92  */
93 class OverRideMap : public StringOverMapType
94 {
95 public:
96 };
97
98 /**
99  * Initialize static list of factories.
100  */
101 std::list<ObjectFactoryBase*>* 
102 ObjectFactoryBase::m_RegisteredFactories = 0;
103
104
105 /**
106  * Create an instance of a named itk object using the loaded
107  * factories
108  */
109 LightObject::Pointer 
110 ObjectFactoryBase
111 ::CreateInstance(const char* itkclassname)
112 {
113   if ( !ObjectFactoryBase::m_RegisteredFactories )
114     {
115     ObjectFactoryBase::Initialize();
116     }
117   
118   for ( std::list<ObjectFactoryBase*>::iterator 
119           i = m_RegisteredFactories->begin();
120 IND ********i != m_RegisteredFactories->end(); ++i )
121     {
122     LightObject::Pointer newobject = (*i)->CreateObject(itkclassname);
123     if(newobject)
124       {
125       return newobject;
126       }
127     }
128   return 0;
129 }
130
131
132 std::list<LightObject::Pointer>
133 ObjectFactoryBase
134 ::CreateAllInstance(const char* itkclassname)
135 {
136   if ( !ObjectFactoryBase::m_RegisteredFactories )
137     {
138     ObjectFactoryBase::Initialize();
139     }
140   std::list<LightObject::Pointer> created;
141   for ( std::list<ObjectFactoryBase*>::iterator 
142           i = m_RegisteredFactories->begin();
143 IND ********i != m_RegisteredFactories->end(); ++i )
144     {
145     LightObject::Pointer newobject = (*i)->CreateObject(itkclassname);
146     if(newobject)
147       {
148       created.push_back(newobject);
149       }
150     }
151   return created;
152 }
153
154
155 /**
156  * A one time initialization method.
157  */
158 void 
159 ObjectFactoryBase
160 ::Initialize()
161 {
162   CleanUpObjectFactoryGlobal.Use();
163   /**
164    * Don't do anything if we are already initialized
165    */
166   if ( ObjectFactoryBase::m_RegisteredFactories )
167     {
168     return;
169     }
170   
171   ObjectFactoryBase::m_RegisteredFactories =
172 IND ****new std::list<ObjectFactoryBase*>;
173   ObjectFactoryBase::RegisterDefaults();
174   ObjectFactoryBase::LoadDynamicFactories();
175 }
176
177
178 /**
179  * Register any factories that are always present in ITK like
180  * the OpenGL factory, currently this is not done.
181  */
182 void 
183 ObjectFactoryBase
184 ::RegisterDefaults()
185 {
186 }
187
188 /**
189  * Load all libraries in ITK_AUTOLOAD_PATH
190  */
191 void 
192 ObjectFactoryBase
193 ::LoadDynamicFactories()
194 {
195   /**
196    * follow PATH conventions
197    */
198 #ifdef _WIN32
199   char PathSeparator = ';';
200 IND #else
201   char PathSeparator = ':';
202 #endif
203   
204   std::string LoadPath;
205   if (getenv("ITK_AUTOLOAD_PATH"))
206     {
207     LoadPath = getenv("ITK_AUTOLOAD_PATH");
208     }
209   else
210     {
211     return;
212     }
213
214   if(LoadPath.size() == 0)
215     {
216     return;
217     }
218   std::string::size_type EndSeparatorPosition = 0;
219   std::string::size_type StartSeparatorPosition = 0;
220   while ( StartSeparatorPosition != std::string::npos )
221     {
222     StartSeparatorPosition = EndSeparatorPosition;
223     /**
224      * find PathSeparator in LoadPath
225      */
226     EndSeparatorPosition = LoadPath.find(PathSeparator, 
227                                          StartSeparatorPosition);
228     if(EndSeparatorPosition == std::string::npos)
229       {
230       EndSeparatorPosition = LoadPath.size();
231       }
232     std::string CurrentPath = 
233 IND ******LoadPath.substr(StartSeparatorPosition, EndSeparatorPosition);
234     ObjectFactoryBase::LoadLibrariesInPath(CurrentPath.c_str());
235     /**
236      * move past separator
237      */
238     if(EndSeparatorPosition == LoadPath.size())
239       {
240       StartSeparatorPosition = std::string::npos;
241       }
242     else
243       {
244       EndSeparatorPosition++;
245       }
246     }
247 }
248
249
250 /**
251  * A file scope helper function to concat path and file into
252  * a full path
253  */
254 static std::string 
255 CreateFullPath(const char* path, const char* file)
256 {
257   std::string ret;
258 #ifdef _WIN32
259   const char sep = '\\';
260 IND #else
261   const char sep = '/';
262 #endif
263   /**
264    * make sure the end of path is a separator
265    */
266   ret = path;
267   if ( ret[ret.size()-1] != sep )
268     {
269     ret += sep;
270     }
271   ret += file;
272   return ret;
273 }
274
275
276 /**
277  * A file scope typedef to make the cast code to the load
278  * function cleaner to read.
279  */
280 typedef ObjectFactoryBase* (* ITK_LOAD_FUNCTION)();
281
282
283 /**
284  * A file scoped function to determine if a file has
285  * the shared library extension in its name, this converts name to lower
286  * case before the compare, DynamicLoader always uses
287  * lower case for LibExtension values.
288  */
289 inline bool 
290 NameIsSharedLibrary(const char* name)
291 {
292   std::string sname = name;
293   if ( sname.find(DynamicLoader::LibExtension()) != std::string::npos )
294     {
295     return true;
296     }
297   return false;
298 }
299
300
301 /**
302  *
303  */
304 void 
305 ObjectFactoryBase
306 ::LoadLibrariesInPath(const char* path)
307 {
308   Directory::Pointer dir = Directory::New();
309   if ( !dir->Load(path) )
310     {
311     return;
312     }
313   
314   /**
315    * Attempt to load each file in the directory as a shared library
316    */
317   for ( unsigned int i = 0; i < dir->GetNumberOfFiles(); i++ )
318     {
319     const char* file = dir->GetFile(i);
320     /**
321      * try to make sure the file has at least the extension
322      * for a shared library in it.
323      */
324     if ( NameIsSharedLibrary(file) )
325       {
326       std::string fullpath = CreateFullPath(path, file);
327       LibHandle lib = DynamicLoader::OpenLibrary(fullpath.c_str());
328       if ( lib )
329         {
330         /**
331          * Look for the symbol itkLoad in the library
332          */
333         ITK_LOAD_FUNCTION loadfunction
334 IND **********= (ITK_LOAD_FUNCTION)DynamicLoader::GetSymbolAddress(lib, "itkLoad");
335         /**
336          * if the symbol is found call it to create the factory
337          * from the library
338          */
339         if ( loadfunction )
340           {
341           ObjectFactoryBase* newfactory = (*loadfunction)();
342           /**
343            * initialize class members if load worked
344            */
345           newfactory->m_LibraryHandle = (void*)lib;
346           newfactory->m_LibraryPath = fullpath;
347           newfactory->m_LibraryDate = 0; // unused for now...
348           ObjectFactoryBase::RegisterFactory(newfactory);
349           }
350         }
351       }
352     }
353 }
354
355
356 /**
357  * Recheck the ITK_AUTOLOAD_PATH for new libraries
358  */
359 void 
360 ObjectFactoryBase
361 ::ReHash()
362 {
363   ObjectFactoryBase::UnRegisterAllFactories();
364   ObjectFactoryBase::Initialize();
365 }
366
367
368 /**
369  * initialize class members
370  */
371 ObjectFactoryBase::ObjectFactoryBase()
372 {
373   m_LibraryHandle = 0;
374   m_LibraryDate = 0;
375   m_OverrideMap = new OverRideMap;
376 }
377
378
379 /**
380  * Unload the library and free the path string
381  */
382 ObjectFactoryBase
383 ::~ObjectFactoryBase()
384 {
385   if(m_LibraryHandle)
386     {
387     DynamicLoader::CloseLibrary((LibHandle)m_LibraryHandle);
388     }
389   m_OverrideMap->erase(m_OverrideMap->begin(), m_OverrideMap->end());
390   delete m_OverrideMap;
391 }
392
393
394 /**
395  * Add a factory to the registered list
396  */
397 void 
398 ObjectFactoryBase
399 ::RegisterFactory(ObjectFactoryBase* factory)
400 {
401   if ( factory->m_LibraryHandle == 0 )
402     {
403     const char* nonDynamicName = "Non-Dynamicly loaded factory";
404     factory->m_LibraryPath = nonDynamicName;
405     }
406   if ( strcmp(factory->GetITKSourceVersion(), 
407 IND **************Version::GetITKSourceVersion()) != 0 )
408     {
409     itkGenericOutputMacro(<< "Possible incompatible factory load:" 
410 LEN                           << "\nRunning itk version :\n" << Version::GetITKSourceVersion() 
411 LEN                           << "\nLoaded factory version:\n" << factory->GetITKSourceVersion()
412 LEN,IND **************************<< "\nLoading factory:\n" << factory->m_LibraryPath << "\n");
413     }
414
415   ObjectFactoryBase::Initialize();
416   ObjectFactoryBase::m_RegisteredFactories->push_back(factory);
417   factory->Register();
418 }
419
420
421 /**
422  *
423  */
424 void 
425 ObjectFactoryBase
426 ::PrintSelf(std::ostream& os, Indent indent) const
427 {
428   Superclass::PrintSelf(os, indent);
429
430   os << indent << "Factory DLL path: " << m_LibraryPath.c_str() << "\n";
431 LEN   os << indent << "Factory description: " << this->GetDescription() << std::endl;
432
433   int num = static_cast<int>( m_OverrideMap->size() );
434   os << indent << "Factory overides " << num << " classes:" << std::endl;
435
436   indent = indent.GetNextIndent();
437   for(OverRideMap::iterator i = m_OverrideMap->begin();
438 IND ******i != m_OverrideMap->end(); ++i)
439     {
440     os << indent << "Class : " <<  (*i).first.c_str() << "\n";
441 LEN     os << indent << "Overriden with: " <<  (*i).second.m_OverrideWithName.c_str()
442        << std::endl;
443     os << indent << "Enable flag: " << (*i).second.m_EnabledFlag
444        << std::endl;
445     os << std::endl;
446     }
447 }
448
449
450 /**
451  *
452  */
453 void 
454 ObjectFactoryBase
455 ::UnRegisterFactory(ObjectFactoryBase* factory)
456
457   for ( std::list<ObjectFactoryBase*>::iterator i = 
458           m_RegisteredFactories->begin();
459 IND ********i != m_RegisteredFactories->end(); ++i )
460     {
461     if ( factory == *i )
462       {
463       m_RegisteredFactories->remove(factory);
464       factory->UnRegister();
465       return;
466       }
467     }
468 }
469   
470
471 /**
472  * unregister all factories and delete the RegisteredFactories list
473  */
474 void 
475 ObjectFactoryBase
476 ::UnRegisterAllFactories()
477 {
478   
479   if ( ObjectFactoryBase::m_RegisteredFactories )
480     {
481     for ( std::list<ObjectFactoryBase*>::iterator i 
482             = m_RegisteredFactories->begin();
483 IND **********i != m_RegisteredFactories->end(); ++i )
484       {
485       (*i)->UnRegister();
486       }
487     delete ObjectFactoryBase::m_RegisteredFactories;
488     ObjectFactoryBase::m_RegisteredFactories = 0;
489     }
490 }
491
492
493 /**
494  *
495  */
496 void 
497 ObjectFactoryBase
498 ::RegisterOverride(const char* classOverride,
499                    const char* subclass,
500                    const char* description,
501                    bool enableFlag,
502                    CreateObjectFunctionBase*
503                    createFunction)
504 {
505   ObjectFactoryBase::OverrideInformation info;
506   info.m_Description = description;
507   info.m_OverrideWithName = subclass;
508   info.m_EnabledFlag = enableFlag;
509   info.m_CreateObject = createFunction;
510   m_OverrideMap->insert(OverRideMap::value_type(classOverride, info));
511 }
512
513
514 LightObject::Pointer 
515 ObjectFactoryBase
516 ::CreateObject(const char* itkclassname)
517 {
518   m_OverrideMap->find(itkclassname);
519   OverRideMap::iterator pos = m_OverrideMap->find(itkclassname);
520   if ( pos != m_OverrideMap->end() )
521     {
522     return (*pos).second.m_CreateObject->CreateObject();
523     }
524   return 0;
525 }
526
527
528 /**
529  *
530  */
531 void 
532 ObjectFactoryBase
533 ::SetEnableFlag(bool flag,
534                 const char* className,
535                 const char* subclassName)
536 {
537   OverRideMap::iterator start = m_OverrideMap->lower_bound(className);
538   OverRideMap::iterator end = m_OverrideMap->upper_bound(className);
539   for ( OverRideMap::iterator i = start; i != end; ++i )
540     {
541     if ( (*i).second.m_OverrideWithName == subclassName )
542       {
543       (*i).second.m_EnabledFlag = flag;
544       }
545     }
546 }
547
548
549 /**
550  *
551  */
552 bool 
553 ObjectFactoryBase
554 ::GetEnableFlag(const char* className, const char* subclassName)
555 {
556   OverRideMap::iterator start = m_OverrideMap->lower_bound(className);
557   OverRideMap::iterator end = m_OverrideMap->upper_bound(className);
558   for ( OverRideMap::iterator i = start; i != end; ++i )
559     {
560     if ( (*i).second.m_OverrideWithName == subclassName )
561       {
562       return (*i).second.m_EnabledFlag;
563       }
564     }
565   return 0;
566 }
567
568
569 /**
570  *
571  */
572 void 
573 ObjectFactoryBase
574 ::Disable(const char* className)
575 {
576   OverRideMap::iterator start = m_OverrideMap->lower_bound(className);
577   OverRideMap::iterator end = m_OverrideMap->upper_bound(className);
578   for ( OverRideMap::iterator i = start; i != end; ++i )
579     {
580     (*i).second.m_EnabledFlag = 0;
581     }
582 }
583
584
585 /**
586  *
587  */
588 std::list<ObjectFactoryBase*> 
589 ObjectFactoryBase
590 ::GetRegisteredFactories()
591 {
592   return *ObjectFactoryBase::m_RegisteredFactories;
593 }
594
595
596 /**
597  * Return a list of classes that this factory overrides.
598  */
599 std::list<std::string> 
600 ObjectFactoryBase
601 ::GetClassOverrideNames()
602 {
603   std::list<std::string> ret;
604   for ( OverRideMap::iterator i = m_OverrideMap->begin();
605 IND ********i != m_OverrideMap->end(); ++i )
606     {
607     ret.push_back((*i).first);
608     }
609   return ret;
610 }
611
612
613 /**
614  * Return a list of the names of classes that override classes.
615  */
616 std::list<std::string> 
617 ObjectFactoryBase
618 ::GetClassOverrideWithNames()
619 {
620   std::list<std::string> ret;
621   for ( OverRideMap::iterator i = m_OverrideMap->begin();
622 IND ********i != m_OverrideMap->end(); ++i )
623     {
624     ret.push_back((*i).second.m_OverrideWithName);
625     }
626   return ret;
627 }
628
629
630 /**
631  * Retrun a list of descriptions for class overrides
632  */
633 std::list<std::string> 
634 ObjectFactoryBase
635 ::GetClassOverrideDescriptions()
636
637   std::list<std::string> ret;
638   for ( OverRideMap::iterator i = m_OverrideMap->begin();
639 IND ********i != m_OverrideMap->end(); ++i )
640     {
641     ret.push_back((*i).second.m_Description);
642     }
643   return ret;
644 }
645
646
647 /**
648  * Return a list of enable flags
649  */
650 std::list<bool> 
651 ObjectFactoryBase
652 ::GetEnableFlags()
653 {
654   std::list<bool> ret;
655   for( OverRideMap::iterator i = m_OverrideMap->begin();
656 IND *******i != m_OverrideMap->end(); ++i)
657     {
658     ret.push_back((*i).second.m_EnabledFlag);
659     }
660   return ret;
661 }
662
663 /**
664  * Return the path to a dynamically loaded factory. */
665 const char *
666 ObjectFactoryBase
667 ::GetLibraryPath()
668 {
669   return m_LibraryPath.c_str();
670 }
671
672 // end namespace itk
673

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:37PM
© Kitware Inc.