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 // validators() checks invalid validator names
179 // Events_Error::send(std::string("Validator ") + aValidatorID + " was not registered");
182 const ModelAPI_FeatureValidator* aFValidator =
183 dynamic_cast<const ModelAPI_FeatureValidator*>(validator(aValidatorID));
185 Events_InfoMessage anError;
186 if (!aFValidator->isValid(theFeature, anArguments, anError)) {
188 anError = "Unknown error.";
189 if (anError.context().empty()) {
190 anError.setContext(theFeature->getKind() + ":" + aValidatorID);
192 theFeature->setError(Config_Translator::translate(anError), false, false);
193 theFeature->data()->execState(ModelAPI_StateInvalidArgument);
199 // The default validator was retrned by validators() and was checked in previous cycle
200 //// check default validator
201 //std::map<std::string, ModelAPI_Validator*>::const_iterator aDefaultVal = myIDs.find(kDefaultId);
202 //if(aDefaultVal != myIDs.end()) {
203 // static const std::list<std::string> anEmptyArgList;
204 // const ModelAPI_FeatureValidator* aFValidator =
205 // dynamic_cast<const ModelAPI_FeatureValidator*>(aDefaultVal->second);
206 // if (aFValidator) {
207 // std::string anError;
208 // if (!aFValidator->isValid(theFeature, anEmptyArgList, anError)) {
209 // if (anError.empty())
210 // anError = "Unknown error.";
211 // anError = "Feature invalidated by \"" + kDefaultId + "\" with error: " + anError;
212 // theFeature->setError(anError, false);
213 // theFeature->data()->execState(ModelAPI_StateInvalidArgument);
219 // check all attributes for validity
220 // Validity of data is checked by "Model_FeatureValidator" (kDefaultId)
221 // if (!aData || !aData->isValid())
223 static const std::string kAllTypes = "";
224 std::list<std::string> aLtAttributes = aData->attributesIDs(kAllTypes);
225 std::list<std::string>::const_iterator anAttrIt = aLtAttributes.cbegin();
226 for (; anAttrIt != aLtAttributes.cend(); anAttrIt++) {
227 const std::string& anAttributeID = *anAttrIt;
228 AttributePtr anAttribute = theFeature->data()->attribute(anAttributeID);
230 std::string aValidatorID;
231 Events_InfoMessage anError;
232 if (!validate(anAttribute, aValidatorID, anError)) {
234 anError = "Unknown error.";
235 if (anError.context().empty()) {
236 anError.setContext(theFeature->getKind() + ":" + anAttributeID + ":" + aValidatorID);
238 theFeature->setError(Config_Translator::translate(anError), false, false);
239 theFeature->data()->execState(ModelAPI_StateInvalidArgument);
247 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Attribute>& theAttribute,
248 std::string& theValidator,
249 Events_InfoMessage& theError) const
251 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
252 if (!aFeature.get()) {
253 theValidator = "Model_ValidatorsFactory";
254 theError = "Attribute has no feature.";
258 // skip not-case attributes, that really may be invalid (issue 671)
259 if (!const_cast<Model_ValidatorsFactory*>(this)->isCase(aFeature, theAttribute->id()))
262 Validators aValidators;
263 validators(aFeature->getKind(), theAttribute->id(), aValidators);
265 Validators::iterator aValidatorIt = aValidators.begin();
266 for (; aValidatorIt != aValidators.end(); ++aValidatorIt) {
267 const std::string& aValidatorID = aValidatorIt->first;
268 const std::list<std::string>& anArguments = aValidatorIt->second;
269 const ModelAPI_AttributeValidator* anAttrValidator =
270 dynamic_cast<const ModelAPI_AttributeValidator*>(validator(aValidatorID));
271 if (!anAttrValidator)
273 if (!anAttrValidator->isValid(theAttribute, anArguments, theError)) {
274 theValidator = aValidatorID;
282 void Model_ValidatorsFactory::registerNotObligatory(std::string theFeature,
283 std::string theAttribute)
285 const static std::string kDefaultId = "Model_FeatureValidator";
286 std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
287 if (it != myIDs.end()) {
288 Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
290 aValidator->registerNotObligatory(theFeature, theAttribute);
295 bool Model_ValidatorsFactory::isNotObligatory(std::string theFeature, std::string theAttribute)
297 const static std::string kDefaultId = "Model_FeatureValidator";
298 std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
299 if (it != myIDs.end()) {
300 Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
302 return aValidator->isNotObligatory(theFeature, theAttribute);
305 return false; // default
308 void Model_ValidatorsFactory::registerConcealment(std::string theFeature, std::string theAttribute)
310 std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
311 if (aFind == myConcealed.end()) {
312 std::set<std::string> aNewSet;
313 aNewSet.insert(theAttribute);
314 myConcealed[theFeature] = aNewSet;
316 aFind->second.insert(theAttribute);
320 bool Model_ValidatorsFactory::isConcealed(std::string theFeature, std::string theAttribute)
322 std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
323 return aFind != myConcealed.end() && aFind->second.find(theAttribute) != aFind->second.end();
326 void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string theAttribute,
327 const std::list<std::pair<std::string, std::string> >& theCases)
329 std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
330 ::iterator aFindFeature = myCases.find(theFeature);
331 if (aFindFeature == myCases.end()) {
332 myCases[theFeature] = std::map<std::string, std::map<std::string, std::set<std::string> > >();
333 aFindFeature = myCases.find(theFeature);
335 std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator aFindAttrID =
336 aFindFeature->second.find(theAttribute);
338 if (aFindAttrID == aFindFeature->second.end()) {
339 aFindFeature->second[theAttribute] =
340 std::map<std::string, std::set<std::string> >();
341 aFindAttrID = aFindFeature->second.find(theAttribute);
343 std::list<std::pair<std::string, std::string> >::const_iterator aCasesIt = theCases.begin(),
344 aCasesLast = theCases.end();
345 std::map<std::string, std::set<std::string> > aFindCases = aFindAttrID->second;
346 for (; aCasesIt != aCasesLast; aCasesIt++) {
347 std::pair<std::string, std::string> aCasePair = *aCasesIt;
348 std::string aSwitch = aCasePair.first;
349 if (aFindAttrID->second.find(aSwitch) == aFindAttrID->second.end()) {
350 aFindAttrID->second[aSwitch] = std::set<std::string>();
352 aFindAttrID->second[aSwitch].insert(aCasePair.second);
356 bool Model_ValidatorsFactory::isCase(FeaturePtr theFeature, std::string theAttribute)
358 bool anInCase = true;
359 std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
360 ::iterator aFindFeature = myCases.find(theFeature->getKind());
361 if (aFindFeature != myCases.end()) {
362 std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator
363 aFindAttrID = aFindFeature->second.find(theAttribute);
364 if (aFindAttrID != aFindFeature->second.end()) {
365 std::map<std::string, std::set<std::string> >::iterator
366 aCasesIt = aFindAttrID->second.begin(), aCasesLast = aFindAttrID->second.end();
367 for (; aCasesIt != aCasesLast && anInCase; aCasesIt++) {
368 // the the switch-attribute that contains the case value
369 AttributeStringPtr aSwitch = theFeature->string(aCasesIt->first);
371 // the second has the case identifier
372 anInCase = aCasesIt->second.find(aSwitch->value()) != aCasesIt->second.end();
377 return anInCase; // if no additional conditions, this attribute is the case to be validated