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, const std::string& theAttrID,
101 Validators& theValidators) const
103 std::map<std::string, std::map<std::string, AttrValidators> >::const_iterator aFeatureIt =
104 myAttrs.find(theFeatureID);
105 if (aFeatureIt != myAttrs.cend()) {
106 std::map<std::string, AttrValidators>::const_iterator anAttrIt = aFeatureIt->second.find(theAttrID);
107 if (anAttrIt != aFeatureIt->second.end()) {
108 AttrValidators::const_iterator aValidatorsIt = anAttrIt->second.cbegin();
109 for (; aValidatorsIt != anAttrIt->second.cend(); aValidatorsIt++) {
110 if (!validator(aValidatorsIt->first)) {
111 Events_InfoMessage("Model_Validator", "Validator %1 was not registered")
112 .arg(aValidatorsIt->first).send();
114 theValidators.push_back(std::make_pair(aValidatorsIt->first, aValidatorsIt->second));
119 addDefaultAttributeValidators(theValidators);
122 Model_ValidatorsFactory::Model_ValidatorsFactory()
123 : ModelAPI_ValidatorsFactory()
125 registerValidator("Model_FeatureValidator", new Model_FeatureValidator);
126 registerValidator("Model_AttributeValidator", new Model_AttributeValidator);
129 const ModelAPI_Validator* Model_ValidatorsFactory::validator(const std::string& theID) const
131 std::map<std::string, ModelAPI_Validator*>::const_iterator aIt = myIDs.find(theID);
132 if (aIt != myIDs.end()) {
138 void Model_ValidatorsFactory::addDefaultValidators(Validators& theValidators) const
140 const static std::string kDefaultId = "Model_FeatureValidator";
141 if (!validator(kDefaultId))
143 theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
146 void Model_ValidatorsFactory::addDefaultAttributeValidators(Validators& theValidators) const
148 const static std::string kDefaultId = "Model_AttributeValidator";
149 if (!validator(kDefaultId))
151 theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
154 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Feature>& theFeature) const
156 std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theFeature->data());
157 if (aData.get() && aData->isValid()) {
158 if (aData->execState() == ModelAPI_StateDone)
159 aData->eraseErrorString(); // no error => erase the information string
161 return false; // feature is broken, already not presented in the data structure
164 // check feature validators first
165 Validators aValidators;
166 validators(theFeature->getKind(), aValidators);
168 if (!aValidators.empty()) {
169 Validators::const_iterator aValidatorIt = aValidators.cbegin();
170 for(; aValidatorIt != aValidators.cend(); aValidatorIt++) {
171 const std::string& aValidatorID = aValidatorIt->first;
172 const std::list<std::string>& anArguments = aValidatorIt->second;
173 // validators() checks invalid validator names
175 // Events_Error::send(std::string("Validator ") + aValidatorID + " was not registered");
178 const ModelAPI_FeatureValidator* aFValidator =
179 dynamic_cast<const ModelAPI_FeatureValidator*>(validator(aValidatorID));
181 Events_InfoMessage anError;
182 if (!aFValidator->isValid(theFeature, anArguments, anError)) {
184 anError = "Unknown error.";
185 anError = aValidatorID + ": " + anError.messageString();
186 theFeature->setError(anError.messageString(), false);
187 theFeature->data()->execState(ModelAPI_StateInvalidArgument);
193 // The default validator was retrned by validators() and was checked in previous cycle
194 //// check default validator
195 //std::map<std::string, ModelAPI_Validator*>::const_iterator aDefaultVal = myIDs.find(kDefaultId);
196 //if(aDefaultVal != myIDs.end()) {
197 // static const std::list<std::string> anEmptyArgList;
198 // const ModelAPI_FeatureValidator* aFValidator =
199 // dynamic_cast<const ModelAPI_FeatureValidator*>(aDefaultVal->second);
200 // if (aFValidator) {
201 // std::string anError;
202 // if (!aFValidator->isValid(theFeature, anEmptyArgList, anError)) {
203 // if (anError.empty())
204 // anError = "Unknown error.";
205 // anError = "Feature invalidated by \"" + kDefaultId + "\" with error: " + anError;
206 // theFeature->setError(anError, false);
207 // theFeature->data()->execState(ModelAPI_StateInvalidArgument);
213 // check all attributes for validity
214 // Validity of data is checked by "Model_FeatureValidator" (kDefaultId)
215 // if (!aData || !aData->isValid())
217 static const std::string kAllTypes = "";
218 std::list<std::string> aLtAttributes = aData->attributesIDs(kAllTypes);
219 std::list<std::string>::const_iterator anAttrIt = aLtAttributes.cbegin();
220 for (; anAttrIt != aLtAttributes.cend(); anAttrIt++) {
221 const std::string& anAttributeID = *anAttrIt;
222 AttributePtr anAttribute = theFeature->data()->attribute(anAttributeID);
224 std::string aValidatorID;
225 Events_InfoMessage anError;
226 if (!validate(anAttribute, aValidatorID, anError)) {
228 anError = "Unknown error.";
229 anError = anAttributeID + " - " + aValidatorID + ": " + anError.messageString();
230 theFeature->setError(anError.messageString(), false);
231 theFeature->data()->execState(ModelAPI_StateInvalidArgument);
239 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Attribute>& theAttribute,
240 std::string& theValidator,
241 Events_InfoMessage& theError) const
243 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
244 if (!aFeature.get()) {
245 theValidator = "Model_ValidatorsFactory";
246 theError = "Attribute has no feature.";
250 // skip not-case attributes, that really may be invalid (issue 671)
251 if (!const_cast<Model_ValidatorsFactory*>(this)->isCase(aFeature, theAttribute->id()))
254 Validators aValidators;
255 validators(aFeature->getKind(), theAttribute->id(), aValidators);
257 Validators::iterator aValidatorIt = aValidators.begin();
258 for (; aValidatorIt != aValidators.end(); ++aValidatorIt) {
259 const std::string& aValidatorID = aValidatorIt->first;
260 const std::list<std::string>& anArguments = aValidatorIt->second;
261 const ModelAPI_AttributeValidator* anAttrValidator =
262 dynamic_cast<const ModelAPI_AttributeValidator*>(validator(aValidatorID));
263 if (!anAttrValidator)
265 if (!anAttrValidator->isValid(theAttribute, anArguments, theError)) {
266 theValidator = aValidatorID;
274 void Model_ValidatorsFactory::registerNotObligatory(std::string theFeature, std::string theAttribute)
276 const static std::string kDefaultId = "Model_FeatureValidator";
277 std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
278 if (it != myIDs.end()) {
279 Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
281 aValidator->registerNotObligatory(theFeature, theAttribute);
286 bool Model_ValidatorsFactory::isNotObligatory(std::string theFeature, std::string theAttribute)
288 const static std::string kDefaultId = "Model_FeatureValidator";
289 std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
290 if (it != myIDs.end()) {
291 Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
293 return aValidator->isNotObligatory(theFeature, theAttribute);
296 return false; // default
299 void Model_ValidatorsFactory::registerConcealment(std::string theFeature, std::string theAttribute)
301 std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
302 if (aFind == myConcealed.end()) {
303 std::set<std::string> aNewSet;
304 aNewSet.insert(theAttribute);
305 myConcealed[theFeature] = aNewSet;
307 aFind->second.insert(theAttribute);
311 bool Model_ValidatorsFactory::isConcealed(std::string theFeature, std::string theAttribute)
313 std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
314 return aFind != myConcealed.end() && aFind->second.find(theAttribute) != aFind->second.end();
317 void Model_ValidatorsFactory::registerUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
318 std::shared_ptr<ModelAPI_Feature> theCanceledFeat)
320 if (myUnconcealed.find(theUnconcealed) == myUnconcealed.end()) {
321 myUnconcealed[theUnconcealed] = std::list<std::shared_ptr<ModelAPI_Feature> >();
323 myUnconcealed[theUnconcealed].push_back(theCanceledFeat);
324 std::dynamic_pointer_cast<Model_Data>(theUnconcealed->data())->updateConcealmentFlag();
327 void Model_ValidatorsFactory::disableUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
328 std::shared_ptr<ModelAPI_Feature> theCanceledFeat)
330 std::map<std::shared_ptr<ModelAPI_Result>, std::list<std::shared_ptr<ModelAPI_Feature> > >
331 ::iterator aResFound = myUnconcealed.find(theUnconcealed);
332 if (aResFound != myUnconcealed.end()) {
333 std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anIter = aResFound->second.begin();
334 for(; anIter != aResFound->second.end(); anIter++) {
335 if (*anIter == theCanceledFeat) {
336 aResFound->second.erase(anIter);
337 std::dynamic_pointer_cast<Model_Data>(theUnconcealed->data())->updateConcealmentFlag();
344 bool Model_ValidatorsFactory::isUnconcealed(std::shared_ptr<ModelAPI_Result> theUnconcealed,
345 std::shared_ptr<ModelAPI_Feature> theCanceledFeat)
347 std::map<std::shared_ptr<ModelAPI_Result>, std::list<std::shared_ptr<ModelAPI_Feature> > >
348 ::iterator aResFound = myUnconcealed.find(theUnconcealed);
349 if (aResFound != myUnconcealed.end()) {
350 std::list<std::shared_ptr<ModelAPI_Feature> >::iterator aFeatIter = aResFound->second.begin();
351 for(; aFeatIter != aResFound->second.end(); aFeatIter++) {
352 if (aFeatIter->get()) {
353 if ((*aFeatIter)->isDisabled()) continue;
354 if (*aFeatIter == theCanceledFeat)
355 return true; // this is exactly canceled
356 if (theCanceledFeat->document()->isLater(*aFeatIter, theCanceledFeat))
357 return true; // if unconcealed feature (from the list) is later than concealed
359 return true; // empty attribute means that everything is canceled
365 void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string theAttribute,
366 const std::list<std::pair<std::string, std::string> >& theCases)
368 std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
369 ::iterator aFindFeature = myCases.find(theFeature);
370 if (aFindFeature == myCases.end()) {
371 myCases[theFeature] = std::map<std::string, std::map<std::string, std::set<std::string> > >();
372 aFindFeature = myCases.find(theFeature);
374 std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator aFindAttrID =
375 aFindFeature->second.find(theAttribute);
377 if (aFindAttrID == aFindFeature->second.end()) {
378 aFindFeature->second[theAttribute] =
379 std::map<std::string, std::set<std::string> >();
380 aFindAttrID = aFindFeature->second.find(theAttribute);
382 std::list<std::pair<std::string, std::string> >::const_iterator aCasesIt = theCases.begin(),
383 aCasesLast = theCases.end();
384 std::map<std::string, std::set<std::string> > aFindCases = aFindAttrID->second;
385 for (; aCasesIt != aCasesLast; aCasesIt++) {
386 std::pair<std::string, std::string> aCasePair = *aCasesIt;
387 std::string aSwitch = aCasePair.first;
388 if (aFindAttrID->second.find(aSwitch) == aFindAttrID->second.end()) {
389 aFindAttrID->second[aSwitch] = std::set<std::string>();
391 aFindAttrID->second[aSwitch].insert(aCasePair.second);
395 bool Model_ValidatorsFactory::isCase(FeaturePtr theFeature, std::string theAttribute)
397 bool anInCase = true;
398 std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
399 ::iterator aFindFeature = myCases.find(theFeature->getKind());
400 if (aFindFeature != myCases.end()) {
401 std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator
402 aFindAttrID = aFindFeature->second.find(theAttribute);
403 if (aFindAttrID != aFindFeature->second.end()) {
404 std::map<std::string, std::set<std::string> >::iterator
405 aCasesIt = aFindAttrID->second.begin(), aCasesLast = aFindAttrID->second.end();
406 for (; aCasesIt != aCasesLast && anInCase; aCasesIt++) {
407 // the the switch-attribute that contains the case value
408 AttributeStringPtr aSwitch = theFeature->string(aCasesIt->first);
410 // the second has the case identifier
411 anInCase = aCasesIt->second.find(aSwitch->value()) != aCasesIt->second.end();
416 return anInCase; // if no additional conditions, this attribute is the case to be validated