Salome HOME
d34681a13a2c5c9e4a7115d8c72ab9d5478ad282
[modules/shaper.git] / src / Model / Model_Validator.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        Model_Validator.cpp
4 // Created:     2 Jul 2014
5 // Author:      Mikhail PONIKAROV
6
7 #include "Model_Validator.h"
8
9 #include "Model_AttributeValidator.h"
10 #include "Model_FeatureValidator.h"
11
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>
18
19 #include <Events_InfoMessage.h>
20
21 void Model_ValidatorsFactory::registerValidator(const std::string& theID,
22   ModelAPI_Validator* theValidator)
23 {
24   if (myIDs.find(theID) != myIDs.end()) {
25     Events_InfoMessage("Model_Validator", "Validator %1 is already registered").arg(theID).send();
26   } else {
27     myIDs[theID] = theValidator;
28   }
29 }
30
31 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
32   const std::string& theFeatureID)
33 {
34   if (myFeatures.find(theFeatureID) == myFeatures.end()) {
35     myFeatures[theFeatureID] = AttrValidators();
36   }
37   if (myFeatures[theFeatureID].find(theID) != myFeatures[theFeatureID].end()) {
38     //Events_Error::send(std::string("Validator ") + theID +
39     //  " for feature " + theFeatureID + "is already registered");
40   } else {
41     myFeatures[theFeatureID][theID] = std::list<std::string>();
42   }
43 }
44
45 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
46   const std::string& theFeatureID,
47   const std::list<std::string>& theArguments)
48 {
49   if (myFeatures.find(theFeatureID) == myFeatures.end()) {
50     myFeatures[theFeatureID] = AttrValidators();
51   }
52
53   if (myFeatures[theFeatureID].find(theID) != myFeatures[theFeatureID].end()) {
54     //Events_Error::send(std::string("Validator ") + theID +
55     //  " for feature " + theFeatureID + "is already registered");
56   } else {
57     myFeatures[theFeatureID][theID] = theArguments;
58   }
59 }
60
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)
65 {
66   // create feature-structures if not exist
67   std::map<std::string, std::map<std::string, AttrValidators> >::iterator aFeature = myAttrs.find(
68     theFeatureID);
69   if (aFeature == myAttrs.end()) {
70     myAttrs[theFeatureID] = std::map<std::string, AttrValidators>();
71     aFeature = myAttrs.find(theFeatureID);
72   }
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();
77   }
78   aFeature->second[theAttrID][theID] = theArguments;
79 }
80
81 void Model_ValidatorsFactory::validators(const std::string& theFeatureID,
82                                          Validators& theValidators) const
83 {
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();
92       } else {
93         theValidators.push_back(std::make_pair(aValidatorsIt->first, aValidatorsIt->second));
94       }
95     }
96   }
97   addDefaultValidators(theValidators);
98 }
99
100 void Model_ValidatorsFactory::validators(const std::string& theFeatureID,
101                                          const std::string& theAttrID,
102                                          Validators& theValidators) const
103 {
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();
115         } else {
116           theValidators.push_back(std::make_pair(aValidatorsIt->first, aValidatorsIt->second));
117         }
118       }
119     }
120   }
121   addDefaultAttributeValidators(theValidators);
122 }
123
124 Model_ValidatorsFactory::Model_ValidatorsFactory()
125   : ModelAPI_ValidatorsFactory()
126 {
127   registerValidator("Model_FeatureValidator", new Model_FeatureValidator);
128   registerValidator("Model_AttributeValidator", new Model_AttributeValidator);
129 }
130
131 const ModelAPI_Validator* Model_ValidatorsFactory::validator(const std::string& theID) const
132 {
133   std::map<std::string, ModelAPI_Validator*>::const_iterator aIt = myIDs.find(theID);
134   if (aIt != myIDs.end()) {
135     return aIt->second;
136   }
137   return NULL;
138 }
139
140 void Model_ValidatorsFactory::addDefaultValidators(Validators& theValidators) const
141 {
142   const static std::string kDefaultId = "Model_FeatureValidator";
143   if (!validator(kDefaultId))
144     return;
145   theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
146 }
147
148 void Model_ValidatorsFactory::addDefaultAttributeValidators(Validators& theValidators) const
149 {
150   const static std::string kDefaultId = "Model_AttributeValidator";
151   if (!validator(kDefaultId))
152     return;
153   theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
154 }
155
156 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Feature>& theFeature) const
157 {
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
162   } else {
163     return false; // feature is broken, already not presented in the data structure
164   }
165
166   // check feature validators first
167   Validators aValidators;
168   validators(theFeature->getKind(), aValidators);
169
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
176       //if (!aValidator) {
177       //  Events_Error::send(std::string("Validator ") + aValidatorID + " was not registered");
178       //  continue;
179       //}
180       const ModelAPI_FeatureValidator* aFValidator =
181         dynamic_cast<const ModelAPI_FeatureValidator*>(validator(aValidatorID));
182       if (aFValidator) {
183         Events_InfoMessage anError;
184         if (!aFValidator->isValid(theFeature, anArguments, anError)) {
185           if (anError.empty())
186             anError = "Unknown error.";
187           anError = aValidatorID + ": " + anError.messageString();
188           theFeature->setError(anError.messageString(), false);
189           theFeature->data()->execState(ModelAPI_StateInvalidArgument);
190           return false;
191         }
192       }
193     }
194   }
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);
210   //      return false;
211   //    }
212   //  }
213   //}
214
215   // check all attributes for validity
216   // Validity of data is checked by "Model_FeatureValidator" (kDefaultId)
217   // if (!aData || !aData->isValid())
218   //   return false;
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);
225
226     std::string aValidatorID;
227     Events_InfoMessage anError;
228     if (!validate(anAttribute, aValidatorID, anError)) {
229       if (anError.empty())
230         anError = "Unknown error.";
231       anError = anAttributeID + " - " + aValidatorID + ": " + anError.messageString();
232       theFeature->setError(anError.messageString(), false);
233       theFeature->data()->execState(ModelAPI_StateInvalidArgument);
234       return false;
235     }
236   }
237
238   return true;
239 }
240
241 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Attribute>& theAttribute,
242                                        std::string& theValidator,
243                                        Events_InfoMessage& theError) const
244 {
245   FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
246   if (!aFeature.get()) {
247     theValidator = "Model_ValidatorsFactory";
248     theError = "Attribute has no feature.";
249     return false;
250   }
251
252   // skip not-case attributes, that really may be invalid (issue 671)
253   if (!const_cast<Model_ValidatorsFactory*>(this)->isCase(aFeature, theAttribute->id()))
254     return true;
255
256   Validators aValidators;
257   validators(aFeature->getKind(), theAttribute->id(), aValidators);
258
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)
266       continue;
267     if (!anAttrValidator->isValid(theAttribute, anArguments, theError)) {
268       theValidator = aValidatorID;
269       return false;
270     }
271   }
272
273   return true;
274 }
275
276 void Model_ValidatorsFactory::registerNotObligatory(std::string theFeature,
277                                                     std::string theAttribute)
278 {
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);
283     if (aValidator) {
284       aValidator->registerNotObligatory(theFeature, theAttribute);
285     }
286   }
287 }
288
289 bool Model_ValidatorsFactory::isNotObligatory(std::string theFeature, std::string theAttribute)
290 {
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);
295     if (aValidator) {
296       return aValidator->isNotObligatory(theFeature, theAttribute);
297     }
298   }
299   return false; // default
300 }
301
302 void Model_ValidatorsFactory::registerConcealment(std::string theFeature, std::string theAttribute)
303 {
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;
309   } else {
310     aFind->second.insert(theAttribute);
311   }
312 }
313
314 bool Model_ValidatorsFactory::isConcealed(std::string theFeature, std::string theAttribute)
315 {
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();
318 }
319
320 void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string theAttribute,
321                             const std::list<std::pair<std::string, std::string> >& theCases)
322 {
323   std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
324     ::iterator aFindFeature = myCases.find(theFeature);
325   if (aFindFeature == myCases.end()) {
326     myCases[theFeature] = std::map<std::string, std::map<std::string, std::set<std::string> > >();
327     aFindFeature = myCases.find(theFeature);
328   }
329   std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator aFindAttrID =
330     aFindFeature->second.find(theAttribute);
331
332   if (aFindAttrID == aFindFeature->second.end()) {
333     aFindFeature->second[theAttribute] =
334       std::map<std::string, std::set<std::string> >();
335     aFindAttrID = aFindFeature->second.find(theAttribute);
336   }
337   std::list<std::pair<std::string, std::string> >::const_iterator aCasesIt = theCases.begin(),
338                                                                        aCasesLast = theCases.end();
339   std::map<std::string, std::set<std::string> > aFindCases = aFindAttrID->second;
340   for (; aCasesIt != aCasesLast; aCasesIt++) {
341     std::pair<std::string, std::string> aCasePair = *aCasesIt;
342     std::string aSwitch = aCasePair.first;
343     if (aFindAttrID->second.find(aSwitch) == aFindAttrID->second.end()) {
344       aFindAttrID->second[aSwitch] = std::set<std::string>();
345     }
346     aFindAttrID->second[aSwitch].insert(aCasePair.second);
347   }
348 }
349
350 bool Model_ValidatorsFactory::isCase(FeaturePtr theFeature, std::string theAttribute)
351 {
352   bool anInCase = true;
353   std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
354     ::iterator aFindFeature = myCases.find(theFeature->getKind());
355   if (aFindFeature != myCases.end()) {
356     std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator
357       aFindAttrID = aFindFeature->second.find(theAttribute);
358     if (aFindAttrID != aFindFeature->second.end()) {
359       std::map<std::string, std::set<std::string> >::iterator
360               aCasesIt = aFindAttrID->second.begin(), aCasesLast = aFindAttrID->second.end();
361       for (; aCasesIt != aCasesLast && anInCase; aCasesIt++) {
362         // the the switch-attribute that contains the case value
363         AttributeStringPtr aSwitch = theFeature->string(aCasesIt->first);
364         if (aSwitch.get()) {
365           // the second has the case identifier
366           anInCase =  aCasesIt->second.find(aSwitch->value()) != aCasesIt->second.end();
367         }
368       }
369     }
370   }
371   return anInCase; // if no additional conditions, this attribute is the case to be validated
372 }