00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef CONFIGURATION_PARAMETERS_H
00022 #define CONFIGURATION_PARAMETERS_H
00023
00024 #include "configurationconfig.h"
00025 #include <QMap>
00026 #include <QString>
00027 #include <QRegExp>
00028 #include <QStringList>
00029 #include <QList>
00030 #include <memory>
00031 #include "parametersfileloadersaver.h"
00032 #include "resourcesuser.h"
00033
00034 namespace farsa {
00035
00036 class RealFactory;
00037 class ParameterSettable;
00038 class ParameterSettableWithConfigureFunction;
00039 class ConfigurationNode;
00040 class FactoryObserver;
00041
00259 class FARSA_CONF_API ConfigurationParameters
00260 {
00261 public:
00268 static QString GroupSeparator() { return QString("/"); };
00269
00276 static QString ParentGroup() { return QString(".."); };
00277
00292 static bool registerFileFormat(QString format, ParametersFileLoaderSaver *fileLoaderSaver, QString defaultExtension);
00293
00294 private:
00302 struct FileFormat
00303 {
00307 FileFormat(const QString &f, ParametersFileLoaderSaver *l, const QString &e) :
00308 formatName(f),
00309 fileLoaderSaver(l),
00310 extension(e),
00311 m_destructionResponsability(true)
00312 {
00313 }
00314
00318 FileFormat(const FileFormat& other) :
00319 formatName(other.formatName),
00320 fileLoaderSaver(other.fileLoaderSaver),
00321 extension(other.extension),
00322 m_destructionResponsability(other.m_destructionResponsability)
00323 {
00324
00325
00326 other.m_destructionResponsability = false;
00327 }
00328
00332 FileFormat& operator=(const FileFormat &other)
00333 {
00334
00335 if (&other == this) {
00336 return *this;
00337 }
00338
00339 formatName = other.formatName;
00340 fileLoaderSaver = other.fileLoaderSaver;
00341 extension = other.extension;
00342 m_destructionResponsability = other.m_destructionResponsability;
00343
00344
00345
00346 other.m_destructionResponsability = false;
00347
00348 return *this;
00349 }
00350
00354 ~FileFormat()
00355 {
00356
00357 if (m_destructionResponsability) {
00358 delete fileLoaderSaver;
00359 }
00360 }
00361
00365 QString formatName;
00366
00370 ParametersFileLoaderSaver *fileLoaderSaver;
00371
00375 QString extension;
00376
00377 private:
00384 mutable bool m_destructionResponsability;
00385 };
00386
00397 static QMap<QString, FileFormat>& getFormatsMap();
00398
00409 static QMap<QString, QString>& getFileExtensionsMap();
00410
00411 public:
00419 ConfigurationParameters(bool caseSensitive = false);
00420
00429 ConfigurationParameters(const ConfigurationParameters &other);
00430
00442 ConfigurationParameters& operator=(const ConfigurationParameters &other);
00443
00447 ~ConfigurationParameters();
00448
00454 bool isCaseSensitive() const;
00455
00459 void clearAll();
00460
00468 QStringList getGroupsList(QString group) const;
00469
00480 QStringList getGroupsWithPrefixList(QString group, QString prefix) const;
00481
00492 QStringList getFilteredGroupsList(QString group, QRegExp filter) const;
00493
00500 void createGroup(QString groupPath);
00501
00534 bool deleteGroup(QString groupPath);
00535
00573 bool renameGroup(QString oldGroupPath, QString newGroupName);
00574
00584 QString createSubGroup(QString parentPath, QString groupName) {
00585 QString fullpath = parentPath + GroupSeparator() + groupName;
00586 createGroup( fullpath );
00587 return fullpath;
00588 };
00589
00598 void createParameter(QString groupPath, QString parameter);
00599
00610 void createParameter(QString groupPath, QString parameter, QString value)
00611 {
00612 createParameter(groupPath, parameter);
00613 setValue(groupPath + GroupSeparator() + parameter, value);
00614 }
00615
00626 void createParameter(QString groupPath, QString parameter, ParameterSettable* object)
00627 {
00628 createParameter(groupPath, parameter);
00629 setValue(groupPath + GroupSeparator() + parameter, object);
00630 }
00631
00639 void deleteParameter(QString groupPath, QString parameter);
00640
00684 bool startObjectParameters(QString groupPath, QString typeName, ParameterSettable* object);
00685
00713 QString getValue(QString path, bool alsoMatchParents = false) const;
00714
00723 bool setValue(QString path, QString value);
00724
00733 bool setValue(QString path, ParameterSettable* object);
00734
00741 QStringList getParametersList(QString group) const;
00742
00753 QStringList getParametersWithPrefixList(QString group, QString prefix) const;
00754
00765 QStringList getFilteredParametersList(QString group, QRegExp filter) const;
00766
00784 void startRememberingGroupObjectAssociations();
00785
00791 void stopRememberingGroupObjectAssociations();
00792
00800 void resetGroupObjectAssociations();
00801
00833 template <class TypeToCreate>
00834 TypeToCreate* getObjectFromGroup(QString group, bool configure = true, bool forceObjectCreation = false);
00835
00874 template <class TypeToCreate>
00875 TypeToCreate* getObjectFromParameter(QString param, bool alsoMatchParents = false, bool configure = true, bool forceObjectCreation = false)
00876 {
00877
00878 QString value = getValue(param, alsoMatchParents);
00879
00880
00881 if (value.isEmpty()) {
00882 return NULL;
00883 }
00884 return getObjectFromGroup<TypeToCreate>(value, configure, forceObjectCreation);
00885 }
00886
00896 void updateObjectReferences();
00897
00910 bool loadParameters(QString filename, bool keepOld = false, QString format = "");
00911
00928 bool saveParameters(QString filename, QString format = "", bool append = false);
00929
00939 SimpleResourcesUser* getResourcesUserForResource(QString resourceName);
00940
00947 void setResourcesUser(ResourcesUser* resourcesUser);
00948
00955 void addObserver(FactoryObserver* observer);
00956
00957 private:
00965 QString formatFromFilenameExtension(QString filename) const;
00966
00972 void copyTree(const ConfigurationNode *root);
00973
00981 void copyNode(const ConfigurationNode *source, ConfigurationNode *target);
00982
00990 bool setObjectFromGroupStatusToCreating(QString group);
00991
01004 bool setObjectFromGroupStatusToCreatedNotConfigured(QString group, ParameterSettable *object);
01005
01015 bool setObjectFromGroupStatusToConfiguring(QString group);
01016
01027 bool setObjectFromGroupStatusToCreatingAndConfiguring(QString group);
01028
01042 bool setObjectFromGroupStatusToCreatedAndConfigured(QString group, ParameterSettable *object = NULL);
01043
01051 bool outsideCallsToGetObjectFromGroup() const
01052 {
01053 return (m_getObjectFromGroupRecursionLevel == 0);
01054 }
01055
01061 const std::auto_ptr<RealFactory> m_factory;
01062
01066 std::auto_ptr<ConfigurationNode> m_root;
01067
01074 unsigned int m_getObjectFromGroupRecursionLevel;
01075
01084 struct ObjectAndRecursionLevel
01085 {
01089 ParameterSettableWithConfigureFunction* object;
01090
01094 unsigned int recursionLevel;
01095
01100 QString groupName;
01101 };
01102
01107 QList<ObjectAndRecursionLevel> m_objectsToConfigure;
01108
01114 bool m_dontForgetGroupObjectAssociations;
01115
01123 QList<SimpleResourcesUser> m_resourcesUserPerRecursionLevel;
01124
01129 template<class T, bool ConfigureInConstructor>
01130 friend class ParameterSettableCreatorT;
01131
01140 friend class RealFactory;
01141 };
01142
01143 }
01144
01145
01146 #include "configurationnode.h"
01147 #include "parametersettable.h"
01148 #include "realfactory.h"
01149 #include <memory>
01150
01151 namespace farsa {
01152
01153 template <class TypeToCreate>
01154 TypeToCreate* ConfigurationParameters::getObjectFromGroup(QString group, bool configure, bool forceObjectCreation)
01155 {
01156
01157
01158
01159
01160 class RecursionLevelRAII
01161 {
01162 public:
01163 RecursionLevelRAII(unsigned int *var, QList<ConfigurationParameters::ObjectAndRecursionLevel> *list, QList<SimpleResourcesUser> *resourcesUsers, ConfigurationParameters ¶ms, RealFactory& factory) :
01164 m_var(var),
01165 m_list(list),
01166 m_resourcesUsers(resourcesUsers),
01167 m_params(params),
01168 m_factory(factory)
01169 {
01170 (*m_var)++;
01171 m_resourcesUsers->append(SimpleResourcesUser());
01172 }
01173
01174
01175 ~RecursionLevelRAII() throw()
01176 {
01177 release(false);
01178 }
01179
01180 void release(bool doConfigure = true)
01181 {
01182 if (m_list != NULL) {
01183 while ((!m_list->isEmpty()) && (m_list->back().recursionLevel > (*m_var))) {
01184 if (doConfigure) {
01185
01186 m_list->back().object->configure(m_params, m_list->back().groupName + GroupSeparator());
01187
01188 m_factory.objectConfigured(m_list->back().object);
01189 }
01190 m_list->pop_back();
01191 }
01192 m_list = NULL;
01193 }
01194 if (m_var != NULL) {
01195 (*m_var)--;
01196 m_var = NULL;
01197 m_resourcesUsers->removeLast();
01198 }
01199 }
01200
01201 private:
01202 unsigned int *m_var;
01203 QList<ObjectAndRecursionLevel> *m_list;
01204 QList<SimpleResourcesUser> *m_resourcesUsers;
01205 ConfigurationParameters& m_params;
01206 RealFactory& m_factory;
01207
01208
01209
01210
01211 RecursionLevelRAII(const RecursionLevelRAII& other) : m_params(*((ConfigurationParameters *) NULL)), m_factory(*((RealFactory *) NULL)) {}
01212 RecursionLevelRAII& operator=(const RecursionLevelRAII& other) { return *this; }
01213 };
01214
01215
01216 ConfigurationNode *node = m_root->getNode(group);
01217
01218
01219 if (node == NULL) {
01220 return NULL;
01221 }
01222
01223
01224 if ((!m_dontForgetGroupObjectAssociations) && (m_getObjectFromGroupRecursionLevel == 0)) {
01225 resetGroupObjectAssociations();
01226 }
01227
01228
01229
01230
01231 if (m_getObjectFromGroupRecursionLevel == 0) {
01232 configure = true;
01233 }
01234
01235
01236 RecursionLevelRAII recursionLevelRAII(&m_getObjectFromGroupRecursionLevel, &m_objectsToConfigure, &m_resourcesUserPerRecursionLevel, *this, *m_factory);
01237
01238
01239 TypeToCreate* retObj = NULL;
01240
01241 std::auto_ptr<TypeToCreate> retObjRAII(NULL);
01242
01243
01244 ConfigurationNode::ObjectAndStatus object = node->getObjectForNode("");
01245
01246
01247
01248 bool actuallyConfigured = true;
01249 switch (object.objectStatus) {
01250 case ObjectNotCreated:
01251
01252 retObj = m_factory->createFromParameter<TypeToCreate>(group, configure, &actuallyConfigured);
01253 retObjRAII.reset(retObj);
01254 break;
01255 case CreatingObject:
01256
01257
01258 if (forceObjectCreation) {
01259 throw OtherObjectBeingCreatedException(group.toAscii().data());
01260 } else {
01261 throw CyclicDependencyException(group.toAscii().data());
01262 }
01263 break;
01264 case ObjectCreatedNotConfigured:
01265
01266
01267 if (forceObjectCreation) {
01268 throw OtherObjectBeingCreatedException(group.toAscii().data());
01269 }
01270
01271 retObj = dynamic_cast<TypeToCreate *>(object.object);
01272 if (retObj == NULL) {
01273 throw CannotConvertToTypeException(typeid(object.object).name(), typeid(TypeToCreate));
01274 }
01275 if (configure) {
01276
01277
01278
01279
01280
01281
01282 node->setObjectForNode("", retObj, ConfiguringObject);
01283 ParameterSettableWithConfigureFunction *const o = dynamic_cast<ParameterSettableWithConfigureFunction *>(retObj);
01284 o->configure(*this, group);
01285
01286 m_factory->objectConfigured(o);
01287 node->setObjectForNode("", retObj, ObjectCreatedAndConfigured);
01288 }
01289 break;
01290 case ConfiguringObject:
01291
01292
01293 if (forceObjectCreation) {
01294 throw OtherObjectBeingCreatedException(group.toAscii().data());
01295 }
01296 if (configure) {
01297
01298 throw CyclicDependencyException(group.toAscii().data());
01299 } else {
01300
01301 retObj = dynamic_cast<TypeToCreate *>(object.object);
01302 if (retObj == NULL) {
01303 throw CannotConvertToTypeException(typeid(object.object).name(), typeid(TypeToCreate));
01304 }
01305 }
01306 break;
01307 case CreatingAndConfiguringObject:
01308
01309
01310 if (forceObjectCreation) {
01311 throw OtherObjectBeingCreatedException(group.toAscii().data());
01312 } else {
01313 throw CyclicDependencyException(group.toAscii().data());
01314 }
01315 break;
01316 case ObjectCreatedAndConfigured:
01317
01318 if (forceObjectCreation) {
01319
01320 retObj = m_factory->createFromParameter<TypeToCreate>(group, configure, &actuallyConfigured);
01321 retObjRAII.reset(retObj);
01322 } else {
01323
01324 retObj = dynamic_cast<TypeToCreate *>(object.object);
01325 if (retObj == NULL) {
01326 throw CannotConvertToTypeException(typeid(object.object).name(), typeid(TypeToCreate));
01327 }
01328 }
01329 break;
01330 }
01331
01332
01333 if (!actuallyConfigured) {
01334 ObjectAndRecursionLevel o;
01335 o.object = dynamic_cast<ParameterSettableWithConfigureFunction *>(retObj);
01336 o.recursionLevel = m_getObjectFromGroupRecursionLevel;
01337 o.groupName = group;
01338 m_objectsToConfigure.push_back(o);
01339 }
01340
01341
01342
01343 recursionLevelRAII.release();
01344
01345
01346
01347
01348
01349
01350 if (m_factory->outsideCallsToCreate() && (m_getObjectFromGroupRecursionLevel == 0)) {
01351 m_factory->callPostConfigureInitializationForConfiguredObjects();
01352
01353
01354 if (m_objectsToConfigure.size() != 0) {
01355 qFatal( "INTERNAL ERROR: The list of objects yet to be configured is not empty at the exit of the most external call to ConfigurationParameters::getObjectFromGroup(). The number of objects still in the list is %d", m_objectsToConfigure.size());
01356 }
01357 }
01358
01359 retObjRAII.release();
01360 return retObj;
01361 }
01362
01363 }
01364
01365 #endif