Salome HOME
41fa0f7014a03e24137734cbd4bc447925905271
[modules/shaper.git] / src / Model / Model_Validator.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "Model_Validator.h"
22
23 #include "Model_AttributeValidator.h"
24 #include "Model_FeatureValidator.h"
25
26 #include <ModelAPI_Attribute.h>
27 #include <ModelAPI_AttributeString.h>
28 #include <ModelAPI_AttributeValidator.h>
29 #include <ModelAPI_Feature.h>
30 #include <ModelAPI_Result.h>
31 #include <Model_Data.h>
32
33 #include <Config_Translator.h>
34
35 #include <Events_InfoMessage.h>
36
37 void Model_ValidatorsFactory::registerValidator(const std::string& theID,
38   ModelAPI_Validator* theValidator)
39 {
40   if (myIDs.find(theID) != myIDs.end()) {
41     Events_InfoMessage("Model_Validator", "Validator %1 is already registered").arg(theID).send();
42   } else {
43     myIDs[theID] = theValidator;
44   }
45 }
46
47 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
48   const std::string& theFeatureID)
49 {
50   if (myFeatures.find(theFeatureID) == myFeatures.end()) {
51     myFeatures[theFeatureID] = AttrValidators();
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] = std::list<std::string>();
58   }
59 }
60
61 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
62   const std::string& theFeatureID,
63   const std::list<std::string>& theArguments)
64 {
65   if (myFeatures.find(theFeatureID) == myFeatures.end()) {
66     myFeatures[theFeatureID] = AttrValidators();
67   }
68
69   if (myFeatures[theFeatureID].find(theID) != myFeatures[theFeatureID].end()) {
70     //Events_Error::send(std::string("Validator ") + theID +
71     //  " for feature " + theFeatureID + "is already registered");
72   } else {
73     myFeatures[theFeatureID][theID] = theArguments;
74   }
75 }
76
77 void Model_ValidatorsFactory::assignValidator(const std::string& theID,
78   const std::string& theFeatureID,
79   const std::string& theAttrID,
80   const std::list<std::string>& theArguments)
81 {
82   // create feature-structures if not exist
83   std::map<std::string, std::map<std::string, AttrValidators> >::iterator aFeature = myAttrs.find(
84     theFeatureID);
85   if (aFeature == myAttrs.end()) {
86     myAttrs[theFeatureID] = std::map<std::string, AttrValidators>();
87     aFeature = myAttrs.find(theFeatureID);
88   }
89   // add attr-structure if not exist, or generate error if already exist
90   std::map<std::string, AttrValidators>::iterator anAttr = aFeature->second.find(theAttrID);
91   if (anAttr == aFeature->second.end()) {
92     aFeature->second[theAttrID] = AttrValidators();
93   }
94   aFeature->second[theAttrID][theID] = theArguments;
95 }
96
97 void Model_ValidatorsFactory::validators(const std::string& theFeatureID,
98                                          Validators& theValidators) const
99 {
100   std::map<std::string, AttrValidators>::const_iterator aFeatureIt =
101       myFeatures.find(theFeatureID);
102   if (aFeatureIt != myFeatures.cend()) {
103     AttrValidators::const_iterator aValidatorsIt = aFeatureIt->second.cbegin();
104     for (; aValidatorsIt != aFeatureIt->second.cend(); aValidatorsIt++) {
105       if (!validator(aValidatorsIt->first)) {
106         Events_InfoMessage("Model_Validator", "Validator %1 was not registered")
107           .arg(aValidatorsIt->first).send();
108       } else {
109         theValidators.push_back(std::make_pair(aValidatorsIt->first, aValidatorsIt->second));
110       }
111     }
112   }
113   addDefaultValidators(theValidators);
114 }
115
116 void Model_ValidatorsFactory::validators(const std::string& theFeatureID,
117                                          const std::string& theAttrID,
118                                          Validators& theValidators) const
119 {
120   std::map<std::string, std::map<std::string, AttrValidators> >::const_iterator aFeatureIt =
121       myAttrs.find(theFeatureID);
122   if (aFeatureIt != myAttrs.cend()) {
123     std::map<std::string, AttrValidators>::const_iterator anAttrIt =
124       aFeatureIt->second.find(theAttrID);
125     if (anAttrIt != aFeatureIt->second.end()) {
126       AttrValidators::const_iterator aValidatorsIt = anAttrIt->second.cbegin();
127       for (; aValidatorsIt != anAttrIt->second.cend(); aValidatorsIt++) {
128         if (!validator(aValidatorsIt->first)) {
129           Events_InfoMessage("Model_Validator", "Validator %1 was not registered")
130             .arg(aValidatorsIt->first).send();
131         } else {
132           theValidators.push_back(std::make_pair(aValidatorsIt->first, aValidatorsIt->second));
133         }
134       }
135     }
136   }
137   addDefaultAttributeValidators(theValidators);
138 }
139
140 Model_ValidatorsFactory::Model_ValidatorsFactory()
141   : ModelAPI_ValidatorsFactory()
142 {
143   registerValidator("Model_FeatureValidator", new Model_FeatureValidator);
144   registerValidator("Model_AttributeValidator", new Model_AttributeValidator);
145 }
146
147 const ModelAPI_Validator* Model_ValidatorsFactory::validator(const std::string& theID) const
148 {
149   std::map<std::string, ModelAPI_Validator*>::const_iterator aIt = myIDs.find(theID);
150   if (aIt != myIDs.end()) {
151     return aIt->second;
152   }
153   return NULL;
154 }
155
156 void Model_ValidatorsFactory::addDefaultValidators(Validators& theValidators) const
157 {
158   const static std::string kDefaultId = "Model_FeatureValidator";
159   if (!validator(kDefaultId))
160     return;
161   theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
162 }
163
164 void Model_ValidatorsFactory::addDefaultAttributeValidators(Validators& theValidators) const
165 {
166   const static std::string kDefaultId = "Model_AttributeValidator";
167   if (!validator(kDefaultId))
168     return;
169   theValidators.push_back(std::make_pair(kDefaultId, std::list<std::string>()));
170 }
171
172 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Feature>& theFeature) const
173 {
174   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theFeature->data());
175   if (aData.get() && aData->isValid()) {
176     if (aData->execState() == ModelAPI_StateDone)
177       aData->eraseErrorString(); // no error => erase the information string
178   } else {
179     return false; // feature is broken, already not presented in the data structure
180   }
181
182   // check feature validators first
183   Validators aValidators;
184   validators(theFeature->getKind(), aValidators);
185
186   if (!aValidators.empty()) {
187     Validators::const_iterator aValidatorIt = aValidators.cbegin();
188     for(; aValidatorIt != aValidators.cend(); aValidatorIt++) {
189       const std::string& aValidatorID = aValidatorIt->first;
190       const std::list<std::string>& anArguments = aValidatorIt->second;
191       const ModelAPI_FeatureValidator* aFValidator =
192         dynamic_cast<const ModelAPI_FeatureValidator*>(validator(aValidatorID));
193       if (aFValidator) {
194         Events_InfoMessage anError;
195         if (!aFValidator->isValid(theFeature, anArguments, anError)) {
196           if (anError.empty())
197             anError = "Unknown error.";
198           if (anError.context().empty()) {
199             anError.setContext(theFeature->getKind() + ":" + aValidatorID);
200           }
201           theFeature->setError(Config_Translator::translate(anError), false, false);
202           theFeature->data()->execState(ModelAPI_StateInvalidArgument);
203           return false;
204         }
205       }
206     }
207   }
208
209   // check all attributes for validity
210   static const std::string kAllTypes = "";
211   std::list<std::string> aLtAttributes = aData->attributesIDs(kAllTypes);
212   std::list<std::string>::const_iterator anAttrIt = aLtAttributes.cbegin();
213   for (; anAttrIt != aLtAttributes.cend(); anAttrIt++) {
214     const std::string& anAttributeID = *anAttrIt;
215     AttributePtr anAttribute = theFeature->data()->attribute(anAttributeID);
216
217     std::string aValidatorID;
218     Events_InfoMessage anError;
219     if (!validate(anAttribute, aValidatorID, anError)) {
220       if (anError.empty())
221         anError = "Unknown error.";
222       if (anError.context().empty()) {
223         anError.setContext(theFeature->getKind() + ":" + anAttributeID + ":" + aValidatorID);
224       }
225       theFeature->setError(Config_Translator::translate(anError), false, false);
226       theFeature->data()->execState(ModelAPI_StateInvalidArgument);
227       return false;
228     }
229   }
230
231   return true;
232 }
233
234 bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Attribute>& theAttribute,
235                                        std::string& theValidator,
236                                        Events_InfoMessage& theError) const
237 {
238   FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
239   if (!aFeature.get()) {
240     theValidator = "Model_ValidatorsFactory";
241     theError = "Attribute has no feature.";
242     return false;
243   }
244
245   // skip not-case attributes, that really may be invalid (issue 671)
246   if (!const_cast<Model_ValidatorsFactory*>(this)->isCase(aFeature, theAttribute->id()))
247     return true;
248
249   Validators aValidators;
250   validators(aFeature->getKind(), theAttribute->id(), aValidators);
251
252   Validators::iterator aValidatorIt = aValidators.begin();
253   for (; aValidatorIt != aValidators.end(); ++aValidatorIt) {
254     const std::string& aValidatorID = aValidatorIt->first;
255     const std::list<std::string>& anArguments = aValidatorIt->second;
256     const ModelAPI_AttributeValidator* anAttrValidator =
257         dynamic_cast<const ModelAPI_AttributeValidator*>(validator(aValidatorID));
258     if (!anAttrValidator)
259       continue;
260     if (!anAttrValidator->isValid(theAttribute, anArguments, theError)) {
261       theValidator = aValidatorID;
262       return false;
263     }
264   }
265
266   return true;
267 }
268
269 void Model_ValidatorsFactory::registerNotObligatory(std::string theFeature,
270                                                     std::string theAttribute)
271 {
272   const static std::string kDefaultId = "Model_FeatureValidator";
273   std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
274   if (it != myIDs.end()) {
275     Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
276     if (aValidator) {
277       aValidator->registerNotObligatory(theFeature, theAttribute);
278     }
279   }
280 }
281
282 bool Model_ValidatorsFactory::isNotObligatory(std::string theFeature, std::string theAttribute)
283 {
284   const static std::string kDefaultId = "Model_FeatureValidator";
285   std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
286   if (it != myIDs.end()) {
287     Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
288     if (aValidator) {
289       return aValidator->isNotObligatory(theFeature, theAttribute);
290     }
291   }
292   return false; // default
293 }
294
295 void Model_ValidatorsFactory::registerConcealment(std::string theFeature, std::string theAttribute)
296 {
297   std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
298   if (aFind == myConcealed.end()) {
299     std::set<std::string> aNewSet;
300     aNewSet.insert(theAttribute);
301     myConcealed[theFeature] = aNewSet;
302   } else {
303     aFind->second.insert(theAttribute);
304   }
305 }
306
307 bool Model_ValidatorsFactory::isConcealed(std::string theFeature, std::string theAttribute)
308 {
309   std::map<std::string, std::set<std::string> >::iterator aFind = myConcealed.find(theFeature);
310   return aFind != myConcealed.end() && aFind->second.find(theAttribute) != aFind->second.end();
311 }
312
313 void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string theAttribute,
314                             const std::list<std::pair<std::string, std::string> >& theCases)
315 {
316   std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
317     ::iterator aFindFeature = myCases.find(theFeature);
318   if (aFindFeature == myCases.end()) {
319     myCases[theFeature] = std::map<std::string, std::map<std::string, std::set<std::string> > >();
320     aFindFeature = myCases.find(theFeature);
321   }
322   std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator aFindAttrID =
323     aFindFeature->second.find(theAttribute);
324
325   if (aFindAttrID == aFindFeature->second.end()) {
326     aFindFeature->second[theAttribute] =
327       std::map<std::string, std::set<std::string> >();
328     aFindAttrID = aFindFeature->second.find(theAttribute);
329   }
330   std::list<std::pair<std::string, std::string> >::const_iterator aCasesIt = theCases.begin(),
331                                                                        aCasesLast = theCases.end();
332   std::map<std::string, std::set<std::string> > aFindCases = aFindAttrID->second;
333   for (; aCasesIt != aCasesLast; aCasesIt++) {
334     std::pair<std::string, std::string> aCasePair = *aCasesIt;
335     std::string aSwitch = aCasePair.first;
336     if (aFindAttrID->second.find(aSwitch) == aFindAttrID->second.end()) {
337       aFindAttrID->second[aSwitch] = std::set<std::string>();
338     }
339     aFindAttrID->second[aSwitch].insert(aCasePair.second);
340   }
341 }
342
343 bool Model_ValidatorsFactory::isCase(FeaturePtr theFeature, std::string theAttribute)
344 {
345   bool anInCase = true;
346   std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
347     ::iterator aFindFeature = myCases.find(theFeature->getKind());
348   if (aFindFeature != myCases.end()) {
349     std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator
350       aFindAttrID = aFindFeature->second.find(theAttribute);
351     if (aFindAttrID != aFindFeature->second.end()) {
352       std::map<std::string, std::set<std::string> >::iterator
353               aCasesIt = aFindAttrID->second.begin(), aCasesLast = aFindAttrID->second.end();
354       for (; aCasesIt != aCasesLast && anInCase; aCasesIt++) {
355         // the the switch-attribute that contains the case value
356         AttributeStringPtr aSwitch = theFeature->string(aCasesIt->first);
357         if (aSwitch.get()) {
358           // the second has the case identifier
359           anInCase =  aCasesIt->second.find(aSwitch->value()) != aCasesIt->second.end();
360         }
361       }
362     }
363   }
364   return anInCase; // if no additional conditions, this attribute is the case to be validated
365 }
366
367 void Model_ValidatorsFactory::registerMainArgument(std::string theFeature,
368                                                    std::string theAttribute)
369 {
370   std::map<std::string, std::string>::iterator aFound = myMainArgument.find(theFeature);
371   if (aFound == myMainArgument.end())
372     myMainArgument[theFeature] = theAttribute;
373 }
374
375 bool Model_ValidatorsFactory::isMainArgument(std::string theFeature, std::string theAttribute)
376 {
377   std::map<std::string, std::string>::iterator aFound = myMainArgument.find(theFeature);
378   return aFound != myMainArgument.end() && aFound->second == theAttribute;
379 }