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 <Events_InfoMessage.h>
21 void Model_ValidatorsFactory::registerValidator(const std::string& theID,
22 ModelAPI_Validator* theValidator)
24 if (myIDs.find(theID) != myIDs.end()) {
25 Events_InfoMessage("Model_Validator", "Validator %1 is already registered").arg(theID).send();
27 myIDs[theID] = theValidator;
31 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
32 const std::string& theFeatureID)
34 if (myFeatures.find(theFeatureID) == myFeatures.end()) {
35 myFeatures[theFeatureID] = AttrValidators();
37 if (myFeatures[theFeatureID].find(theID) != myFeatures[theFeatureID].end()) {
38 //Events_Error::send(std::string("Validator ") + theID +
39 // " for feature " + theFeatureID + "is already registered");
41 myFeatures[theFeatureID][theID] = std::list<std::string>();
45 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
46 const std::string& theFeatureID,
47 const std::list<std::string>& theArguments)
49 if (myFeatures.find(theFeatureID) == myFeatures.end()) {
50 myFeatures[theFeatureID] = AttrValidators();
53 if (myFeatures[theFeatureID].find(theID) != myFeatures[theFeatureID].end()) {
54 //Events_Error::send(std::string("Validator ") + theID +
55 // " for feature " + theFeatureID + "is already registered");
57 myFeatures[theFeatureID][theID] = theArguments;
61 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
62 const std::string& theFeatureID,
63 const std::string& theAttrID,
64 const std::list<std::string>& theArguments)
66 // create feature-structures if not exist
67 std::map<std::string, std::map<std::string, AttrValidators> >::iterator aFeature = myAttrs.find(
69 if (aFeature == myAttrs.end()) {
70 myAttrs[theFeatureID] = std::map<std::string, AttrValidators>();
71 aFeature = myAttrs.find(theFeatureID);
73 // add attr-structure if not exist, or generate error if already exist
74 std::map<std::string, AttrValidators>::iterator anAttr = aFeature->second.find(theAttrID);
75 if (anAttr == aFeature->second.end()) {
76 aFeature->second[theAttrID] = AttrValidators();
78 aFeature->second[theAttrID][theID] = theArguments;
81 void Model_ValidatorsFactory::validators(const std::string& theFeatureID,
82 Validators& theValidators) const
84 std::map<std::string, AttrValidators>::const_iterator aFeatureIt =
85 myFeatures.find(theFeatureID);
86 if (aFeatureIt != myFeatures.cend()) {
87 AttrValidators::const_iterator aValidatorsIt = aFeatureIt->second.cbegin();
88 for (; aValidatorsIt != aFeatureIt->second.cend(); aValidatorsIt++) {
89 if (!validator(aValidatorsIt->first)) {
90 Events_InfoMessage("Model_Validator", "Validator %1 was not registered")
91 .arg(aValidatorsIt->first).send();
93 theValidators.push_back(std::make_pair(aValidatorsIt->first, aValidatorsIt->second));
97 addDefaultValidators(theValidators);
100 void Model_ValidatorsFactory::validators(const std::string& theFeatureID,
101 const std::string& theAttrID,
102 Validators& theValidators) const
104 std::map<std::string, std::map<std::string, AttrValidators> >::const_iterator aFeatureIt =
105 myAttrs.find(theFeatureID);
106 if (aFeatureIt != myAttrs.cend()) {
107 std::map<std::string, AttrValidators>::const_iterator anAttrIt =
108 aFeatureIt->second.find(theAttrID);
109 if (anAttrIt != aFeatureIt->second.end()) {
110 AttrValidators::const_iterator aValidatorsIt = anAttrIt->second.cbegin();
111 for (; aValidatorsIt != anAttrIt->second.cend(); aValidatorsIt++) {
112 if (!validator(aValidatorsIt->first)) {
113 Events_InfoMessage("Model_Validator", "Validator %1 was not registered")
114 .arg(aValidatorsIt->first).send();
116 theValidators.push_back(std::make_pair(aValidatorsIt->first, aValidatorsIt->second));
121 addDefaultAttributeValidators(theValidators);
124 Model_ValidatorsFactory::Model_ValidatorsFactory()
125 : ModelAPI_ValidatorsFactory()
127 registerValidator("Model_FeatureValidator", new Model_FeatureValidator);
128 registerValidator("Model_AttributeValidator", new Model_AttributeValidator);
131 const ModelAPI_Validator* Model_ValidatorsFactory::validator(const std::string& theID) const
133 std::map<std::string, ModelAPI_Validator*>::const_iterator aIt = myIDs.find(theID);
134 if (aIt != myIDs.end()) {
140 void Model_ValidatorsFactory::addDefaultValidators(Validators& theValidators) const
142 const static std::string kDefaultId = "Model_FeatureValidator";
143 if (!validator(kDefaultId))
145 theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
148 void Model_ValidatorsFactory::addDefaultAttributeValidators(Validators& theValidators) const
150 const static std::string kDefaultId = "Model_AttributeValidator";
151 if (!validator(kDefaultId))
153 theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
156 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Feature>& theFeature) const
158 std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theFeature->data());
159 if (aData.get() && aData->isValid()) {
160 if (aData->execState() == ModelAPI_StateDone)
161 aData->eraseErrorString(); // no error => erase the information string
163 return false; // feature is broken, already not presented in the data structure
166 // check feature validators first
167 Validators aValidators;
168 validators(theFeature->getKind(), aValidators);
170 if (!aValidators.empty()) {
171 Validators::const_iterator aValidatorIt = aValidators.cbegin();
172 for(; aValidatorIt != aValidators.cend(); aValidatorIt++) {
173 const std::string& aValidatorID = aValidatorIt->first;
174 const std::list<std::string>& anArguments = aValidatorIt->second;
175 // validators() checks invalid validator names
177 // Events_Error::send(std::string("Validator ") + aValidatorID + " was not registered");
180 const ModelAPI_FeatureValidator* aFValidator =
181 dynamic_cast<const ModelAPI_FeatureValidator*>(validator(aValidatorID));
183 Events_InfoMessage anError;
184 if (!aFValidator->isValid(theFeature, anArguments, anError)) {
186 anError = "Unknown error.";
187 anError = aValidatorID + ": " + anError.messageString();
188 theFeature->setError(anError.messageString(), false);
189 theFeature->data()->execState(ModelAPI_StateInvalidArgument);
195 // The default validator was retrned by validators() and was checked in previous cycle
196 //// check default validator
197 //std::map<std::string, ModelAPI_Validator*>::const_iterator aDefaultVal = myIDs.find(kDefaultId);
198 //if(aDefaultVal != myIDs.end()) {
199 // static const std::list<std::string> anEmptyArgList;
200 // const ModelAPI_FeatureValidator* aFValidator =
201 // dynamic_cast<const ModelAPI_FeatureValidator*>(aDefaultVal->second);
202 // if (aFValidator) {
203 // std::string anError;
204 // if (!aFValidator->isValid(theFeature, anEmptyArgList, anError)) {
205 // if (anError.empty())
206 // anError = "Unknown error.";
207 // anError = "Feature invalidated by \"" + kDefaultId + "\" with error: " + anError;
208 // theFeature->setError(anError, false);
209 // theFeature->data()->execState(ModelAPI_StateInvalidArgument);
215 // check all attributes for validity
216 // Validity of data is checked by "Model_FeatureValidator" (kDefaultId)
217 // if (!aData || !aData->isValid())
219 static const std::string kAllTypes = "";
220 std::list<std::string> aLtAttributes = aData->attributesIDs(kAllTypes);
221 std::list<std::string>::const_iterator anAttrIt = aLtAttributes.cbegin();
222 for (; anAttrIt != aLtAttributes.cend(); anAttrIt++) {
223 const std::string& anAttributeID = *anAttrIt;
224 AttributePtr anAttribute = theFeature->data()->attribute(anAttributeID);
226 std::string aValidatorID;
227 Events_InfoMessage anError;
228 if (!validate(anAttribute, aValidatorID, anError)) {
230 anError = "Unknown error.";
231 anError = anAttributeID + " - " + aValidatorID + ": " + anError.messageString();
232 theFeature->setError(anError.messageString(), false);
233 theFeature->data()->execState(ModelAPI_StateInvalidArgument);
241 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Attribute>& theAttribute,
242 std::string& theValidator,
243 Events_InfoMessage& theError) const
245 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
246 if (!aFeature.get()) {
247 theValidator = "Model_ValidatorsFactory";
248 theError = "Attribute has no feature.";
252 // skip not-case attributes, that really may be invalid (issue 671)
253 if (!const_cast<Model_ValidatorsFactory*>(this)->isCase(aFeature, theAttribute->id()))
256 Validators aValidators;
257 validators(aFeature->getKind(), theAttribute->id(), aValidators);
259 Validators::iterator aValidatorIt = aValidators.begin();
260 for (; aValidatorIt != aValidators.end(); ++aValidatorIt) {
261 const std::string& aValidatorID = aValidatorIt->first;
262 const std::list<std::string>& anArguments = aValidatorIt->second;
263 const ModelAPI_AttributeValidator* anAttrValidator =
264 dynamic_cast<const ModelAPI_AttributeValidator*>(validator(aValidatorID));
265 if (!anAttrValidator)
267 if (!anAttrValidator->isValid(theAttribute, anArguments, theError)) {
268 theValidator = aValidatorID;
276 void Model_ValidatorsFactory::registerNotObligatory(std::string theFeature,
277 std::string theAttribute)
279 const static std::string kDefaultId = "Model_FeatureValidator";
280 std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
281 if (it != myIDs.end()) {
282 Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
284 aValidator->registerNotObligatory(theFeature, theAttribute);
289 bool Model_ValidatorsFactory::isNotObligatory(std::string theFeature, std::string theAttribute)
291 const static std::string kDefaultId = "Model_FeatureValidator";
292 std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
293 if (it != myIDs.end()) {
294 Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
296 return aValidator->isNotObligatory(theFeature, theAttribute);
299 return false; // default
302 void Model_ValidatorsFactory::registerConcealment(std::string theFeature, std::string theAttribute)
304 std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
305 if (aFind == myConcealed.end()) {
306 std::set<std::string> aNewSet;
307 aNewSet.insert(theAttribute);
308 myConcealed[theFeature] = aNewSet;
310 aFind->second.insert(theAttribute);
314 bool Model_ValidatorsFactory::isConcealed(std::string theFeature, std::string theAttribute)
316 std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
317 return aFind != myConcealed.end() && aFind->second.find(theAttribute) != aFind->second.end();
320 void Model_ValidatorsFactory::registerUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
321 std::shared_ptr<ModelAPI_Feature> theCanceledFeat)
323 if (myUnconcealed.find(theUnconcealed) == myUnconcealed.end()) {
324 myUnconcealed[theUnconcealed] = std::list<std::shared_ptr<ModelAPI_Feature> >();
326 myUnconcealed[theUnconcealed].push_back(theCanceledFeat);
327 std::dynamic_pointer_cast<Model_Data>(theUnconcealed->data())->updateConcealmentFlag();
330 void Model_ValidatorsFactory::disableUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
331 std::shared_ptr<ModelAPI_Feature> theCanceledFeat)
333 std::map<std::shared_ptr<ModelAPI_Result>, std::list<std::shared_ptr<ModelAPI_Feature> > >
334 ::iterator aResFound = myUnconcealed.find(theUnconcealed);
335 if (aResFound != myUnconcealed.end()) {
336 std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anIter = aResFound->second.begin();
337 for(; anIter != aResFound->second.end(); anIter++) {
338 if (*anIter == theCanceledFeat) {
339 aResFound->second.erase(anIter);
340 std::dynamic_pointer_cast<Model_Data>(theUnconcealed->data())->updateConcealmentFlag();
347 bool Model_ValidatorsFactory::isUnconcealed(std::shared_ptr<ModelAPI_Result> theUnconcealed,
348 std::shared_ptr<ModelAPI_Feature> theCanceledFeat)
350 std::map<std::shared_ptr<ModelAPI_Result>, std::list<std::shared_ptr<ModelAPI_Feature> > >
351 ::iterator aResFound = myUnconcealed.find(theUnconcealed);
352 if (aResFound != myUnconcealed.end()) {
353 std::list<std::shared_ptr<ModelAPI_Feature> >::iterator aFeatIter = aResFound->second.begin();
354 for(; aFeatIter != aResFound->second.end(); aFeatIter++) {
355 if (aFeatIter->get()) {
356 if ((*aFeatIter)->isDisabled()) continue;
357 if (*aFeatIter == theCanceledFeat)
358 return true; // this is exactly canceled
359 if (theCanceledFeat->document()->isLater(*aFeatIter, theCanceledFeat))
360 return true; // if unconcealed feature (from the list) is later than concealed
362 return true; // empty attribute means that everything is canceled
368 void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string theAttribute,
369 const std::list<std::pair<std::string, std::string> >& theCases)
371 std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
372 ::iterator aFindFeature = myCases.find(theFeature);
373 if (aFindFeature == myCases.end()) {
374 myCases[theFeature] = std::map<std::string, std::map<std::string, std::set<std::string> > >();
375 aFindFeature = myCases.find(theFeature);
377 std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator aFindAttrID =
378 aFindFeature->second.find(theAttribute);
380 if (aFindAttrID == aFindFeature->second.end()) {
381 aFindFeature->second[theAttribute] =
382 std::map<std::string, std::set<std::string> >();
383 aFindAttrID = aFindFeature->second.find(theAttribute);
385 std::list<std::pair<std::string, std::string> >::const_iterator aCasesIt = theCases.begin(),
386 aCasesLast = theCases.end();
387 std::map<std::string, std::set<std::string> > aFindCases = aFindAttrID->second;
388 for (; aCasesIt != aCasesLast; aCasesIt++) {
389 std::pair<std::string, std::string> aCasePair = *aCasesIt;
390 std::string aSwitch = aCasePair.first;
391 if (aFindAttrID->second.find(aSwitch) == aFindAttrID->second.end()) {
392 aFindAttrID->second[aSwitch] = std::set<std::string>();
394 aFindAttrID->second[aSwitch].insert(aCasePair.second);
398 bool Model_ValidatorsFactory::isCase(FeaturePtr theFeature, std::string theAttribute)
400 bool anInCase = true;
401 std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
402 ::iterator aFindFeature = myCases.find(theFeature->getKind());
403 if (aFindFeature != myCases.end()) {
404 std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator
405 aFindAttrID = aFindFeature->second.find(theAttribute);
406 if (aFindAttrID != aFindFeature->second.end()) {
407 std::map<std::string, std::set<std::string> >::iterator
408 aCasesIt = aFindAttrID->second.begin(), aCasesLast = aFindAttrID->second.end();
409 for (; aCasesIt != aCasesLast && anInCase; aCasesIt++) {
410 // the the switch-attribute that contains the case value
411 AttributeStringPtr aSwitch = theFeature->string(aCasesIt->first);
413 // the second has the case identifier
414 anInCase = aCasesIt->second.find(aSwitch->value()) != aCasesIt->second.end();
419 return anInCase; // if no additional conditions, this attribute is the case to be validated