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