Factory.hxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2007 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #ifndef _Factory_hxx_
00023 #define _Factory_hxx_
00024 
00025 #include <map>
00026 #include <string>
00027 #include <list>
00028 #include <set>
00029 #include <iostream> //TODO only for debugging
00030 
00031 #include "Assert.hxx"
00032 #include "ErrFactory.hxx"
00033 #include "RunTimeLibraryLoader.hxx"
00034 
00035 namespace CLAM {
00036 
00068 template <typename AbstractProductType>
00069 class Factory
00070 {
00071 public:
00072         typedef AbstractProductType AbstractProduct;
00073         typedef std::string RegistryKey;
00074 
00075 private:        
00076         typedef std::string Attribute;
00077         typedef std::string Value;
00078         struct Pair 
00079         {
00080                 Attribute attribute;
00081                 Value value;
00082         };
00083         typedef RegistryKey Key; // TODO remove
00084 
00085 public:
00086         typedef std::list<Key> Keys;
00087         typedef std::list<std::string> Values;
00088         typedef std::list<Pair> Pairs; 
00089 
00090         typedef AbstractProduct* (*CreatorMethod)(void); //TODO drop after refactoring
00091 
00093         class Creator
00094         {
00095         public:
00096                 virtual AbstractProductType* Create() = 0;
00097                 virtual ~Creator(){};
00098         };
00099 
00100         Factory() {};
00101         ~Factory() {};
00102 /*
00103         static Factory& GetInstance()   {
00104                 static Factory theInstance;
00105                 return theInstance;
00106         }
00107 */
00113         AbstractProduct* Create( const RegistryKey name )
00114         {
00115                 Creator& creator = _registry.GetCreator( name );
00116                 return creator.Create();
00117         }
00118 
00119 
00120 
00125         AbstractProduct* CreateSafe( const RegistryKey name ) throw (ErrFactory)
00126         {
00127                 return  _registry.GetCreatorSafe(name).Create();
00128         }
00129 
00130 
00131         void Clear()
00132         { 
00133                 _registry.RemoveAllCreators();
00134         }
00135 
00136         void AddCreator(const RegistryKey name, Creator* creator)
00137         {
00138                 _registry.AddCreator(name, creator);
00139         }
00140 
00141         void AddCreatorWarningRepetitions(const RegistryKey name, Creator* creator)
00142         {
00143                 _registry.AddCreatorWarningRepetitions(name, creator);
00144         }
00145 
00146         void AddCreatorSafe(const RegistryKey name, Creator* creator) throw (ErrFactory)
00147         {
00148                 _registry.AddCreatorSafe(name, creator);
00149         }
00150 
00151         void DeleteCreator(const RegistryKey name)
00152         {
00153                 _registry.DeleteCreator(name);
00154         }
00155 
00156         void GetRegisteredNames( std::list<std::string>& namesList )
00157         {
00158                 _registry.GetRegisteredNames( namesList );
00159         }
00160 
00161         bool KeyExists( const RegistryKey& key)
00162         {
00163                 return _registry.KeyExists(key);
00164         }
00165 
00166         bool AttributeExists (const std::string& key, const std::string& attribute)
00167         {
00168                 return _registry.AttributeExists(key,attribute);
00169         }
00170 
00172         Keys GetKeys(const std::string& attribute, const std::string& value)
00173         {
00174                 return _registry.GetKeys(attribute, value);
00175         }
00177         Keys GetKeys()
00178         {
00179                 return GetKeys("","");
00180         }
00182         Pairs GetPairsFromKey(const std::string& key)
00183         {
00184                 return _registry.GetPairsFromKey(key);
00185         }
00188         Values GetSetOfValues(const std::string& attribute)
00189         {
00190                 return _registry.GetSetOfValues(attribute);
00191         }
00193         Values GetValuesFromAttribute(const std::string& key, const std::string& attribute)
00194         {
00195                 return _registry.GetValuesFromAttribute(key, attribute);
00196         }
00199         Value GetValueFromAttribute(const std::string& key, const std::string& attribute)
00200         {
00201                 return GetValuesFromAttribute(key,attribute).front();
00202         }
00203 
00204         void AddAttribute(const std::string& key, const std::string& attribute, const std::string& value)
00205         {
00206                 _registry.AddAttribute(key, attribute, value);
00207         }
00208 
00209 public: // Inner classes. Public for better testing
00215         class Registry
00216         {
00217         private:
00218                 struct FactoryEntry {
00219                         Creator * creator;
00220                         Pairs pairs;
00221                 };
00222                 typedef std::map<Key, FactoryEntry> FactoryEntries;
00223 
00224         public:
00225                 Creator& GetCreator( RegistryKey creatorId) 
00226                 {
00227                         CLAM_ASSERT(_factoryEntries.begin() != _factoryEntries.end(),
00228                                 "the Factory Registry shouldn't be empty");
00229 
00230                         Creator* res = CommonGetCreator(creatorId);
00231                         if (!res)
00232                         {
00233                                 std::string errmsg("GetCreator invoked with a non existent key: ");
00234                                 errmsg += creatorId + "\nRegistered keys are:\n";
00235                                 errmsg += GetRegisteredNames();
00236                                 CLAM_ASSERT(res,errmsg.c_str());
00237                         }
00238 
00239                         return *res;
00240                 }
00241 
00242                 Creator& GetCreatorSafe( RegistryKey creatorId) throw (ErrFactory) 
00243                 {
00244                         if ( _factoryEntries.begin() == _factoryEntries.end() )
00245                                 throw ErrFactory("GetCreatorSafe invoked on an empty registry");
00246 
00247                         Creator* res = CommonGetCreator(creatorId);
00248                         if (!res)
00249                         {
00250                                 std::string msg("GetCreatorSafe invoked with a non existent key: ");
00251                                 msg += creatorId;
00252                                 msg += "\nRegistered keys are:\n";
00253                                 msg += GetRegisteredNames();
00254                                 throw ErrFactory(msg.c_str());
00255                         }
00256                         return *res;
00257                 }
00258 
00259                 void AddCreator( RegistryKey creatorId, Creator* creator ) 
00260                 {
00261                         bool res = CommonAddCreator(creatorId, creator);
00262                         if (!res)
00263                         {
00264                                 std::string errmsg("Adding creator method in the factory: CreatorId '");
00265                                 errmsg += creatorId + "' was already registered.\nRegistered keys are:\n";
00266                                 errmsg += GetRegisteredNames();
00267                                 CLAM_ASSERT(res, errmsg.c_str());
00268                         }
00269                 }
00270                 void AddCreatorWarningRepetitions( RegistryKey creatorId, Creator* creator ) 
00271                 {
00272                         bool res = CommonAddCreator(creatorId, creator);
00273                         if (!res)
00274                         {
00275                                 std::string errmsg("WARNING. While adding a creator method in the factory, id '");
00276                                 errmsg += creatorId + "' was already registered.";
00277 //                              errmsg += "\n Registered keys: " + GetRegisteredNames();
00278                                 CLAM_WARNING(false, errmsg.c_str() );
00279                         }
00280                 }
00281 
00282                 void AddCreatorSafe( RegistryKey creatorId, Creator* creator ) throw (ErrFactory) 
00283                 {
00284                         if( !CommonAddCreator( creatorId, creator ) ) 
00285                                 throw ErrFactory("A repeated key was passed");
00286                 }
00287 
00288                 void DeleteCreator( RegistryKey creatorId)
00289                 {
00290                         if (CommonDeleteCreator(creatorId)==false)
00291                                 std::cout<<"WARNING: attempted to delete an inexistent creator"<<std::endl;
00292                 }
00293 
00294                 void RemoveAllCreators() 
00295                 {
00296                         _factoryEntries.clear();
00297                 }
00298 
00299                 std::size_t Count() { return _factoryEntries.size(); }
00300 
00301                 void GetRegisteredNames( std::list<RegistryKey>& namesList )
00302                 {
00303                         typename FactoryEntries::const_iterator i;
00304 
00305                         for ( i = _factoryEntries.begin(); i != _factoryEntries.end(); i++ )
00306                         {
00307                                 namesList.push_back( i->first );
00308                         }
00309                 }
00310                 std::string GetRegisteredNames()
00311                 {
00312                         std::string result;
00313                         typedef std::list<RegistryKey> Names;
00314                         Names names;
00315                         GetRegisteredNames(names);
00316                         for(Names::iterator it=names.begin(); it!=names.end(); it++)
00317                         {
00318                                 result += (*it)+", ";
00319                         }
00320                         return result;
00321                         
00322                 }
00323 
00324                 bool KeyExists(const RegistryKey& key)
00325                 {
00326                         typename FactoryEntries::const_iterator it = _factoryEntries.find(key);
00327                         if(it == _factoryEntries.end())
00328                         {
00329                                 return false;
00330                         }
00331                         return true;
00332                 }
00333                 bool AttributeExists(const std::string& key, const std::string& attribute)
00334                 {
00335                         Pairs pairsFromKey = GetPairsFromKey(key);
00336                         typename Pairs::const_iterator itPairs;
00337                         for (itPairs=pairsFromKey.begin();itPairs!=pairsFromKey.end();itPairs++)
00338                         {
00339                                 if (itPairs->attribute==attribute) return true;
00340                         }
00341                         return false;
00342                 }
00343 
00345                 Keys GetKeys(const std::string& attribute, const std::string& value)
00346                 {
00347                         Keys result;
00348                         typename FactoryEntries::const_iterator it;
00349                         for(it = _factoryEntries.begin(); it != _factoryEntries.end(); it++)
00350                         {
00351                                 if( (attribute == "") )
00352                                 {
00353                                         result.push_back(it->first);
00354                                         continue;
00355                                 }
00356                                 Pairs attributes = it->second.pairs;
00357                                 typename Pairs::const_iterator itAtt;
00358                                 for(itAtt = attributes.begin(); itAtt != attributes.end(); itAtt++)
00359                                 {
00360                                         if( ((*itAtt).attribute == attribute) && ((*itAtt).value == value) )
00361                                         {
00362                                                 result.push_back(it->first);
00363                                         }
00364                                 }
00365                         }
00366                         return result;
00367                 }
00369                 Keys GetKeys()
00370                 {
00371                         return GetKeys("","");
00372                 }
00374                 Pairs GetPairsFromKey(const std::string& key)
00375                 {
00376                         Pairs attributes;
00377                         typename FactoryEntries::const_iterator it = _factoryEntries.find(key);
00378                         if(it!=_factoryEntries.end())
00379                         {
00380                                 attributes = it->second.pairs;
00381                         }
00382                         return attributes;
00383                 }
00386                 Values GetSetOfValues(const std::string& attribute)
00387                 {
00388                         std::set<Value> AttributeSet;
00389                         std::set<Value>::const_iterator itSet;
00390                         Values values;
00391                         typename FactoryEntries::const_iterator it;
00392                         for(it = _factoryEntries.begin(); it != _factoryEntries.end(); it++)
00393                         {
00394                                 Pairs attributes = it->second.pairs;
00395                                 typename Pairs::const_iterator itAtt;
00396                                 for(itAtt = attributes.begin(); itAtt != attributes.end(); itAtt++)
00397                                 {
00398                                         if((*itAtt).attribute == attribute)
00399                                         {
00400                                                 itSet = AttributeSet.find((*itAtt).value);
00401                                                 if(itSet == AttributeSet.end())
00402                                                 {
00403                                                         AttributeSet.insert((*itAtt).value);
00404                                                 }
00405                                         }
00406                                 }
00407                         }
00408                         // keep using the ProcessingFactory::Values
00409                         for(itSet = AttributeSet.begin(); itSet != AttributeSet.end(); itSet++)
00410                         {
00411                                 values.push_back(*itSet);
00412                         }
00413                         return values;
00414                 }
00416                 Values GetValuesFromAttribute(const std::string& key, const std::string& attribute)
00417                 {
00418                         Values values;
00419                         typename FactoryEntries::const_iterator it = _factoryEntries.find(key);
00420                         if(it != _factoryEntries.end())
00421                         {
00422                                 typename Pairs::const_iterator itAtt;
00423                                 for(itAtt = it->second.pairs.begin(); itAtt != it->second.pairs.end(); itAtt++)
00424                                 {
00425                                         if((*itAtt).attribute == attribute)
00426                                         {
00427                                                 values.push_back((*itAtt).value);
00428                                         }
00429                                 }
00430                         }
00431                         return values;
00432                 }
00434                 Value GetValueFromAttribute(const std::string& key, const std::string& attribute)
00435                 {
00436                         return GetValuesFromAttribute(key,attribute).front();
00437                 }
00438 
00439                 void AddAttribute(const std::string& key, const std::string& attribute, const std::string& value)
00440                 {
00441                         typename FactoryEntries::const_iterator it;
00442                         it = _factoryEntries.find(key);
00443                         /*if(!KeyExists(key)) // NOT NEEDED AFETER UNIFYING
00444                         {
00445                                 std::cout << "[Factory] tryind to add metadata to a non-existing key \"" << key << "\"" << std::endl; 
00446                 //              return;  //pau: debugging: add metadata anyway. maybe factory registrator is about to be instantiated.
00447                         }*/
00448                         
00449                         Pair pair;
00450                         pair.attribute = attribute;
00451                         pair.value = value;
00452 
00453                         _factoryEntries[key].pairs.push_back(pair);
00454                         /*Pairs pairs;
00455                         if(it == _factoryEntries.end()) // it's a new key: insert it in the _factoryEntries map
00456                         {
00457                                 pairs.push_back(pair);
00458                                 _factoryEntries.insert( typename FactoryEntries::value_type( key, pairs ) );
00459 
00460                         } 
00461                         else
00462                         {
00463                                 _factoryEntries[key].push_back(pair);
00464                         }*/
00465                 }
00466 
00467 
00468         private: // data
00469                 FactoryEntries _factoryEntries;
00470 
00471                 // helper methods:
00472                 Creator* CommonGetCreator( RegistryKey& creatorId ) 
00473                 {
00474                         typename FactoryEntries::const_iterator i = 
00475                                 _factoryEntries.find(creatorId);
00476                         if ( i==_factoryEntries.end() ) // not found
00477                                 return 0;
00478                         return i->second.creator;
00479                 }
00480 
00481                 bool CommonAddCreator( RegistryKey& creatorId, Creator* creator) 
00482                 {
00483                         FactoryEntry factoryEntry;
00484                         Pairs pairs;
00485                         factoryEntry.creator = creator;
00486                         factoryEntry.pairs = pairs;
00487                         // returns false if the key was repeated.
00488                         typedef typename FactoryEntries::value_type ValueType;
00489                         return  _factoryEntries.insert( ValueType( creatorId, factoryEntry ) ).second;
00490                 }
00491 
00492                 bool CommonDeleteCreator (RegistryKey& creatorId)
00493                 {
00494                         typename FactoryEntries::iterator i =
00495                                 _factoryEntries.find(creatorId);
00496                         if ( i == _factoryEntries.end() ) //not found
00497                                 return false;
00498                         Creator * creator = i->second.creator; 
00499                         delete creator;
00500                         _factoryEntries.erase(i);
00501                         return true;
00502                 }
00503         };
00504 
00505         int Count() { return _registry.Count(); }
00506 
00507 private:
00508         Registry _registry;
00509 };
00510 
00511 
00521 template< typename TheFactoryType, typename ConcreteProductType>
00522 class FactoryRegistrator
00523 {
00524         typedef typename TheFactoryType::AbstractProduct AbstractProduct;
00525         typedef typename TheFactoryType::RegistryKey RegistryKey;
00526 public:
00527         FactoryRegistrator( const char* metadata[] ) 
00528         {
00529                 CLAM_ASSERT(std::string(metadata[0])==std::string("key"), "FactoryRegistrator: first char* metadata should be 'key'"); //TODO fix
00530                 CLAM_ASSERT(metadata[1], "FactoryRegistrator: value for first attriute ('key') must not be 0");
00531                 std::string key = metadata[1];
00532 
00533                 TheFactoryType & factory = TheFactoryType::GetInstance();
00534                 factory.AddCreatorWarningRepetitions( key, new ConcreteCreator() );
00535                 std::string attribute, value;
00536                 for(unsigned i = 2; metadata[i]; i++)
00537                 {
00538                         if(!metadata[i+1])
00539                         {
00540                                 std::cout << "[METADATA] error with attribute \"" << metadata[i] << "\"" << std::endl;
00541                         }
00542                         attribute = metadata[i];
00543                         value = metadata[++i];
00544                         factory.AddAttribute(key, attribute, value);
00545                 }
00546                 const std::string & libraryFileName=RunTimeLibraryLoader::FileOfSymbol(this);
00547                 if (libraryFileName!="")
00548                         factory.AddAttribute(key,"library",libraryFileName);
00549         }
00550 
00551         FactoryRegistrator( RegistryKey key, TheFactoryType& fact ) 
00552         {
00553 //              std::cout << "FactoryRegistrator(key,factory) " << key << std::endl;
00554                 fact.AddCreatorWarningRepetitions( key, new ConcreteCreator() );
00555         }
00556 
00557         FactoryRegistrator( TheFactoryType& fact ) 
00558         {
00559                 ConcreteProductType dummy;
00560                 RegistryKey key=dummy.GetClassName();
00561 //              std::cout << "FactoryRegistrator(factory) " << dummy.GetClassName() << std::endl;
00562                 fact.AddCreatorWarningRepetitions( key, new ConcreteCreator() );
00563         }
00564 
00565         FactoryRegistrator( RegistryKey key ) 
00566         {
00567 //              std::cout << "FactoryRegistrator(key) " << key << std::endl;
00568                 TheFactoryType::GetInstance().AddCreatorWarningRepetitions( key, new ConcreteCreator() );
00569         }
00570 
00571 /*
00572         FactoryRegistrator( ) 
00573         {
00574                 ConcreteProductType dummy;
00575                 RegistryKey key=dummy.GetClassName();
00576 //              std::cout << "FactoryRegistrator() " << key << std::endl;
00577                 TheFactoryType::GetInstance().AddCreatorWarningRepetitions( key, new ConcreteCreator() );
00578         }
00579 */
00580         ~FactoryRegistrator() 
00581         {
00582 //              std::cout << "~FactoryRegistrator() " << std::endl;
00583         }
00584         
00585         class ConcreteCreator : public TheFactoryType::Creator
00586         {
00587         public:
00588                 AbstractProduct *Create()
00589                 {       
00590                         return new ConcreteProductType();
00591                 }
00592 
00593         };
00594 };
00595 
00596 } // namespace
00597 
00598 #endif // _Factory_hxx_
00599 

Generated on Tue Aug 12 22:33:42 2008 for CLAM by  doxygen 1.5.5