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