]> SALOME platform Git repositories - modules/shaper.git/blob - src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
Salome HOME
Issue #1837: make all files with UNIX end lines
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Validators.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        FeaturesPlugin_Validators.cpp
4 // Created:     22 March 2016
5 // Author:      Dmitry Bobylev
6
7 #include "FeaturesPlugin_Validators.h"
8
9 #include "FeaturesPlugin_Union.h"
10
11 #include <Events_InfoMessage.h>
12
13 #include <ModelAPI_Attribute.h>
14 #include <ModelAPI_AttributeInteger.h>
15 #include <ModelAPI_AttributeSelectionList.h>
16 #include <ModelAPI_AttributeString.h>
17 #include <ModelAPI_AttributeReference.h>
18 #include <ModelAPI_AttributeRefList.h>
19 #include <ModelAPI_Feature.h>
20 #include <ModelAPI_ResultCompSolid.h>
21 #include <ModelAPI_ResultConstruction.h>
22 #include <ModelAPI_Tools.h>
23
24 #include <GeomValidators_BodyShapes.h>
25 #include <GeomValidators_FeatureKind.h>
26 #include <GeomValidators_ShapeType.h>
27
28 #include <GeomAPI_DataMapOfShapeShape.h>
29 #include <GeomAPI_Lin.h>
30 #include <GeomAPI_PlanarEdges.h>
31 #include <GeomAPI_ShapeExplorer.h>
32 #include <GeomAPI_ShapeIterator.h>
33
34 #include <GeomAlgoAPI_CompoundBuilder.h>
35 #include <GeomAlgoAPI_ShapeBuilder.h>
36 #include <GeomAlgoAPI_ShapeTools.h>
37 #include <GeomAlgoAPI_WireBuilder.h>
38
39 #define _USE_MATH_DEFINES
40 #include <math.h>
41
42 //==================================================================================================
43 bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,
44                                                const std::list<std::string>& theArguments,
45                                                Events_InfoMessage& theError) const
46 {
47   AttributeSelectionPtr aPathAttrSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
48   if(!aPathAttrSelection.get()) {
49     theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";
50     return false;
51   }
52
53   GeomShapePtr aPathShape = aPathAttrSelection->value();
54   ResultPtr aContext = aPathAttrSelection->context();
55   if(!aContext.get()) {
56     theError = "Error: Empty context.";
57     return false;
58   }
59   GeomShapePtr aContextShape = aContext->shape();
60   if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE && !aPathShape->isEqual(aContextShape)) {
61     theError = "Error: Local selection of wires not allowed.";
62     return false;
63   }
64
65   return true;
66 }
67
68 //==================================================================================================
69 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
70                                                     const std::list<std::string>& theArguments,
71                                                     Events_InfoMessage& theError) const
72 {
73   static const std::string aCreationMethodID = "creation_method";
74   static const std::string aBaseObjectsID = "base_objects";
75   static const std::string aLocationsID = "locations_objects";
76
77   if(theFeature->getKind() != "Pipe") {
78     theError = "Error: Feature \"%1\" does not supported by this validator.";
79     theError.arg(theFeature->getKind());
80     return false;
81   }
82
83   AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
84   if(!aCreationMethodAttr.get()) {
85     theError = "Error: Could not get \"%1\" attribute.";
86     theError.arg(aCreationMethodID);
87     return false;
88   }
89
90   if(aCreationMethodAttr->value() != "locations") {
91     return true;
92   }
93
94   AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
95   if(!aBaseObjectsSelectionList.get()) {
96     theError = "Error: Could not get \"%1\" attribute.";
97     theError.arg(aBaseObjectsID);
98     return false;
99   }
100
101   AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
102   if(!aLocationsSelectionList.get()) {
103     theError = "Error: Could not get \"%1\" attribute.";
104     theError.arg(aBaseObjectsID);
105     return false;
106   }
107
108   if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
109     theError = "Error: Number of locations should be the same as base objects.";
110     return false;
111   }
112
113   return true;
114 }
115
116 //==================================================================================================
117 bool FeaturesPlugin_ValidatorPipeLocations::isNotObligatory(std::string theFeature, std::string theAttribute)
118 {
119   return false;
120 }
121
122 //==================================================================================================
123 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
124                                                         const std::list<std::string>& theArguments,
125                                                         Events_InfoMessage& theError) const
126 {
127   if(theArguments.empty()) {
128     theError = "Error: Validator parameters is empty.";
129     return false;
130   }
131
132   // Checking attribute.
133   if(!isValidAttribute(theAttribute, theArguments, theError)) {
134     if(theError.empty()) {
135       theError = "Error: Attribute contains unacceptable shape.";
136     }
137     return false;
138   }
139
140   std::set<ResultConstructionPtr> aSelectedSketches;
141   std::set<ResultConstructionPtr> aSelectedSketchesFromObjects;
142   GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects;
143   std::string anAttributeType = theAttribute->attributeType();
144   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
145     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
146     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
147       AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
148       ResultPtr aContext = aSelectionAttr->context();
149       if(!aContext.get()) {
150         theError = "Error: Empty context.";
151         return false;
152       }
153
154       ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
155       if(!aResultConstruction.get()) {
156         // It is not a result construction. If shape is compound check that it contains only faces and edges.
157         GeomShapePtr aShape = aSelectionAttr->value();
158         if(!aShape.get()) {
159           aShape = aContext->shape();
160         }
161
162         if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
163           for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
164             GeomShapePtr aSubShape = anIt.current();
165             if(aSubShape->shapeType() != GeomAPI_Shape::EDGE
166                 && aSubShape->shapeType() != GeomAPI_Shape::FACE) {
167               theError = "Error: Compound should contain only faces and edges.";
168               return false;
169             }
170           }
171         }
172
173         continue;
174       }
175
176       GeomShapePtr aShape = aSelectionAttr->value();
177       GeomShapePtr aContextShape = aResultConstruction->shape();
178       if(!aShape.get()) {
179         // Whole sketch selected.
180         if(aSelectedSketchesFromObjects.find(aResultConstruction) != aSelectedSketchesFromObjects.cend()) {
181           theError = "Error: Object from this sketch is already selected. Sketch is not allowed for selection.";
182           return false;
183         }
184
185         aSelectedSketches.insert(aResultConstruction);
186       } else {
187         // Object from sketch selected.
188         if(aSelectedSketches.find(aResultConstruction) != aSelectedSketches.cend()) {
189           theError = "Error: Whole sketch with this object is already selected. Don't allow to select this object.";
190           return false;
191         }
192
193         for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
194           GeomShapePtr aWire = anExp.current();
195           if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
196             theError = "Error: Wire with wrong orientation selected.";
197             return false;
198           }
199
200           if(aSelectedWiresFromObjects.isBound(aWire)) {
201             theError = "Error: Objects with such wire already selected. Don't allow to select this object.";
202             return false;
203           }
204
205           aSelectedWiresFromObjects.bind(aWire, aWire);
206           aSelectedSketchesFromObjects.insert(aResultConstruction);
207         }
208       }
209     }
210   }
211
212   return true;
213 }
214
215 //==================================================================================================
216 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
217                                                                  const std::list<std::string>& theArguments,
218                                                                  Events_InfoMessage& theError) const
219 {
220   if(!theAttribute.get()) {
221     theError = "Error: Empty attribute.";
222     return false;
223   }
224
225   std::string anAttributeType = theAttribute->attributeType();
226   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
227     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
228     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
229       // If at least one attribute is invalid, the result is false.
230       if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) {
231         return false;
232       }
233     }
234   } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
235     // Getting context.
236     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
237     ResultPtr aContext = anAttr->context();
238     if(!aContext.get()) {
239       theError = "Error: Attribute have empty context.";
240       return false;
241     }
242
243     GeomShapePtr aShape = anAttr->value();
244     GeomShapePtr aContextShape = aContext->shape();
245     if(!aShape.get()) {
246       aShape = aContextShape;
247     }
248     if(!aShape.get()) {
249       theError = "Error: Empty shape selected";
250       return false;
251     }
252
253     ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
254     if(aConstruction.get()) {
255       // Construciotn selected. Check that is is not infinite.
256       if(aConstruction->isInfinite()) {
257         theError = "Error: Infinite constructions is not allowed as base.";
258         return false;
259       }
260
261       if(aShape->isEqual(aContextShape)) {
262         // Whole construction selected. Check that it have faces.
263         if(aConstruction->facesNum() > 0) {
264           return true;
265         }
266       } else {
267         // Shape on construction selected. Check that it is a face or wire.
268         if(aShape->shapeType() == GeomAPI_Shape::WIRE || aShape->shapeType() == GeomAPI_Shape::FACE) {
269           return true;
270         }
271       }
272
273       return false;
274     }
275
276     if(!aShape->isEqual(aContextShape)) {
277       // Local selection on body does not allowed.
278       theError = "Error: Selected shape is in the local selection. Only global selection is allowed.";
279       return false;
280     }
281
282     // Check that object is a shape with allowed type.
283     GeomValidators_ShapeType aShapeTypeValidator;
284     if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
285       theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch(if it has at least one face), and whole objects with shape types: %1";
286       std::string anArgumentString;
287       for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) {
288         if (!anArgumentString.empty())
289           anArgumentString += ", ";
290         anArgumentString += *anIt;
291       }
292       theError.arg(anArgumentString);
293       return false;
294     }
295
296   } else {
297     theError = "Error: Attribute \"%1\" does not supported by this validator.";
298     theError.arg(anAttributeType);
299     return false;
300   }
301
302   return true;
303 }
304
305 //==================================================================================================
306 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,
307                                                         const std::list<std::string>& theArguments,
308                                                         Events_InfoMessage& theError) const
309 {
310   if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
311     theError = "Error: The attribute with the %1 type is not processed";
312     theError.arg(theAttribute->attributeType());
313     return false;
314   }
315   if (theArguments.size() != 2) {
316     theError = "Error: Wrong parameters in XML definition for %1 type";
317     theError.arg(theAttribute->attributeType());
318     return false;
319   }
320   // first argument is for the base attribute, second - for skipping feature kind
321   std::list<std::string>::const_iterator anIt = theArguments.begin();
322   std::string aBaseAttributeId = *anIt;
323   FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
324   AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId);
325   if (!aBaseAttribute.get()) {
326     theError = "Wrong parameters in XML definition for %1 type";
327     theError.arg(theAttribute->attributeType());
328     return false;
329   }
330   if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,
331     // this validator is not necessary anymore
332     return true;
333
334   anIt++;
335   std::string aFeatureAttributeKind = *anIt;
336   GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();
337   // check whether the selection is on the sketch
338   std::list<std::string> anArguments;
339   anArguments.push_back(aFeatureAttributeKind);
340
341   bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError);
342   bool aPlanarFace = false;
343   // check if selection has Face selected
344   GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();
345   anArguments.clear();
346   anArguments.push_back("face");
347   aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);
348
349   bool aValid = !aFeatureKind && aPlanarFace;
350   return aValid;
351 }
352
353 //==================================================================================================
354 bool FeaturesPlugin_ValidatorExtrusionDir::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
355                                                  const std::list<std::string>& theArguments,
356                                                  Events_InfoMessage& theError) const
357 {
358   if(theArguments.size() != 2) {
359     theError = "Error: Validator should be used with 2 parameters for extrusion.";
360     return false;
361   }
362
363   std::list<std::string>::const_iterator anArgsIt = theArguments.begin(), aLast = theArguments.end();
364
365   AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
366   ++anArgsIt;
367
368   GeomShapePtr aDirShape;
369   AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
370   if(aSelAttr.get()) {
371     aDirShape = aSelAttr->value();
372     if(!aDirShape.get()) {
373       ResultPtr aContext = aSelAttr->context();
374       if(aContext.get()) {
375         aDirShape = aContext->shape();
376       }
377     }
378   }
379
380   if(!aDirShape.get()) {
381     // Check that dir can be empty.
382     if(!isShapesCanBeEmpty(aCheckAttribute, theError)) {
383       theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" can not be used with default value. Select direction for extrusion.";
384       theError.arg(*anArgsIt);
385       return false;
386     } else {
387       return true;
388     }
389   }
390
391   std::shared_ptr<GeomAPI_Edge> aDirEdge(new GeomAPI_Edge(aDirShape));
392
393   // If faces selected check that direction not parallel with them.
394   AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aCheckAttribute);
395   for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
396     AttributeSelectionPtr anAttr = aListAttr->value(anIndex);
397     GeomShapePtr aShapeInList = anAttr->value();
398     if(!aShapeInList.get()) {
399       aShapeInList = anAttr->context()->shape();
400     }
401     bool isParallel = true;
402     if(aShapeInList->shapeType() == GeomAPI_Shape::FACE || aShapeInList->shapeType() == GeomAPI_Shape::SHELL) {
403       for(GeomAPI_ShapeExplorer anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {
404         std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(anExp.current()));
405         isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace);
406         if(isParallel) {
407           break;
408         }
409       }
410     } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) {
411       std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges = std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShapeInList);
412       if(aPlanarEdges.get()) {
413         std::shared_ptr<GeomAPI_Dir> aSketchDir = aPlanarEdges->norm();
414         if(aDirEdge->isLine()) {
415           std::shared_ptr<GeomAPI_Dir> aDir = aDirEdge->line()->direction();
416           isParallel = fabs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7;
417         } else {
418           isParallel = false;
419         }
420       } else {
421         isParallel = false;
422       }
423     } else {
424       isParallel = false;
425     }
426     if(isParallel) {
427       theError = "Error: Direction is parallel to one of the selected face or face on selected shell.";
428       return false;
429     }
430   }
431
432   return true;
433 }
434
435 //==================================================================================================
436 bool FeaturesPlugin_ValidatorExtrusionDir::isNotObligatory(std::string theFeature, std::string theAttribute)
437 {
438   return false;
439 }
440
441 //==================================================================================================
442 bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute,
443                                                               Events_InfoMessage& theError) const
444 {
445   if(!theAttribute.get()) {
446     return true;
447   }
448
449   std::string anAttributeType = theAttribute->attributeType();
450   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
451     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
452     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
453       // If at least one attribute is invalid, the result is false.
454       if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
455         return false;
456       }
457     }
458   } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
459     // Getting context.
460     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
461     ResultPtr aContext = anAttr->context();
462     if(!aContext.get()) {
463       return false;
464     }
465
466     GeomShapePtr aShape = anAttr->value();
467     GeomShapePtr aContextShape = aContext->shape();
468     if(!aShape.get()) {
469       aShape = aContextShape;
470     }
471     if(!aShape.get()) {
472       return false;
473     }
474
475     if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
476        aShape->shapeType() == GeomAPI_Shape::EDGE ||
477        !aShape->isPlanar()) {
478       return false;
479     }
480   } else {
481     return false;
482   }
483
484   return true;
485 }
486
487 //==================================================================================================
488 bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,
489                                                        const std::list<std::string>& theArguments,
490                                                        Events_InfoMessage& theError) const
491 {
492   AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
493   if(!anAttrSelectionList.get()) {
494     theError = "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
495     return false;
496   }
497   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
498   int anOperationType = aFeature->integer("bool_type")->value();
499
500   for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
501     AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
502     if(!anAttrSelection.get()) {
503       theError = "Error: Empty attribute selection.";
504       return false;
505     }
506     ResultPtr aContext = anAttrSelection->context();
507     if(!aContext.get()) {
508       theError = "Error: Empty selection context.";
509       return false;
510     }
511     ResultConstructionPtr aResultConstruction =
512       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
513     if(aResultConstruction.get()) {
514       theError = "Error: Result construction not allowed for selection.";
515       return false;
516     }
517     std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
518     GeomShapePtr aContextShape = aContext->shape();
519     if(!aShape.get()) {
520       aShape = aContextShape;
521     }
522     if(!aShape.get()) {
523       theError = "Error: Empty shape.";
524       return false;
525     }
526     if(!aShape->isEqual(aContextShape)) {
527       theError = "Error: Local selection not allowed.";
528       return false;
529     }
530
531     int aShapeType = aShape->shapeType();
532     if(anOperationType == 1) {
533       // Fuse operation. Allow to select edges, faces and solids.
534       if(aShapeType != GeomAPI_Shape::EDGE &&
535          aShapeType != GeomAPI_Shape::FACE &&
536          aShapeType != GeomAPI_Shape::SOLID &&
537          aShapeType != GeomAPI_Shape::COMPSOLID &&
538          aShapeType != GeomAPI_Shape::COMPOUND) {
539         theError = "Error: Selected shape has the wrong type.";
540         return false;
541       }
542     } else {
543       if(aShapeType != GeomAPI_Shape::SOLID &&
544          aShapeType != GeomAPI_Shape::COMPSOLID &&
545          aShapeType != GeomAPI_Shape::COMPOUND) {
546         theError = "Error: Selected shape has the wrong type.";
547         return false;
548       }
549     }
550   }
551
552   return true;
553 }
554
555 //==================================================================================================
556 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
557                                                          const std::list<std::string>& theArguments,
558                                                          Events_InfoMessage& theError) const
559 {
560   AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
561   if(!anAttrSelectionList.get()) {
562     theError = "Error: This validator can only work with selection list in \"Partition\" feature.";
563     return false;
564   }
565
566   for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
567     AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);
568
569     //GeomValidators_BodyShapes aBodyValidator;
570     //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
571     //  continue;
572     //}
573
574     GeomValidators_FeatureKind aFeatureKindValidator;
575     if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
576       continue;
577     }
578
579     ResultPtr aContext = aSelectAttr->context();
580     ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
581     if(aResultConstruction.get()) {
582       theError = "Error: Only body shapes and construction planes are allowed for selection.";
583       return false;
584     }
585
586     ResultCompSolidPtr aResultCompsolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
587     if(aResultCompsolid.get()) {
588       continue;
589     }
590
591     theError = "Error: Only body shapes and construction planes are allowed for selection.";
592     return false;
593   }
594
595   theError = "";
596   return true;
597 }
598
599 //==================================================================================================
600 bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,
601                                                                const std::list<std::string>& theArguments,
602                                                                Events_InfoMessage& theError) const
603 {
604   AttributeSelectionListPtr aSubShapesAttrList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
605   if(!aSubShapesAttrList.get()) {
606     theError = "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";
607     return false;
608   }
609
610   static const std::string aBaseShapeID = "base_shape";
611   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
612   AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
613
614   if(!aShapeAttrSelection.get()) {
615     theError = "Error: Could not get \"%1\" attribute.";
616     theError.arg(aBaseShapeID);
617     return false;
618   }
619
620   GeomShapePtr aBaseShape = aShapeAttrSelection->value();
621   ResultPtr aContext = aShapeAttrSelection->context();
622   if(!aContext.get()) {
623     theError = "Error: Empty context.";
624     return false;
625   }
626   if(!aBaseShape.get()) {
627     aBaseShape = aContext->shape();
628   }
629   if(!aBaseShape.get()) {
630     theError = "Error: Empty base shape.";
631     return false;
632   }
633
634   for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
635     bool isSameFound = false;
636     AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
637     GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
638     for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
639       if(anIt.current()->isEqual(aShapeToAdd)) {
640         isSameFound = true;
641         break;
642       }
643     }
644     if(!isSameFound) {
645       theError = "Error: Only sub-shapes of selected shape is allowed for selection.";
646       return false;
647     }
648   }
649
650   return true;
651 }
652
653 //==================================================================================================
654 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
655                                                             const std::list<std::string>& theArguments,
656                                                             Events_InfoMessage& theError) const
657 {
658   static const std::string aBaseShapeID = "base_shape";
659   static const std::string aSubShapesID = "subshapes";
660
661   if(theFeature->getKind() != "Remove_SubShapes") {
662     theError = "Error: Feature \"%1\" does not supported by this validator.";
663     theError.arg(theFeature->getKind());
664     return false;
665   }
666
667   AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);
668   if(!aShapeAttrSelection.get()) {
669     theError = "Error: Could not get \"%1\" attribute.";
670     theError.arg(aBaseShapeID);
671     return false;
672   }
673
674   AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);
675   if(!aSubShapesAttrList.get()) {
676     theError = "Error: Could not get \"%1\" attribute.";
677     theError.arg(aSubShapesID);
678     return false;
679   }
680
681   // Copy base shape.
682   GeomShapePtr aBaseShape = aShapeAttrSelection->value();
683   if(!aBaseShape.get()) {
684     theError = "Error: Base shape is empty.";
685     return false;
686   }
687   GeomShapePtr aResultShape = aBaseShape->emptyCopied();
688
689   // Copy sub-shapes from list to new shape.
690   for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
691     AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
692     GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
693     GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
694   }
695
696   // Check new shape.
697   if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {
698     theError = "Error: Resulting shape is not valid.";
699     return false;
700   }
701
702   return true;
703 }
704
705 //==================================================================================================
706 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isNotObligatory(std::string theFeature,
707                                                                     std::string theAttribute)
708 {
709   return false;
710 }
711
712 //==================================================================================================
713 bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute,
714                                                      const std::list<std::string>& theArguments,
715                                                      Events_InfoMessage& theError) const
716 {
717   AttributeSelectionListPtr aBaseObjectsAttrList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
718   if(!aBaseObjectsAttrList.get()) {
719     theError = "Error: This validator can only work with selection list in \"%1\" feature.";
720     theError.arg(FeaturesPlugin_Union::ID());
721     return false;
722   }
723
724   for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) {
725     bool isSameFound = false;
726     AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);
727     ResultCompSolidPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(anAttrSelectionInList->context());
728     if(!aResult.get()) {
729       continue;
730     }
731     if(aResult->numberOfSubs() > 0) {
732       theError = "Error: Whole compsolids not allowed for selection.";
733       return false;
734     }
735   }
736
737   return true;
738 }
739
740 //==================================================================================================
741 bool FeaturesPlugin_ValidatorUnionArguments::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
742                                                      const std::list<std::string>& theArguments,
743                                                      Events_InfoMessage& theError) const
744 {
745   // Check feature kind.
746   if(theFeature->getKind() != FeaturesPlugin_Union::ID()) {
747     theError = "Error: This validator supports only \"%1\" feature.";
748     theError.arg(FeaturesPlugin_Union::ID());
749     return false;
750   }
751
752   // Get base objects attribute list.
753   AttributeSelectionListPtr aBaseObejctsAttrList = theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID());
754   if(!aBaseObejctsAttrList.get()) {
755     theError = "Error: Could not get \"%1\" attribute.";
756     theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID());
757     return false;
758   }
759
760   // Get all shapes.
761   ListOfShape aBaseShapesList;
762   for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) {
763     AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex);
764     GeomShapePtr aShape = anAttrSelectionInList->value();
765     aBaseShapesList.push_back(aShape);
766   }
767
768   // Make componud and find connected.
769   GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList);
770   ListOfShape aCombined, aFree;
771   GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCombined, aFree);
772
773   if(aFree.size() > 0 || aCombined.size() > 1) {
774     theError = "Error: Not all shapes have shared topology.";
775     return false;
776   }
777
778   return true;
779 }
780
781 //==================================================================================================
782 bool FeaturesPlugin_ValidatorUnionArguments::isNotObligatory(std::string theFeature,
783                                                              std::string theAttribute)
784 {
785   return false;
786 }
787
788 bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute,
789                                             const std::list<std::string>& theArguments,
790                                             Events_InfoMessage& theError) const
791 {
792   if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
793     theError = "Error: The attribute with the %1 type is not processed";
794     theError.arg(theAttribute->attributeType());
795     return false;
796   }
797
798   AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeReference>
799                                                                                (theAttribute);
800   ObjectPtr aRefObject = aRefAttribute->value();
801   if (!aRefObject.get()) {
802     theError = "Error: Empty feature.";
803     return false;
804   }
805
806   FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aRefObject);
807   if (!aRefFeature.get()) {
808     theError = "Error: Empty feature.";
809     return false;
810   }
811   std::list<std::shared_ptr<ModelAPI_Result> > aResults;
812   ModelAPI_Tools::getConcealedResults(aRefFeature, aResults);
813
814   size_t aConcealedResults = aResults.size();
815   if (!aConcealedResults && !theArguments.empty()) {
816     // find if these results are touched by the feature in another attribute
817     std::list<std::string>::const_iterator anIt = theArguments.begin();
818     std::string aRecoveredList = *anIt;
819     if (!aRecoveredList.empty()) {
820       std::shared_ptr<ModelAPI_AttributeRefList> aParameterList =
821                                  theAttribute->owner()->data()->reflist(aRecoveredList);
822       if (aParameterList.get())
823         aConcealedResults = aParameterList->size();
824     }
825   }
826
827   if (aConcealedResults == 0)
828     theError = "Error: No concealed results.";
829
830   return theError.empty();
831 }