1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: Model_Validator.cpp
5 // Author: Mikhail PONIKAROV
7 #include "Model_Validator.h"
9 #include "Model_AttributeValidator.h"
10 #include "Model_FeatureValidator.h"
12 #include <ModelAPI_Attribute.h>
13 #include <ModelAPI_AttributeString.h>
14 #include <ModelAPI_AttributeValidator.h>
15 #include <ModelAPI_Feature.h>
16 #include <ModelAPI_Result.h>
17 #include <Model_Data.h>
19 #include <Config_Translator.h>
21 #include <Events_InfoMessage.h>
23 void Model_ValidatorsFactory::registerValidator(const std::string& theID,
24 ModelAPI_Validator* theValidator)
26 if (myIDs.find(theID) != myIDs.end()) {
27 Events_InfoMessage("Model_Validator", "Validator %1 is already registered").arg(theID).send();
29 myIDs[theID] = theValidator;
33 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
34 const std::string& theFeatureID)
36 if (myFeatures.find(theFeatureID) == myFeatures.end()) {
37 myFeatures[theFeatureID] = AttrValidators();
39 if (myFeatures[theFeatureID].find(theID) != myFeatures[theFeatureID].end()) {
40 //Events_Error::send(std::string("Validator ") + theID +
41 // " for feature " + theFeatureID + "is already registered");
43 myFeatures[theFeatureID][theID] = std::list<std::string>();
47 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
48 const std::string& theFeatureID,
49 const std::list<std::string>& theArguments)
51 if (myFeatures.find(theFeatureID) == myFeatures.end()) {
52 myFeatures[theFeatureID] = AttrValidators();
55 if (myFeatures[theFeatureID].find(theID) != myFeatures[theFeatureID].end()) {
56 //Events_Error::send(std::string("Validator ") + theID +
57 // " for feature " + theFeatureID + "is already registered");
59 myFeatures[theFeatureID][theID] = theArguments;
63 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
64 const std::string& theFeatureID,
65 const std::string& theAttrID,
66 const std::list<std::string>& theArguments)
68 // create feature-structures if not exist
69 std::map<std::string, std::map<std::string, AttrValidators> >::iterator aFeature = myAttrs.find(
71 if (aFeature == myAttrs.end()) {
72 myAttrs[theFeatureID] = std::map<std::string, AttrValidators>();
73 aFeature = myAttrs.find(theFeatureID);
75 // add attr-structure if not exist, or generate error if already exist
76 std::map<std::string, AttrValidators>::iterator anAttr = aFeature->second.find(theAttrID);
77 if (anAttr == aFeature->second.end()) {
78 aFeature->second[theAttrID] = AttrValidators();
80 aFeature->second[theAttrID][theID] = theArguments;
83 void Model_ValidatorsFactory::validators(const std::string& theFeatureID,
84 Validators& theValidators) const
86 std::map<std::string, AttrValidators>::const_iterator aFeatureIt =
87 myFeatures.find(theFeatureID);
88 if (aFeatureIt != myFeatures.cend()) {
89 AttrValidators::const_iterator aValidatorsIt = aFeatureIt->second.cbegin();
90 for (; aValidatorsIt != aFeatureIt->second.cend(); aValidatorsIt++) {
91 if (!validator(aValidatorsIt->first)) {
92 Events_InfoMessage("Model_Validator", "Validator %1 was not registered")
93 .arg(aValidatorsIt->first).send();
95 theValidators.push_back(std::make_pair(aValidatorsIt->first, aValidatorsIt->second));
99 addDefaultValidators(theValidators);
102 void Model_ValidatorsFactory::validators(const std::string& theFeatureID,
103 const std::string& theAttrID,
104 Validators& theValidators) const
106 std::map<std::string, std::map<std::string, AttrValidators> >::const_iterator aFeatureIt =
107 myAttrs.find(theFeatureID);
108 if (aFeatureIt != myAttrs.cend()) {
109 std::map<std::string, AttrValidators>::const_iterator anAttrIt =
110 aFeatureIt->second.find(theAttrID);
111 if (anAttrIt != aFeatureIt->second.end()) {
112 AttrValidators::const_iterator aValidatorsIt = anAttrIt->second.cbegin();
113 for (; aValidatorsIt != anAttrIt->second.cend(); aValidatorsIt++) {
114 if (!validator(aValidatorsIt->first)) {
115 Events_InfoMessage("Model_Validator", "Validator %1 was not registered")
116 .arg(aValidatorsIt->first).send();
118 theValidators.push_back(std::make_pair(aValidatorsIt->first, aValidatorsIt->second));
123 addDefaultAttributeValidators(theValidators);
126 Model_ValidatorsFactory::Model_ValidatorsFactory()
127 : ModelAPI_ValidatorsFactory()
129 registerValidator("Model_FeatureValidator", new Model_FeatureValidator);
130 registerValidator("Model_AttributeValidator", new Model_AttributeValidator);
133 const ModelAPI_Validator* Model_ValidatorsFactory::validator(const std::string& theID) const
135 std::map<std::string, ModelAPI_Validator*>::const_iterator aIt = myIDs.find(theID);
136 if (aIt != myIDs.end()) {
142 void Model_ValidatorsFactory::addDefaultValidators(Validators& theValidators) const
144 const static std::string kDefaultId = "Model_FeatureValidator";
145 if (!validator(kDefaultId))
147 theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
150 void Model_ValidatorsFactory::addDefaultAttributeValidators(Validators& theValidators) const
152 const static std::string kDefaultId = "Model_AttributeValidator";
153 if (!validator(kDefaultId))
155 theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
158 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Feature>& theFeature) const
160 std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theFeature->data());
161 if (aData.get() && aData->isValid()) {
162 if (aData->execState() == ModelAPI_StateDone)
163 aData->eraseErrorString(); // no error => erase the information string
165 return false; // feature is broken, already not presented in the data structure
168 // check feature validators first
169 Validators aValidators;
170 validators(theFeature->getKind(), aValidators);
172 if (!aValidators.empty()) {
173 Validators::const_iterator aValidatorIt = aValidators.cbegin();
174 for(; aValidatorIt != aValidators.cend(); aValidatorIt++) {
175 const std::string& aValidatorID = aValidatorIt->first;
176 const std::list<std::string>& anArguments = aValidatorIt->second;
177 const ModelAPI_FeatureValidator* aFValidator =
178 dynamic_cast<const ModelAPI_FeatureValidator*>(validator(aValidatorID));
180 Events_InfoMessage anError;
181 if (!aFValidator->isValid(theFeature, anArguments, anError)) {
183 anError = "Unknown error.";
184 if (anError.context().empty()) {
185 anError.setContext(theFeature->getKind() + ":" + aValidatorID);
187 theFeature->setError(Config_Translator::translate(anError), false, false);
188 theFeature->data()->execState(ModelAPI_StateInvalidArgument);
195 // check all attributes for validity
196 static const std::string kAllTypes = "";
197 std::list<std::string> aLtAttributes = aData->attributesIDs(kAllTypes);
198 std::list<std::string>::const_iterator anAttrIt = aLtAttributes.cbegin();
199 for (; anAttrIt != aLtAttributes.cend(); anAttrIt++) {
200 const std::string& anAttributeID = *anAttrIt;
201 AttributePtr anAttribute = theFeature->data()->attribute(anAttributeID);
203 std::string aValidatorID;
204 Events_InfoMessage anError;
205 if (!validate(anAttribute, aValidatorID, anError)) {
207 anError = "Unknown error.";
208 if (anError.context().empty()) {
209 anError.setContext(theFeature->getKind() + ":" + anAttributeID + ":" + aValidatorID);
211 theFeature->setError(Config_Translator::translate(anError), false, false);
212 theFeature->data()->execState(ModelAPI_StateInvalidArgument);
220 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Attribute>& theAttribute,
221 std::string& theValidator,
222 Events_InfoMessage& theError) const
224 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
225 if (!aFeature.get()) {
226 theValidator = "Model_ValidatorsFactory";
227 theError = "Attribute has no feature.";
231 // skip not-case attributes, that really may be invalid (issue 671)
232 if (!const_cast<Model_ValidatorsFactory*>(this)->isCase(aFeature, theAttribute->id()))
235 Validators aValidators;
236 validators(aFeature->getKind(), theAttribute->id(), aValidators);
238 Validators::iterator aValidatorIt = aValidators.begin();
239 for (; aValidatorIt != aValidators.end(); ++aValidatorIt) {
240 const std::string& aValidatorID = aValidatorIt->first;
241 const std::list<std::string>& anArguments = aValidatorIt->second;
242 const ModelAPI_AttributeValidator* anAttrValidator =
243 dynamic_cast<const ModelAPI_AttributeValidator*>(validator(aValidatorID));
244 if (!anAttrValidator)
246 if (!anAttrValidator->isValid(theAttribute, anArguments, theError)) {
247 theValidator = aValidatorID;
255 void Model_ValidatorsFactory::registerNotObligatory(std::string theFeature,
256 std::string theAttribute)
258 const static std::string kDefaultId = "Model_FeatureValidator";
259 std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
260 if (it != myIDs.end()) {
261 Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
263 aValidator->registerNotObligatory(theFeature, theAttribute);
268 bool Model_ValidatorsFactory::isNotObligatory(std::string theFeature, std::string theAttribute)
270 const static std::string kDefaultId = "Model_FeatureValidator";
271 std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
272 if (it != myIDs.end()) {
273 Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
275 return aValidator->isNotObligatory(theFeature, theAttribute);
278 return false; // default
281 void Model_ValidatorsFactory::registerConcealment(std::string theFeature, std::string theAttribute)
283 std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
284 if (aFind == myConcealed.end()) {
285 std::set<std::string> aNewSet;
286 aNewSet.insert(theAttribute);
287 myConcealed[theFeature] = aNewSet;
289 aFind->second.insert(theAttribute);
293 bool Model_ValidatorsFactory::isConcealed(std::string theFeature, std::string theAttribute)
295 std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
296 return aFind != myConcealed.end() && aFind->second.find(theAttribute) != aFind->second.end();
299 void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string theAttribute,
300 const std::list<std::pair<std::string, std::string> >& theCases)
302 std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
303 ::iterator aFindFeature = myCases.find(theFeature);
304 if (aFindFeature == myCases.end()) {
305 myCases[theFeature] = std::map<std::string, std::map<std::string, std::set<std::string> > >();
306 aFindFeature = myCases.find(theFeature);
308 std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator aFindAttrID =
309 aFindFeature->second.find(theAttribute);
311 if (aFindAttrID == aFindFeature->second.end()) {
312 aFindFeature->second[theAttribute] =
313 std::map<std::string, std::set<std::string> >();
314 aFindAttrID = aFindFeature->second.find(theAttribute);
316 std::list<std::pair<std::string, std::string> >::const_iterator aCasesIt = theCases.begin(),
317 aCasesLast = theCases.end();
318 std::map<std::string, std::set<std::string> > aFindCases = aFindAttrID->second;
319 for (; aCasesIt != aCasesLast; aCasesIt++) {
320 std::pair<std::string, std::string> aCasePair = *aCasesIt;
321 std::string aSwitch = aCasePair.first;
322 if (aFindAttrID->second.find(aSwitch) == aFindAttrID->second.end()) {
323 aFindAttrID->second[aSwitch] = std::set<std::string>();
325 aFindAttrID->second[aSwitch].insert(aCasePair.second);
329 bool Model_ValidatorsFactory::isCase(FeaturePtr theFeature, std::string theAttribute)
331 bool anInCase = true;
332 std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
333 ::iterator aFindFeature = myCases.find(theFeature->getKind());
334 if (aFindFeature != myCases.end()) {
335 std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator
336 aFindAttrID = aFindFeature->second.find(theAttribute);
337 if (aFindAttrID != aFindFeature->second.end()) {
338 std::map<std::string, std::set<std::string> >::iterator
339 aCasesIt = aFindAttrID->second.begin(), aCasesLast = aFindAttrID->second.end();
340 for (; aCasesIt != aCasesLast && anInCase; aCasesIt++) {
341 // the the switch-attribute that contains the case value
342 AttributeStringPtr aSwitch = theFeature->string(aCasesIt->first);
344 // the second has the case identifier
345 anInCase = aCasesIt->second.find(aSwitch->value()) != aCasesIt->second.end();
350 return anInCase; // if no additional conditions, this attribute is the case to be validated