00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef REAL_FACTORY_H
00021 #define REAL_FACTORY_H
00022
00023 #include "configurationconfig.h"
00024 #include "configurationexceptions.h"
00025 #include "parametersettable.h"
00026 #include "factoryobserver.h"
00027 #include <QString>
00028 #include <QStringList>
00029 #include <QMap>
00030 #include <QList>
00031 #include <QVector>
00032 #include <typeinfo>
00033 #include <memory>
00034
00035 namespace farsa {
00036
00037 class ConfigurationParameters;
00038
00045 class FARSA_CONF_TEMPLATE ParameterSettableCreator
00046 {
00047 public:
00051 virtual ~ParameterSettableCreator()
00052 {
00053 }
00054
00071 virtual ParameterSettable* create(ConfigurationParameters& settings, QString prefix, bool configure) const = 0;
00072
00080 virtual bool canDeferConfiguration() const = 0;
00081 };
00082
00092 template <class T, bool ConfigureInConstructor>
00093 class FARSA_CONF_TEMPLATE ParameterSettableCreatorT : public ParameterSettableCreator
00094 {
00095 public:
00099 virtual ~ParameterSettableCreatorT()
00100 {
00101 }
00102
00115 virtual ParameterSettableInConstructor* create(ConfigurationParameters& settings, QString prefix, bool configure) const;
00116
00123 virtual bool canDeferConfiguration() const
00124 {
00125 return false;
00126 }
00127 };
00128
00138 template <class T>
00139 class FARSA_CONF_TEMPLATE ParameterSettableCreatorT<T, false> : public ParameterSettableCreator
00140 {
00141 public:
00145 virtual ~ParameterSettableCreatorT()
00146 {
00147 }
00148
00161 virtual ParameterSettableWithConfigureFunction* create(ConfigurationParameters& settings, QString prefix, bool configure) const;
00162
00169 virtual bool canDeferConfiguration() const
00170 {
00171 return true;
00172 }
00173 };
00174
00186 class FARSA_CONF_API RealFactory {
00187 public:
00191 RealFactory(ConfigurationParameters& configurationParameters);
00192
00196 ~RealFactory();
00197
00203 void addObserver(FactoryObserver* observer);
00204
00210 void addObservers(const QSet<FactoryObserver*>& observers);
00211
00217 const QSet<FactoryObserver*>& getObservers() const;
00218
00222 void clearObservers();
00223
00251 template <class TypeToCreate>
00252 TypeToCreate* create(const QString& className, QString prefix, bool configure = true, bool* actuallyConfigured = NULL);
00253
00281 template <class TypeToCreate>
00282 TypeToCreate* createFromParameter(QString prefix, bool configure = true, bool* actuallyConfigured = NULL);
00283
00299 template <class TypeToCreate>
00300 QList<TypeToCreate *> createListFromParameter(QString prefix, QString basename);
00301
00317 template <class TypeToCreate>
00318 QVector<TypeToCreate *> createVectorFromParameter(QString prefix, QString basename);
00319
00329 void objectConfigured(ParameterSettable *object);
00330
00339 bool outsideCallsToCreate() const;
00340
00347 void callPostConfigureInitializationForConfiguredObjects();
00348
00349 private:
00353 ConfigurationParameters& m_configurationParameters;
00354
00358 QSet<FactoryObserver*> m_observers;
00359
00363 unsigned int m_createRecursionLevel;
00364
00369 QList<ParameterSettable*> m_objectsConfiguredNotInitialized;
00370
00371 private:
00381 static bool orderByNumberAfterColon(const QString& s1, const QString& s2);
00382
00383 private:
00391 RealFactory(const RealFactory &other);
00392
00400 RealFactory& operator=(const RealFactory &other);
00401 };
00402
00403 }
00404
00405
00406 #include "configurationparameters.h"
00407 #include "factory.h"
00408
00409 namespace farsa {
00410
00411 template <class T, bool ConfigureInConstructor>
00412 ParameterSettableInConstructor* ParameterSettableCreatorT<T, ConfigureInConstructor>::create(ConfigurationParameters& settings, QString prefix, bool ) const
00413 {
00414 QString terminatedPrefix = prefix + ConfigurationParameters::GroupSeparator();
00415
00416
00417
00418 if (!settings.setObjectFromGroupStatusToCreatingAndConfiguring(terminatedPrefix)) {
00419 throw PrefixNotGroupException(prefix.toAscii().data());
00420 }
00421
00422 std::auto_ptr<T> t(new T(settings, terminatedPrefix));
00423
00424
00425
00426 if (!settings.setObjectFromGroupStatusToCreatedAndConfigured(terminatedPrefix, t.get())) {
00427 throw PrefixNotGroupException(prefix.toAscii().data());
00428 }
00429
00430 return t.release();
00431 }
00432
00433 template <class T>
00434 ParameterSettableWithConfigureFunction* ParameterSettableCreatorT<T, false>::create(ConfigurationParameters& settings, QString prefix, bool configure) const
00435 {
00436 QString terminatedPrefix = prefix + ConfigurationParameters::GroupSeparator();
00437
00438
00439
00440 if (!settings.setObjectFromGroupStatusToCreating(terminatedPrefix)) {
00441 throw PrefixNotGroupException(prefix.toAscii().data());
00442 }
00443
00444 std::auto_ptr<T> t(new T());
00445
00446
00447
00448 if (!settings.setObjectFromGroupStatusToCreatedNotConfigured(terminatedPrefix, t.get())) {
00449 throw PrefixNotGroupException(prefix.toAscii().data());
00450 }
00451
00452 if (configure) {
00453
00454
00455 if (!settings.setObjectFromGroupStatusToConfiguring(terminatedPrefix)) {
00456 throw PrefixNotGroupException(prefix.toAscii().data());
00457 }
00458
00459 t->configure(settings, terminatedPrefix);
00460
00461
00462
00463 if (!settings.setObjectFromGroupStatusToCreatedAndConfigured(terminatedPrefix)) {
00464 throw PrefixNotGroupException(prefix.toAscii().data());
00465 }
00466 }
00467
00468 return t.release();
00469 }
00470
00471 template <class TypeToCreate>
00472 TypeToCreate* RealFactory::create(const QString& className, QString prefix, bool configure, bool* actuallyConfigured)
00473 {
00474
00475
00476 class RecursionLevelRAII
00477 {
00478 public:
00479 RecursionLevelRAII(unsigned int& createRecursionLevel, QList<ParameterSettable*>& objectsConfiguredNotInitialized) :
00480 m_createRecursionLevel(createRecursionLevel)
00481 {
00482 if (m_createRecursionLevel == 0) {
00483
00484
00485 objectsConfiguredNotInitialized.clear();
00486 }
00487 m_createRecursionLevel++;
00488 }
00489
00490 ~RecursionLevelRAII() throw()
00491 {
00492 m_createRecursionLevel--;
00493 }
00494
00495 private:
00496 unsigned int& m_createRecursionLevel;
00497
00498
00499
00500 RecursionLevelRAII(const RecursionLevelRAII& other) : m_createRecursionLevel(other.m_createRecursionLevel) {}
00501 RecursionLevelRAII& operator=(const RecursionLevelRAII& other) { return *this; }
00502 };
00503
00504
00505 RecursionLevelRAII recursionLevelRAII(m_createRecursionLevel, m_objectsConfiguredNotInitialized);
00506
00507
00508 if (!Factory::getInstance().m_classMap.contains(className)) {
00509 throw ClassNameNotRegisteredException(className.toAscii().data());
00510 }
00511
00512
00513 if (!Factory::getInstance().m_classMap[className]->canDeferConfiguration()) {
00514 configure = true;
00515 }
00516 if (actuallyConfigured != NULL) {
00517 (*actuallyConfigured) = configure;
00518 }
00519
00520
00521 std::auto_ptr<ParameterSettable> newObj(Factory::getInstance().m_classMap[className]->create(m_configurationParameters, prefix, configure));
00522 TypeToCreate* obj = dynamic_cast<TypeToCreate*>(newObj.get());
00523
00524 if (obj == NULL) {
00525 throw CannotConvertToTypeException(className.toAscii().data(), typeid(TypeToCreate));
00526 }
00527
00528
00529 if (configure) {
00530 m_objectsConfiguredNotInitialized.append(obj);
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540 if (m_configurationParameters.outsideCallsToGetObjectFromGroup() && (m_createRecursionLevel == 1)) {
00541 callPostConfigureInitializationForConfiguredObjects();
00542 }
00543
00544
00545 foreach(FactoryObserver* obs, m_observers) {
00546 obs->onObjectCreation(obj, className, prefix, configure);
00547 }
00548
00549
00550 newObj.release();
00551
00552 return obj;
00553 }
00554
00555 template <class TypeToCreate>
00556 TypeToCreate* RealFactory::createFromParameter(QString prefix, bool configure, bool* actuallyConfigured)
00557 {
00558 QString type = m_configurationParameters.getValue(prefix + ConfigurationParameters::GroupSeparator() + QString("type"), false);
00559
00560 if (!type.isNull()) {
00561 return create<TypeToCreate>(type, prefix, configure, actuallyConfigured);
00562 }
00563
00564 throw CannotFindTypeParameterException(prefix.toAscii().data());
00565
00566 return NULL;
00567 }
00568
00569 template <class TypeToCreate>
00570 QList<TypeToCreate *> RealFactory::createListFromParameter(QString prefix, QString basename)
00571 {
00572
00573 QList<TypeToCreate *> objects;
00574
00575 QStringList objectsGroups = m_configurationParameters.getGroupsWithPrefixList(prefix, basename);
00576
00577
00578 for (QStringList::iterator it = objectsGroups.begin(); it != objectsGroups.end(); it++) {
00579 objects.push_back(createFromParameter<TypeToCreate>(prefix + ConfigurationParameters::GroupSeparator() + *it));
00580 }
00581
00582 return objects;
00583 }
00584
00585 template <class TypeToCreate>
00586 QVector<TypeToCreate *> RealFactory::createVectorFromParameter(QString prefix, QString basename)
00587 {
00588
00589 QVector<TypeToCreate *> objects;
00590
00591 QStringList objectsGroups = m_configurationParameters.getGroupsWithPrefixList(prefix, basename);
00592
00593 qSort(objectsGroups.begin(), objectsGroups.end(), orderByNumberAfterColon);
00594
00595
00596 for (QStringList::iterator it = objectsGroups.begin(); it != objectsGroups.end(); it++) {
00597 objects.push_back(createFromParameter<TypeToCreate>(prefix + ConfigurationParameters::GroupSeparator() + *it));
00598 }
00599
00600 return objects;
00601 }
00602
00603 }
00604
00605 #endif