CLAM-Development  1.4.0
Factory.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #ifndef _Factory_hxx_
23 #define _Factory_hxx_
24 
25 #include <map>
26 #include <string>
27 #include <list>
28 #include <set>
29 #include <iostream> //TODO only for debugging
30 
31 #include "Assert.hxx"
32 #include "ErrFactory.hxx"
33 #include "RunTimeLibraryLoader.hxx"
34 
35 namespace CLAM {
36 
69 template <typename AbstractProductType>
70 class Factory
71 {
72 public:
73  typedef AbstractProductType AbstractProduct;
74  typedef std::string RegistryKey;
75 
76 private:
77  typedef std::string Attribute;
78  typedef std::string Value;
79  struct Pair
80  {
81  Attribute attribute;
82  Value value;
83  };
84  typedef RegistryKey Key; // TODO remove
85 
86 public:
87  typedef std::list<Key> Keys;
88  typedef std::list<std::string> Values;
89  typedef std::list<Pair> Pairs;
90 
92  class Creator
93  {
94  public:
95  virtual AbstractProductType* Create() = 0;
96  virtual ~Creator(){};
97  };
98 
99  Factory() {};
100  ~Factory() {};
101 /*
102  static Factory& GetInstance() {
103  static Factory theInstance;
104  return theInstance;
105  }
106 */
113  {
114  Creator& creator = _registry.GetCreator( name );
115  return creator.Create();
116  }
117 
118 
119 
125  {
126  return _registry.GetCreatorSafe(name).Create();
127  }
128 
129 
130  void Clear()
131  {
132  _registry.RemoveAllCreators();
133  }
134 
135  void AddCreator(const RegistryKey name, Creator* creator)
136  {
137  _registry.AddCreator(name, creator);
138  }
139 
141  {
142  _registry.AddCreatorWarningRepetitions(name, creator);
143  }
144 
145  void AddCreatorSafe(const RegistryKey name, Creator* creator) throw (ErrFactory)
146  {
147  _registry.AddCreatorSafe(name, creator);
148  }
149 
150  void DeleteCreator(const RegistryKey name)
151  {
152  _registry.DeleteCreator(name);
153  }
154 
155  void GetRegisteredNames( std::list<std::string>& namesList )
156  {
157  _registry.GetRegisteredNames( namesList );
158  }
159 
160  bool KeyExists( const RegistryKey& key)
161  {
162  return _registry.KeyExists(key);
163  }
164 
165  bool AttributeExists (const std::string& key, const std::string& attribute)
166  {
167  return _registry.AttributeExists(key,attribute);
168  }
169 
171  Keys GetKeys(const std::string& attribute, const std::string& value)
172  {
173  return _registry.GetKeys(attribute, value);
174  }
177  {
178  return GetKeys("","");
179  }
181  Pairs GetPairsFromKey(const std::string& key)
182  {
183  return _registry.GetPairsFromKey(key);
184  }
187  Values GetSetOfValues(const std::string& attribute)
188  {
189  return _registry.GetSetOfValues(attribute);
190  }
192  Values GetValuesFromAttribute(const std::string& key, const std::string& attribute)
193  {
194  return _registry.GetValuesFromAttribute(key, attribute);
195  }
198  Value GetValueFromAttribute(const std::string& key, const std::string& attribute)
199  {
200  return GetValuesFromAttribute(key,attribute).front();
201  }
202 
203  void AddAttribute(const std::string& key, const std::string& attribute, const std::string& value)
204  {
205  _registry.AddAttribute(key, attribute, value);
206  }
207 
208 public: // Inner classes. Public for better testing
214  class Registry
215  {
216  private:
217  struct FactoryEntry {
218  Creator * creator;
219  Pairs pairs;
220  };
221  typedef std::map<Key, FactoryEntry> FactoryEntries;
222 
223  public:
225  {
226  CLAM_ASSERT(_factoryEntries.begin() != _factoryEntries.end(),
227  "the Factory Registry shouldn't be empty");
228 
229  Creator* res = CommonGetCreator(creatorId);
230  if (!res)
231  {
232  std::string errmsg("GetCreator invoked with a non existent key: ");
233  errmsg += creatorId + "\nRegistered keys are:\n";
234  errmsg += GetRegisteredNames();
235  CLAM_ASSERT(res,errmsg.c_str());
236  }
237 
238  return *res;
239  }
240 
242  {
243  if ( _factoryEntries.begin() == _factoryEntries.end() )
244  throw ErrFactory("GetCreatorSafe invoked on an empty registry");
245 
246  Creator* res = CommonGetCreator(creatorId);
247  if (!res)
248  {
249  std::string msg("GetCreatorSafe invoked with a non existent key: ");
250  msg += creatorId;
251  msg += "\nRegistered keys are:\n";
252  msg += GetRegisteredNames();
253  throw ErrFactory(msg.c_str());
254  }
255  return *res;
256  }
257 
258  void AddCreator( RegistryKey creatorId, Creator* creator )
259  {
260  bool res = CommonAddCreator(creatorId, creator);
261  if (!res)
262  {
263  std::string errmsg("Adding creator method in the factory: CreatorId '");
264  errmsg += creatorId + "' was already registered.\nRegistered keys are:\n";
265  errmsg += GetRegisteredNames();
266  CLAM_ASSERT(res, errmsg.c_str());
267  }
268  }
269  void AddCreatorWarningRepetitions( RegistryKey creatorId, Creator* creator )
270  {
271  bool res = CommonAddCreator(creatorId, creator);
272  if (!res)
273  {
274  std::string errmsg("WARNING. While adding a creator method in the factory, id '");
275  errmsg += creatorId + "' was already registered.";
276 // errmsg += "\n Registered keys: " + GetRegisteredNames();
277  CLAM_WARNING(false, errmsg.c_str() );
278  }
279  }
280 
281  void AddCreatorSafe( RegistryKey creatorId, Creator* creator ) throw (ErrFactory)
282  {
283  if( !CommonAddCreator( creatorId, creator ) )
284  throw ErrFactory("A repeated key was passed");
285  }
286 
287  void DeleteCreator( RegistryKey creatorId)
288  {
289  if (CommonDeleteCreator(creatorId)==false)
290  std::cout<<"WARNING: attempted to delete an inexistent creator"<<std::endl;
291  }
292 
294  {
295  _factoryEntries.clear();
296  }
297 
298  std::size_t Count() { return _factoryEntries.size(); }
299 
300  void GetRegisteredNames( std::list<RegistryKey>& namesList )
301  {
302  typename FactoryEntries::const_iterator i;
303 
304  for ( i = _factoryEntries.begin(); i != _factoryEntries.end(); i++ )
305  {
306  namesList.push_back( i->first );
307  }
308  }
309  std::string GetRegisteredNames()
310  {
311  std::string result;
312  typedef std::list<RegistryKey> Names;
313  Names names;
314  GetRegisteredNames(names);
315  for(Names::iterator it=names.begin(); it!=names.end(); it++)
316  {
317  result += (*it)+", ";
318  }
319  return result;
320 
321  }
322 
323  bool KeyExists(const RegistryKey& key)
324  {
325  typename FactoryEntries::const_iterator it = _factoryEntries.find(key);
326  if(it == _factoryEntries.end())
327  {
328  return false;
329  }
330  return true;
331  }
332  bool AttributeExists(const std::string& key, const std::string& attribute)
333  {
334  Pairs pairsFromKey = GetPairsFromKey(key);
335  typename Pairs::const_iterator itPairs;
336  for (itPairs=pairsFromKey.begin();itPairs!=pairsFromKey.end();itPairs++)
337  {
338  if (itPairs->attribute==attribute) return true;
339  }
340  return false;
341  }
342 
344  Keys GetKeys(const std::string& attribute, const std::string& value)
345  {
346  Keys result;
347  typename FactoryEntries::const_iterator it;
348  for(it = _factoryEntries.begin(); it != _factoryEntries.end(); it++)
349  {
350  if( (attribute == "") )
351  {
352  result.push_back(it->first);
353  continue;
354  }
355  Pairs attributes = it->second.pairs;
356  typename Pairs::const_iterator itAtt;
357  for(itAtt = attributes.begin(); itAtt != attributes.end(); itAtt++)
358  {
359  if( ((*itAtt).attribute == attribute) && ((*itAtt).value == value) )
360  {
361  result.push_back(it->first);
362  }
363  }
364  }
365  return result;
366  }
369  {
370  return GetKeys("","");
371  }
373  Pairs GetPairsFromKey(const std::string& key)
374  {
375  Pairs attributes;
376  typename FactoryEntries::const_iterator it = _factoryEntries.find(key);
377  if(it!=_factoryEntries.end())
378  {
379  attributes = it->second.pairs;
380  }
381  return attributes;
382  }
385  Values GetSetOfValues(const std::string& attribute)
386  {
387  std::set<Value> AttributeSet;
388  std::set<Value>::const_iterator itSet;
389  Values values;
390  typename FactoryEntries::const_iterator it;
391  for(it = _factoryEntries.begin(); it != _factoryEntries.end(); it++)
392  {
393  Pairs attributes = it->second.pairs;
394  typename Pairs::const_iterator itAtt;
395  for(itAtt = attributes.begin(); itAtt != attributes.end(); itAtt++)
396  {
397  if((*itAtt).attribute == attribute)
398  {
399  itSet = AttributeSet.find((*itAtt).value);
400  if(itSet == AttributeSet.end())
401  {
402  AttributeSet.insert((*itAtt).value);
403  }
404  }
405  }
406  }
407  // keep using the ProcessingFactory::Values
408  for(itSet = AttributeSet.begin(); itSet != AttributeSet.end(); itSet++)
409  {
410  values.push_back(*itSet);
411  }
412  return values;
413  }
415  Values GetValuesFromAttribute(const std::string& key, const std::string& attribute)
416  {
417  Values values;
418  typename FactoryEntries::const_iterator it = _factoryEntries.find(key);
419  if(it != _factoryEntries.end())
420  {
421  typename Pairs::const_iterator itAtt;
422  for(itAtt = it->second.pairs.begin(); itAtt != it->second.pairs.end(); itAtt++)
423  {
424  if((*itAtt).attribute == attribute)
425  {
426  values.push_back((*itAtt).value);
427  }
428  }
429  }
430  return values;
431  }
433  Value GetValueFromAttribute(const std::string& key, const std::string& attribute)
434  {
435  return GetValuesFromAttribute(key,attribute).front();
436  }
437 
438  void AddAttribute(const std::string& key, const std::string& attribute, const std::string& value)
439  {
440  typename FactoryEntries::const_iterator it;
441  it = _factoryEntries.find(key);
442  /*if(!KeyExists(key)) // NOT NEEDED AFETER UNIFYING
443  {
444  std::cout << "[Factory] tryind to add metadata to a non-existing key \"" << key << "\"" << std::endl;
445  // return; //pau: debugging: add metadata anyway. maybe factory registrator is about to be instantiated.
446  }*/
447 
448  Pair pair;
449  pair.attribute = attribute;
450  pair.value = value;
451 
452  _factoryEntries[key].pairs.push_back(pair);
453  /*Pairs pairs;
454  if(it == _factoryEntries.end()) // it's a new key: insert it in the _factoryEntries map
455  {
456  pairs.push_back(pair);
457  _factoryEntries.insert( typename FactoryEntries::value_type( key, pairs ) );
458 
459  }
460  else
461  {
462  _factoryEntries[key].push_back(pair);
463  }*/
464  }
465 
466 
467  private: // data
468  FactoryEntries _factoryEntries;
469 
470  // helper methods:
471  Creator* CommonGetCreator( RegistryKey& creatorId )
472  {
473  typename FactoryEntries::const_iterator i =
474  _factoryEntries.find(creatorId);
475  if ( i==_factoryEntries.end() ) // not found
476  return 0;
477  return i->second.creator;
478  }
479 
480  bool CommonAddCreator( RegistryKey& creatorId, Creator* creator)
481  {
482  FactoryEntry factoryEntry;
483  Pairs pairs;
484  factoryEntry.creator = creator;
485  factoryEntry.pairs = pairs;
486  // returns false if the key was repeated.
487  typedef typename FactoryEntries::value_type ValueType;
488  return _factoryEntries.insert( ValueType( creatorId, factoryEntry ) ).second;
489  }
490 
491  bool CommonDeleteCreator (RegistryKey& creatorId)
492  {
493  typename FactoryEntries::iterator i =
494  _factoryEntries.find(creatorId);
495  if ( i == _factoryEntries.end() ) //not found
496  return false;
497  Creator * creator = i->second.creator;
498  delete creator;
499  _factoryEntries.erase(i);
500  return true;
501  }
502  };
503 
504  int Count() { return _registry.Count(); }
505 
506 private:
507  Registry _registry;
508 };
509 
510 
520 template< typename TheFactoryType, typename ConcreteProductType>
522 {
523  typedef typename TheFactoryType::AbstractProduct AbstractProduct;
524  typedef typename TheFactoryType::RegistryKey RegistryKey;
525 public:
526  FactoryRegistrator( const char* metadata[] )
527  {
528  CLAM_ASSERT(std::string(metadata[0])==std::string("key"), "FactoryRegistrator: first char* metadata should be 'key'"); //TODO fix
529  CLAM_ASSERT(metadata[1], "FactoryRegistrator: value for first attriute ('key') must not be 0");
530  std::string key = metadata[1];
531 
532  TheFactoryType & factory = TheFactoryType::GetInstance();
533  factory.AddCreatorWarningRepetitions( key, new ConcreteCreator() );
534  std::string attribute, value;
535  for(unsigned i = 2; metadata[i]; i++)
536  {
537  attribute = metadata[i];
538  if(!metadata[i+1])
539  {
540  std::cout << "[METADATA] error with attribute \"" << attribute << "\"" << std::endl;
541  CLAM_ASSERT(false, "Bad metadata value");
542  break;
543  }
544  value = metadata[++i];
545  factory.AddAttribute(key, attribute, value);
546  }
547  const std::string & libraryFileName=RunTimeLibraryLoader::FileOfSymbol(this);
548  if (libraryFileName!="")
549  factory.AddAttribute(key,"library",libraryFileName);
550  }
551 
552  FactoryRegistrator( RegistryKey key, TheFactoryType& fact )
553  {
554 // std::cout << "FactoryRegistrator(key,factory) " << key << std::endl;
555  fact.AddCreatorWarningRepetitions( key, new ConcreteCreator() );
556  }
557 
558  FactoryRegistrator( TheFactoryType& fact )
559  {
560  ConcreteProductType dummy;
561  RegistryKey key=dummy.GetClassName();
562 // std::cout << "FactoryRegistrator(factory) " << dummy.GetClassName() << std::endl;
563  fact.AddCreatorWarningRepetitions( key, new ConcreteCreator() );
564  }
565 
566  FactoryRegistrator( RegistryKey key )
567  {
568 // std::cout << "FactoryRegistrator(key) " << key << std::endl;
569  TheFactoryType::GetInstance().AddCreatorWarningRepetitions( key, new ConcreteCreator() );
570  }
571 
572 /*
573  FactoryRegistrator( )
574  {
575  ConcreteProductType dummy;
576  RegistryKey key=dummy.GetClassName();
577 // std::cout << "FactoryRegistrator() " << key << std::endl;
578  TheFactoryType::GetInstance().AddCreatorWarningRepetitions( key, new ConcreteCreator() );
579  }
580 */
582  {
583 // std::cout << "~FactoryRegistrator() " << std::endl;
584  }
585 
586  class ConcreteCreator : public TheFactoryType::Creator
587  {
588  public:
589  AbstractProduct *Create()
590  {
591  return new ConcreteProductType();
592  }
593 
594  };
595 };
596 
597 } // namespace
598 
599 #endif // _Factory_hxx_
600