Salome HOME
Added python dump checking for every unit test where it is useful.
[modules/shaper.git] / src / ModelHighAPI / ModelHighAPI_Tools.cpp
1 // Name   : ModelHighAPI_Tools.cpp
2 // Purpose: 
3 //
4 // History:
5 // 07/06/16 - Sergey POKHODENKO - Creation of the file
6
7 //--------------------------------------------------------------------------------------
8 #include "ModelHighAPI_Tools.h"
9 #include <ModelHighAPI_FeatureStore.h>
10 //--------------------------------------------------------------------------------------
11 #include <GeomAPI_Dir.h>
12 #include <GeomAPI_Pnt.h>
13 #include <GeomAPI_Pnt2d.h>
14 //--------------------------------------------------------------------------------------
15 #include <GeomDataAPI_Dir.h>
16 #include <GeomDataAPI_Point.h>
17 #include <GeomDataAPI_Point2D.h>
18 //--------------------------------------------------------------------------------------
19 #include <ModelAPI_AttributeBoolean.h>
20 #include <ModelAPI_AttributeDocRef.h>
21 #include <ModelAPI_AttributeDouble.h>
22 #include <ModelAPI_AttributeIntArray.h>
23 #include <ModelAPI_AttributeInteger.h>
24 #include <ModelAPI_AttributeRefAttr.h>
25 #include <ModelAPI_AttributeRefAttrList.h>
26 #include <ModelAPI_AttributeReference.h>
27 #include <ModelAPI_AttributeRefList.h>
28 #include <ModelAPI_AttributeSelection.h>
29 #include <ModelAPI_AttributeSelectionList.h>
30 #include <ModelAPI_AttributeString.h>
31 #include <ModelAPI_AttributeDoubleArray.h>
32 #include <ModelAPI_Session.h>
33 #include <ModelAPI_Tools.h>
34 #include <ModelAPI_ResultPart.h>
35 //--------------------------------------------------------------------------------------
36 #include <Config_ModuleReader.h>
37 //--------------------------------------------------------------------------------------
38 #include "ModelHighAPI_Double.h"
39 #include "ModelHighAPI_Integer.h"
40 #include "ModelHighAPI_RefAttr.h"
41 #include "ModelHighAPI_Reference.h"
42 #include "ModelHighAPI_Selection.h"
43
44 #include <Events_InfoMessage.h>
45
46 #include <algorithm>
47 #include <iostream>
48
49 //--------------------------------------------------------------------------------------
50 void fillAttribute(const std::shared_ptr<GeomAPI_Pnt2d> & theValue,
51                    const std::shared_ptr<GeomDataAPI_Point2D> & theAttribute)
52 {
53   theAttribute->setValue(theValue);
54 }
55
56 void fillAttribute(const std::shared_ptr<GeomDataAPI_Point2D> & theAttribute,
57                    double theX, double theY)
58 {
59   theAttribute->setValue(theX, theY);
60 }
61
62 //--------------------------------------------------------------------------------------
63 void fillAttribute(const std::shared_ptr<GeomAPI_Dir> & theValue,
64                    const std::shared_ptr<GeomDataAPI_Dir> & theAttribute)
65 {
66   theAttribute->setValue(theValue);
67 }
68
69 //--------------------------------------------------------------------------------------
70 void fillAttribute(const std::shared_ptr<GeomAPI_Pnt> & theValue,
71                    const std::shared_ptr<GeomDataAPI_Point> & theAttribute)
72 {
73   theAttribute->setValue(theValue);
74 }
75
76 //--------------------------------------------------------------------------------------
77 void fillAttribute(bool theValue,
78                    const std::shared_ptr<ModelAPI_AttributeBoolean> & theAttribute)
79 {
80   theAttribute->setValue(theValue);
81 }
82
83 //--------------------------------------------------------------------------------------
84 void fillAttribute(const ModelHighAPI_Double & theValue,
85                    const std::shared_ptr<ModelAPI_AttributeDouble> & theAttribute)
86 {
87   theValue.fillAttribute(theAttribute);
88 }
89 void fillAttribute(double theValue,
90                    const std::shared_ptr<ModelAPI_AttributeDouble> & theAttribute)
91 {
92   theAttribute->setValue(theValue);
93 }
94
95 //--------------------------------------------------------------------------------------
96 void fillAttribute(const ModelHighAPI_Integer & theValue,
97                    const std::shared_ptr<ModelAPI_AttributeInteger> & theAttribute)
98 {
99   theValue.fillAttribute(theAttribute);
100 }
101 void fillAttribute(int theValue,
102                    const std::shared_ptr<ModelAPI_AttributeInteger> & theAttribute)
103 {
104   theAttribute->setValue(theValue);
105 }
106
107 //--------------------------------------------------------------------------------------
108 void fillAttribute(const ModelHighAPI_RefAttr & theValue,
109                    const std::shared_ptr<ModelAPI_AttributeRefAttr> & theAttribute)
110 {
111   theValue.fillAttribute(theAttribute);
112 }
113
114 //--------------------------------------------------------------------------------------
115 void fillAttribute(const std::list<ModelHighAPI_RefAttr> & theValue,
116                    const std::shared_ptr<ModelAPI_AttributeRefAttrList> & theAttribute)
117 {
118   theAttribute->clear();
119   for (auto it = theValue.begin(); it != theValue.end(); ++it)
120     it->appendToList(theAttribute);
121 }
122
123 //--------------------------------------------------------------------------------------
124 void fillAttribute(const ModelHighAPI_Reference & theValue,
125                    const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute)
126 {
127   theValue.fillAttribute(theAttribute);
128 }
129
130 //--------------------------------------------------------------------------------------
131 void fillAttribute(const std::list<ModelHighAPI_Reference> & theValue,
132                    const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute)
133 {
134   theAttribute->clear();
135   for (auto it = theValue.begin(); it != theValue.end(); ++it)
136     it->appendToList(theAttribute);
137 }
138
139 //--------------------------------------------------------------------------------------
140 void fillAttribute(const std::shared_ptr<ModelAPI_Object> & theValue,
141                    const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute)
142 {
143   theAttribute->setValue(theValue);
144 }
145
146 //--------------------------------------------------------------------------------------
147 void fillAttribute(const std::list<std::shared_ptr<ModelAPI_Object> > & theValue,
148                    const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute)
149 {
150   theAttribute->clear();
151   for (auto it = theValue.begin(); it != theValue.end(); ++it)
152     theAttribute->append(*it);
153 }
154
155 MODELHIGHAPI_EXPORT
156 void fillAttribute(const std::list<ModelHighAPI_Selection> & theValue,
157                    const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute)
158 {
159   theAttribute->clear();
160   for (auto it = theValue.begin(); it != theValue.end(); ++it)
161     theAttribute->append(it->resultSubShapePair().first); // use only context
162 }
163
164 //--------------------------------------------------------------------------------------
165 void fillAttribute(const ModelHighAPI_Selection & theValue,
166                    const std::shared_ptr<ModelAPI_AttributeSelection> & theAttribute)
167 {
168   theValue.fillAttribute(theAttribute);
169 }
170
171 //--------------------------------------------------------------------------------------
172 void fillAttribute(const std::list<ModelHighAPI_Selection> & theValue,
173                    const std::shared_ptr<ModelAPI_AttributeSelectionList> & theAttribute)
174 {
175   theAttribute->clear();
176   for (auto it = theValue.begin(); it != theValue.end(); ++it)
177     it->appendToList(theAttribute);
178 }
179
180 //--------------------------------------------------------------------------------------
181 void fillAttribute(const std::string & theValue,
182                    const std::shared_ptr<ModelAPI_AttributeString> & theAttribute)
183 {
184   theAttribute->setValue(theValue);
185 }
186 void fillAttribute(const char * theValue,
187                    const std::shared_ptr<ModelAPI_AttributeString> & theAttribute)
188 {
189   theAttribute->setValue(theValue);
190 }
191
192 //==================================================================================================
193 GeomAPI_Shape::ShapeType shapeTypeByStr(std::string theShapeTypeStr)
194 {
195   GeomAPI_Shape::ShapeType aShapeType = GeomAPI_Shape::SHAPE;
196
197   std::transform(theShapeTypeStr.begin(), theShapeTypeStr.end(), theShapeTypeStr.begin(), ::tolower);
198
199   if(theShapeTypeStr == "compound") {
200     aShapeType = GeomAPI_Shape::COMPOUND;
201   } else if(theShapeTypeStr == "compsolid") {
202     aShapeType = GeomAPI_Shape::COMPSOLID;
203   } else if(theShapeTypeStr == "solid") {
204     aShapeType = GeomAPI_Shape::SOLID;
205   } else if(theShapeTypeStr == "shell") {
206     aShapeType = GeomAPI_Shape::SHELL;
207   } else if(theShapeTypeStr == "face") {
208     aShapeType = GeomAPI_Shape::FACE;
209   } else if(theShapeTypeStr == "wire") {
210     aShapeType = GeomAPI_Shape::WIRE;
211   } else if(theShapeTypeStr == "edge") {
212     aShapeType = GeomAPI_Shape::EDGE;
213   } else if(theShapeTypeStr == "vertex") {
214     aShapeType = GeomAPI_Shape::VERTEX;
215   } else if(theShapeTypeStr == "shape") {
216     aShapeType = GeomAPI_Shape::SHAPE;
217   }
218
219   return aShapeType;
220 }
221
222 //==================================================================================================
223 GeomAPI_Shape::ShapeType getShapeType(const ModelHighAPI_Selection& theSelection)
224 {
225   GeomAPI_Shape::ShapeType aShapeType = GeomAPI_Shape::SHAPE;
226
227   switch(theSelection.variantType()) {
228     case ModelHighAPI_Selection::VT_ResultSubShapePair: {
229       ResultSubShapePair aPair = theSelection.resultSubShapePair();
230       GeomShapePtr aShape = aPair.second;
231       if(!aShape.get()) {
232         aShape = aPair.first->shape();
233       }
234       if(!aShape.get()) {
235         return aShapeType;
236       }
237       aShapeType = aShape->shapeType();
238       break;
239     }
240     case ModelHighAPI_Selection::VT_TypeSubShapeNamePair: {
241       TypeSubShapeNamePair aPair = theSelection.typeSubShapeNamePair();
242       std::string aType = aPair.first;
243       aShapeType = shapeTypeByStr(aType);
244       break;
245     }
246   }
247
248   return aShapeType;
249 }
250
251 /// stores the features information, recoursively stores sub-documetns features
252 std::string storeFeatures(const std::string& theDocName, DocumentPtr theDoc,
253   std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> >& theStore,
254   const bool theCompare) // if false => store
255 {
256   std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> >::iterator aDocFind;
257   if (theCompare) {
258      aDocFind = theStore.find(theDocName);
259      if (aDocFind == theStore.end()) {
260        return "Document '" + theDocName + "' not found";
261      }
262   }
263   // store the model features information: iterate all features
264   int aFeaturesCount = 0; // stores the number of compared features for this document to compate
265   std::set<std::string> aProcessed; // processed features names (that are in the current document)
266   std::list<FeaturePtr> allFeatures = theDoc->allFeatures();
267   std::list<FeaturePtr>::iterator allIter = allFeatures.begin();
268   for(; allIter != allFeatures.end(); allIter++) {
269     FeaturePtr aFeat = *allIter;
270     if (theCompare) {
271       std::map<std::string, ModelHighAPI_FeatureStore>::iterator 
272         aFeatFind = aDocFind->second.find(aFeat->name());
273       if (aFeatFind == aDocFind->second.end()) {
274         return "Document '" + theDocName + "' feature '" + aFeat->name() + "' not found";
275       }
276       std::string anError = aFeatFind->second.compare(aFeat);
277       if (!anError.empty()) {
278         return anError;
279       }
280       aFeaturesCount++;
281       aProcessed.insert(aFeat->name());
282     } else {
283       theStore[theDocName][aFeat->name()] = ModelHighAPI_FeatureStore(aFeat);
284     }
285     // iterate all results of this feature
286     std::list<ResultPtr> allResults;
287     ModelAPI_Tools::allResults(aFeat, allResults);
288     std::list<ResultPtr>::iterator aRes = allResults.begin();
289     for(; aRes != allResults.end(); aRes++) {
290       if ((*aRes)->groupName() == ModelAPI_ResultPart::group()) { // recoursively store features of sub-documents
291         DocumentPtr aDoc = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRes)->partDoc();
292         if (aDoc.get()) {
293           std::string anError = storeFeatures((*aRes)->data()->name(), aDoc, theStore, theCompare);
294           if (!anError.empty())
295             return anError;
296         }
297       }
298     }
299   }
300   // checks the number of compared features
301   if (theCompare) {
302     if (aDocFind->second.size() != aFeaturesCount) {
303       // search for disappeared feature
304       std::string aLostName;
305       std::map<std::string, ModelHighAPI_FeatureStore>::iterator aLostIter;
306       for(aLostIter = aDocFind->second.begin(); aLostIter != aDocFind->second.end(); aLostIter++) {
307         if (aProcessed.find(aLostIter->first) == aProcessed.end()) {
308           aLostName = aLostIter->first;
309         }
310       }
311       return "For document '" + theDocName + 
312         "' the number of features is decreased, there is no feature '" + aLostName + "'";
313     }
314   }
315   return ""; // ok
316 }
317
318 //==================================================================================================
319 bool checkPythonDump()
320 {
321   SessionPtr aSession = ModelAPI_Session::get();
322   // dump all to the python file
323   aSession->startOperation("Check python dump");
324   FeaturePtr aDump = aSession->moduleDocument()->addFeature("Dump");
325   if (aDump.get()) {
326     aDump->string("file_path")->setValue("check_dump.py"); // to the current folder
327     aDump->string("file_format")->setValue("py"); // to the current folder
328     aDump->execute();
329   }
330   bool isProblem = !aDump.get() || !aDump->error().empty(); // after "finish" dump will be removed
331   aSession->finishOperation();
332   if (isProblem)
333     return false; // something is wrong during dump
334
335    // map from document name to feature name to feature data
336   std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> > aStore;
337   std::string anError = storeFeatures(
338     aSession->moduleDocument()->kind(), aSession->moduleDocument(), aStore, false);
339   if (!anError.empty()) {
340     Events_InfoMessage anError("checkPythonDump", anError);
341     anError.send();
342     return false;
343   }
344   // close all before importation of the script
345   aSession->closeAll();
346   // execute the dumped
347   Config_ModuleReader::loadScript("check_dump");
348
349   // compare with the stored data
350   anError = storeFeatures(
351     aSession->moduleDocument()->kind(), aSession->moduleDocument(), aStore, true);
352   if (!anError.empty()) {
353     std::cout<<anError<<std::endl;
354     Events_InfoMessage anError("checkPythonDump", anError);
355     anError.send();
356     return false;
357   }
358
359   return true;
360 }
361
362 //--------------------------------------------------------------------------------------