From 0918097e4f9023a2d60866cbd272bc66a745d195 Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 3 Jul 2014 12:43:17 +0400 Subject: [PATCH] Initial validators mechanism --- src/Model/CMakeLists.txt | 2 + src/Model/Model_PluginManager.cpp | 9 ++- src/Model/Model_PluginManager.h | 3 + src/Model/Model_Validator.cpp | 94 +++++++++++++++++++++++++ src/Model/Model_Validator.h | 59 ++++++++++++++++ src/ModelAPI/CMakeLists.txt | 1 + src/ModelAPI/ModelAPI.i | 2 + src/ModelAPI/ModelAPI_PluginManager.cpp | 3 +- src/ModelAPI/ModelAPI_PluginManager.h | 7 +- src/ModelAPI/ModelAPI_Validator.h | 77 ++++++++++++++++++++ 10 files changed, 253 insertions(+), 4 deletions(-) create mode 100644 src/Model/Model_Validator.cpp create mode 100644 src/Model/Model_Validator.h create mode 100644 src/ModelAPI/ModelAPI_Validator.h diff --git a/src/Model/CMakeLists.txt b/src/Model/CMakeLists.txt index d6ce96bdf..9dea7108a 100644 --- a/src/Model/CMakeLists.txt +++ b/src/Model/CMakeLists.txt @@ -15,6 +15,7 @@ SET(PROJECT_HEADERS Model_AttributeBoolean.h Model_Events.h Model_Update.h + Model_Validator.h ) SET(PROJECT_SOURCES @@ -31,6 +32,7 @@ SET(PROJECT_SOURCES Model_AttributeBoolean.cpp Model_Events.cpp Model_Update.cpp + Model_Validator.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/Model/Model_PluginManager.cpp b/src/Model/Model_PluginManager.cpp index c95ab1242..00ffa6678 100644 --- a/src/Model/Model_PluginManager.cpp +++ b/src/Model/Model_PluginManager.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -99,7 +100,7 @@ Model_PluginManager::Model_PluginManager() { myPluginsInfoLoaded = false; myCheckTransactions = true; - ModelAPI_PluginManager::SetPluginManager(boost::shared_ptr(this)); + ModelAPI_PluginManager::setPluginManager(boost::shared_ptr(this)); // register the configuration reading listener Events_Loop* aLoop = Events_Loop::loop(); static Events_ID FeatureEvent = Events_Loop::eventByName("FeatureRegisterEvent"); @@ -143,3 +144,9 @@ void Model_PluginManager::registerPlugin(ModelAPI_Plugin* thePlugin) { myPluginObjs[myCurrentPluginName] = thePlugin; } + +ModelAPI_ValidatorsFactory* Model_PluginManager::validators() +{ + static Model_ValidatorsFactory* aFactory = new Model_ValidatorsFactory; + return aFactory; +} diff --git a/src/Model/Model_PluginManager.h b/src/Model/Model_PluginManager.h index bed54c08b..1819c56d5 100644 --- a/src/Model/Model_PluginManager.h +++ b/src/Model/Model_PluginManager.h @@ -54,6 +54,9 @@ public: MODEL_EXPORT virtual boost::shared_ptr copy( boost::shared_ptr theSource, std::string theID); + /// Returns the validators factory: the only one instance per application + MODEL_EXPORT virtual ModelAPI_ValidatorsFactory* validators(); + void setCheckTransactions(const bool theCheck) {myCheckTransactions = theCheck;} /// Is called only once, on startup of the application diff --git a/src/Model/Model_Validator.cpp b/src/Model/Model_Validator.cpp new file mode 100644 index 000000000..fe7110924 --- /dev/null +++ b/src/Model/Model_Validator.cpp @@ -0,0 +1,94 @@ +// File: Model_Validator.cpp +// Created: 2 Jul 2014 +// Author: Mikhail PONIKAROV + +#include +#include +#include + +using namespace std; + +void Model_ValidatorsFactory::registerValidator( + const string& theID, ModelAPI_Validator* theValidator) +{ + if (myIDs.find(theID) != myIDs.end()) { + Events_Error::send(string("Validator ") + theID + " is already registered"); + } else { + myIDs[theID] = theValidator; + } +} + +void Model_ValidatorsFactory::assignValidator(const string& theID, const string& theFeatureID) +{ + bool isError = false; + map::iterator aVal = myIDs.find(theID); + if (aVal == myIDs.end()) { + Events_Error::send( + string("Validator ") + theID + " for feature " + theFeatureID + " was not registered"); + isError = true; + } + if (myFeatures.find(theFeatureID) != myFeatures.end()) { + Events_Error::send( + string("Validator for feature ") + theFeatureID + " is already registered"); + isError = true; + } + if (!isError) + myFeatures[theFeatureID] = aVal->second; +} + +void Model_ValidatorsFactory::assignValidator(const string& theID, + const string& theFeatureID, const string& theAttrID, const list& theArguments) +{ + bool isError = false; + map::iterator aVal = myIDs.find(theID); + if (aVal == myIDs.end()) { + Events_Error::send( + string("Validator ") + theID + " for feature " + theFeatureID + " was not registered"); + isError = true; + } + // create feature-structures if not exist + map > > >::iterator + aFeature = myAttrs.find(theFeatureID); + if (aFeature == myAttrs.end()) { + myAttrs[theFeatureID] = map > >(); + aFeature = myAttrs.find(theFeatureID); + } + // add attr-structure if not exist, or generate error if already exist + map > >::iterator + anAttr = aFeature->second.find(theAttrID); + if (anAttr == aFeature->second.end()) { + if (!isError) { + aFeature->second[theAttrID] = + pair >(aVal->second, theArguments); + } + } else { + Events_Error::send( + string("Validator ") + theID + " for feature " + theFeatureID + + "attribute " + theAttrID + " is already registered"); + isError = true; + } +} + +const ModelAPI_Validator* Model_ValidatorsFactory::validator(const string& theFeatureID) const +{ + map::const_iterator aFeature = myFeatures.find(theFeatureID); + if (aFeature != myFeatures.cend()) + return aFeature->second; + return NULL; // not found +} + +bool Model_ValidatorsFactory::validate( + const boost::shared_ptr& theFeature, const string& theAttrID ) const +{ + map > > >::const_iterator + aFeature = myAttrs.find(theFeature->getKind()); + if (aFeature == myAttrs.cend()) return true; // feature is not found + map > >::const_iterator + anAttr = aFeature->second.find(theAttrID); + if (anAttr == aFeature->second.cend()) return true; // attribute is not found + return anAttr->second.first->validate(theFeature, theAttrID, anAttr->second.second); +} + +Model_ValidatorsFactory::Model_ValidatorsFactory() : ModelAPI_ValidatorsFactory() +{ +} diff --git a/src/Model/Model_Validator.h b/src/Model/Model_Validator.h new file mode 100644 index 000000000..9d04e2901 --- /dev/null +++ b/src/Model/Model_Validator.h @@ -0,0 +1,59 @@ +// File: Model_Validator.hxx +// Created: 2 Jul 2014 +// Author: Mikhail PONIKAROV + +#ifndef Model_Validator_HeaderFile +#define Model_Validator_HeaderFile + +#include +#include +#include + +/**\class Model_ValidatorsFactory + * \ingroup DataModel + * \breif Manages the registered validators + * + * Allows to get a validator by the feature identifier and + * the attribute identifier (if attribute is validated). + * All accessible validators mustbe registered by the ID string first. + * The instance of this factory can be get in the PluginManager. + * Keeps the validator objects alive and just returns one of it by request. + * All the needed information is provided to the validator as an argument, + * this allows to work with them independently from the feature specific object. + */ +class Model_ValidatorsFactory: public ModelAPI_ValidatorsFactory +{ + std::map myIDs; ///< map from ID to registered validator + std::map myFeatures; ///< validators by feature ID + std::map > > > myAttrs; ///< validators and arguments by feature and attribute IDs +public: + /// Registers the instance of the validator by the ID + MODEL_EXPORT virtual void registerValidator( + const std::string& theID, ModelAPI_Validator* theValidator); + + /// Assigns validator to the feature + MODEL_EXPORT virtual void assignValidator( + const std::string& theID, const std::string& theFeatureID); + + /// Assigns validator to the attribute of the feature + MODEL_EXPORT virtual void assignValidator(const std::string& theID, + const std::string& theFeatureID, const std::string& theAttrID, + const std::list& theArguments); + + /// Provides a validator for the feature, returns NULL if no validator + MODEL_EXPORT virtual const ModelAPI_Validator* validator(const std::string& theFeatureID) const; + + /// Returns the result of "validate" method for attribute of validator. + /// If validator is not exists, returns true: everything is valid by default. + MODEL_EXPORT virtual bool validate( + const boost::shared_ptr& theFeature, const std::string& theAttrID) const; + +protected: + /// Get instance from PluginManager + Model_ValidatorsFactory(); + + friend class Model_PluginManager; +}; + +#endif diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index 3fd7da3a0..5a13d37a6 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -18,6 +18,7 @@ SET(PROJECT_HEADERS ModelAPI_AttributeRefList.h ModelAPI_AttributeBoolean.h ModelAPI_Events.h + ModelAPI_Validator.h ) SET(PROJECT_SOURCES diff --git a/src/ModelAPI/ModelAPI.i b/src/ModelAPI/ModelAPI.i index 589ac4026..8fd391b26 100644 --- a/src/ModelAPI/ModelAPI.i +++ b/src/ModelAPI/ModelAPI.i @@ -12,6 +12,7 @@ #include "ModelAPI_AttributeDouble.h" #include "ModelAPI_AttributeReference.h" #include "ModelAPI_AttributeRefAttr.h" + #include "ModelAPI_Validator.h" %} // to avoid error on this @@ -46,3 +47,4 @@ %include "ModelAPI_AttributeDouble.h" %include "ModelAPI_AttributeReference.h" %include "ModelAPI_AttributeRefAttr.h" +%include "ModelAPI_Validator.h" \ No newline at end of file diff --git a/src/ModelAPI/ModelAPI_PluginManager.cpp b/src/ModelAPI/ModelAPI_PluginManager.cpp index 766590a2e..72deaba2c 100644 --- a/src/ModelAPI/ModelAPI_PluginManager.cpp +++ b/src/ModelAPI/ModelAPI_PluginManager.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -42,7 +43,7 @@ ModelAPI_PluginManager::ModelAPI_PluginManager() { } -void ModelAPI_PluginManager::SetPluginManager( +void ModelAPI_PluginManager::setPluginManager( boost::shared_ptr theManager) { MY_MANAGER = theManager; diff --git a/src/ModelAPI/ModelAPI_PluginManager.h b/src/ModelAPI/ModelAPI_PluginManager.h index 6b25bf4a3..f23cf9581 100644 --- a/src/ModelAPI/ModelAPI_PluginManager.h +++ b/src/ModelAPI/ModelAPI_PluginManager.h @@ -12,6 +12,7 @@ class ModelAPI_Feature; class ModelAPI_Plugin; class ModelAPI_Document; +class ModelAPI_ValidatorsFactory; /**\class ModelAPI_PluginManager * \ingroup DataModel @@ -47,6 +48,9 @@ public: virtual boost::shared_ptr copy( boost::shared_ptr theSource, std::string theID) = 0; + /// Returns the validators factory: the only one instance per application + virtual ModelAPI_ValidatorsFactory* validators() = 0; + /// Is needed for python wrapping by swig, call Get to get an instance ModelAPI_PluginManager(); @@ -57,12 +61,11 @@ protected: /// Creates the feature object using plugins functionality virtual boost::shared_ptr createFeature(std::string theFeatureID) = 0; - static void SetPluginManager(boost::shared_ptr theManager); + static void setPluginManager(boost::shared_ptr theManager); friend class Model_Document; }; typedef boost::shared_ptr PluginManagerPtr; - #endif diff --git a/src/ModelAPI/ModelAPI_Validator.h b/src/ModelAPI/ModelAPI_Validator.h new file mode 100644 index 000000000..4a0243cd0 --- /dev/null +++ b/src/ModelAPI/ModelAPI_Validator.h @@ -0,0 +1,77 @@ +// File: ModelAPI_Validator.hxx +// Created: 2 Jul 2014 +// Author: Mikhail PONIKAROV + +#ifndef ModelAPI_Validator_HeaderFile +#define ModelAPI_Validator_HeaderFile + +#include +#include +#include + +class ModelAPI_Feature; + +/**\class ModelAPI_Validator + * \ingroup DataModel + * \brief Allows to validate the attribute value of a feature or the whole feature. + * + * This object is assigned by the name + * in the XML file to the specific attribute or to the whole feature. + * If validator returns "false", it is signalized in user interface + * and feature is not executed. + * Validators must be registered in the validators factory to be + * correctly identified by the XML string-ID. + */ +class MODELAPI_EXPORT ModelAPI_Validator +{ +public: + /// Returns true if feature and/or attributes are valid + /// \param theFeature the validated feature + /// \param theAttr the validated attribute ID, empty string of feature is validated + /// \param theArguments list of string, feature attribute names: dependent attributes + virtual bool validate(const boost::shared_ptr& theFeature, + const std::string theAttr, std::list theArguments) const = 0; +}; + +typedef boost::shared_ptr ValidatorPtr; + +/**\class ModelAPI_ValidatorsFactory + * \ingroup DataModel + * \breif Manages the registered validators + * + * Allows to get a validator by the feature identifier and + * the attribute identifier (if attribute is validated). + * All accessible validators mustbe registered by the ID string first. + * The instance of this factory can be get in the PluginManager. + * Keeps the validator objects alive and just returns one of it by request. + * All the needed information is provided to the validator as an argument, + * this allows to work with them independently from the feature specific object. + */ +class MODELAPI_EXPORT ModelAPI_ValidatorsFactory +{ +public: + /// Registers the instance of the validator by the ID + virtual void registerValidator(const std::string& theID, ModelAPI_Validator* theValidator) = 0; + + /// Assigns validator to the feature + virtual void assignValidator(const std::string& theID, const std::string& theFeatureID) = 0; + + /// Assigns validator to the attribute of the feature + virtual void assignValidator(const std::string& theID, + const std::string& theFeatureID, const std::string& theAttrID, + const std::list& theArguments) = 0; + + /// Provides a validator for the feature, returns NULL if no validator + virtual const ModelAPI_Validator* validator(const std::string& theFeatureID) const = 0; + + /// Returns the result of "validate" method for attribute of validator. + /// If validator is not exists, returns true: everything is valid by default. + virtual bool validate( + const boost::shared_ptr& theFeature, const std::string& theAttrID) const = 0; + +protected: + /// Get instance from PluginManager + ModelAPI_ValidatorsFactory() {} +}; + +#endif -- 2.39.2