]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESH_I/SMESH_DumpPython.cxx
Salome HOME
73223beb78929964bda09a0da6ec878d072f08c9
[modules/smesh.git] / src / SMESH_I / SMESH_DumpPython.cxx
1 // File    : SMESH_Gen_i_DumpPython.cxx
2 // Created : Thu Mar 24 17:17:59 2005
3 // Author  : Julia DOROVSKIKH
4 // Module  : SMESH
5 // $Header : $
6
7 #include "SMESH_PythonDump.hxx"
8 #include "SMESH_Gen_i.hxx"
9 #include "SMESH_Filter_i.hxx"
10
11 #include <TColStd_HSequenceOfInteger.hxx>
12
13 namespace SMESH
14 {
15   TCollection_AsciiString& 
16   operator<<(TCollection_AsciiString& theString, const char* theArg){
17     theString += Standard_CString(theArg);
18     return theString;
19   }
20
21   TCollection_AsciiString& 
22   operator<<(TCollection_AsciiString& theString, int theArg){
23     theString += TCollection_AsciiString(theArg);
24     return theString;
25   }
26
27   TCollection_AsciiString& 
28   operator<<(TCollection_AsciiString& theString, float theArg){
29     theString += TCollection_AsciiString(theArg);
30     return theString;
31   }
32
33   TCollection_AsciiString& 
34   operator<<(TCollection_AsciiString& theString, 
35              const SMESH::long_array& theArg)
36   {
37     theString<<"[ ";
38     CORBA::Long i = 1, iEnd = theArg.length();
39     for(; i <= iEnd; i++) {
40       theString<<int(theArg[i-1]);
41       if(i < iEnd)
42         theString<< ", ";
43     }
44     theString<<" ]";
45     return theString;
46   }
47
48
49   TCollection_AsciiString& 
50   operator<<(TCollection_AsciiString& theString, 
51              CORBA::Object_ptr theArg)
52   {
53     CORBA::String_var aString("None");
54     SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
55     SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
56     SALOMEDS::SObject_var aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
57     if(!aSObject->_is_nil()){
58       aString = aSObject->GetID();
59     }else if(!CORBA::is_nil(theArg)){
60       aString = SMESH_Gen_i::GetORB()->object_to_string(theArg);
61     }
62     theString<<aString.in();
63     return theString;
64   }
65
66   TCollection_AsciiString& 
67   operator<<(TCollection_AsciiString& theString, 
68              SMESH::FilterLibrary_i* theArg)
69   {
70     theString += TCollection_AsciiString("aFilterLibrary_");
71     theString += TCollection_AsciiString(int(theArg));
72     return theString;
73   }
74
75   TCollection_AsciiString& 
76   operator<<(TCollection_AsciiString& theString, 
77              SMESH::FilterManager_i* theArg)
78   {
79     theString += TCollection_AsciiString("aFilterManager_");
80     theString += TCollection_AsciiString(int(theArg));
81     return theString;
82   }
83
84   TCollection_AsciiString& 
85   operator<<(TCollection_AsciiString& theString, 
86              SMESH::Filter_i* theArg)
87   {
88     theString += TCollection_AsciiString("aFilter_");
89     theString += TCollection_AsciiString(int(theArg));
90     return theString;
91   }
92
93   TCollection_AsciiString& 
94   operator<<(TCollection_AsciiString& theString, 
95              SMESH::Functor_i* theArg)
96   {
97     FunctorType aFunctorType = theArg->GetFunctorType();
98     switch(aFunctorType){
99     case FT_AspectRatio:
100       theString += TCollection_AsciiString("anAspectRatio");
101       break;
102     case FT_AspectRatio3D:
103       theString += TCollection_AsciiString("anAspectRatio3D");
104       break;
105     case FT_Warping:
106       theString += TCollection_AsciiString("aWarping");
107       break;
108     case FT_MinimumAngle:
109       theString += TCollection_AsciiString("aMinimumAngle");
110       break;
111     case FT_Taper:
112       theString += TCollection_AsciiString("aTaper");
113       break;
114     case FT_Skew:
115       theString += TCollection_AsciiString("aSkew");
116       break;
117     case FT_Area:
118       theString += TCollection_AsciiString("aArea");
119       break;
120     case FT_FreeBorders:
121       theString += TCollection_AsciiString("aFreeBorders");
122       break;
123     case FT_FreeEdges:
124       theString += TCollection_AsciiString("aFreeEdges");
125       break;
126     case FT_MultiConnection:
127       theString += TCollection_AsciiString("aMultiConnection");
128       break;
129     case FT_MultiConnection2D:
130       theString += TCollection_AsciiString("aMultiConnection2D");
131       break;
132     case FT_Length:
133       theString += TCollection_AsciiString("aLength");
134       break;
135     case FT_Length2D:
136       theString += TCollection_AsciiString("aLength");
137       break;
138     case FT_BelongToGeom:
139       theString += TCollection_AsciiString("aBelongToGeom");
140       break;
141     case FT_BelongToPlane:
142       theString += TCollection_AsciiString("aBelongToPlane");
143       break;
144     case FT_BelongToCylinder:
145       theString += TCollection_AsciiString("aBelongToCylinder");
146       break;
147     case FT_LyingOnGeom:
148       theString += TCollection_AsciiString("aLyingOnGeom");
149       break;
150     case FT_RangeOfIds:
151       theString += TCollection_AsciiString("aRangeOfIds");
152       break;
153     case FT_BadOrientedVolume:
154       theString += TCollection_AsciiString("aBadOrientedVolume");
155       break;
156     case FT_LessThan:
157       theString += TCollection_AsciiString("aLessThan");
158       break;
159     case FT_MoreThan:
160       theString += TCollection_AsciiString("aMoreThan");
161       break;
162     case FT_EqualTo:
163       theString += TCollection_AsciiString("anEqualTo");
164       break;
165     case FT_LogicalNOT:
166       theString += TCollection_AsciiString("aLogicalNOT");
167       break;
168     case FT_LogicalAND:
169       theString += TCollection_AsciiString("aLogicalAND");
170       break;
171     case FT_LogicalOR:
172       theString += TCollection_AsciiString("aLogicalOR");
173       break;
174     case FT_Undefined:
175       theString += TCollection_AsciiString("anUndefined");
176       break;
177     }
178     theString += Standard_CString("_");
179     theString += TCollection_AsciiString(int(theArg));
180     return theString;
181   }
182
183   TPythonDump::
184   ~TPythonDump()
185   {
186     SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
187     SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
188     if(!aStudy->_is_nil()){
189       aSMESHGen->AddToPythonScript(aStudy->StudyId(),myString);
190     }
191   }
192 }
193
194 //=======================================================================
195 //function : DumpPython
196 //purpose  : 
197 //=======================================================================
198 Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Object_ptr theStudy,
199                                            CORBA::Boolean isPublished,
200                                            CORBA::Boolean& isValidScript)
201 {
202   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
203   if (CORBA::is_nil(aStudy))
204     return new Engines::TMPFile(0);
205
206   SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
207   if (CORBA::is_nil(aSO))
208     return new Engines::TMPFile(0);
209
210   // Map study entries to object names
211   Resource_DataMapOfAsciiStringAsciiString aMap;
212   TCollection_AsciiString s ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
213
214   SALOMEDS::ChildIterator_var Itr = aStudy->NewChildIterator(aSO);
215   for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
216     SALOMEDS::SObject_var aValue = Itr->Value();
217
218     TCollection_AsciiString aName (aValue->GetName());
219     if (aName.Length() > 0) {
220       int p, p2 = 1, e = aName.Length();
221       while ((p = aName.FirstLocationNotInSet(s, p2, e))) {
222         aName.SetValue(p, '_');
223         p2 = p;
224       }
225       aMap.Bind(TCollection_AsciiString(aValue->GetID()), aName);
226     }
227   }
228
229   // Get trace of restored study
230   //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
231   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
232   SALOMEDS::GenericAttribute_var anAttr =
233     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
234
235   char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
236   TCollection_AsciiString aSavedTrace (oldValue);
237
238   // Add trace of API methods calls and replace study entries by names
239   bool aValidScript;
240   //TCollection_AsciiString aScript = myGen.DumpPython
241   TCollection_AsciiString aScript = DumpPython_impl
242     (aStudy->StudyId(), aMap, isPublished, aValidScript, aSavedTrace);
243
244   int aLen = aScript.Length(); 
245   unsigned char* aBuffer = new unsigned char[aLen+1];
246   strcpy((char*)aBuffer, aScript.ToCString());
247
248   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
249   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aLen+1, aLen+1, anOctetBuf, 1); 
250   isValidScript = aValidScript;
251
252   return aStreamFile._retn(); 
253 }
254
255 //=============================================================================
256 /*!
257  *  AddToPythonScript
258  */
259 //=============================================================================
260 void SMESH_Gen_i::AddToPythonScript (int theStudyID, const TCollection_AsciiString& theString)
261 {
262   if (myPythonScripts.find(theStudyID) == myPythonScripts.end()) {
263     myPythonScripts[theStudyID] = new TColStd_HSequenceOfAsciiString;
264   }
265   myPythonScripts[theStudyID]->Append(theString);
266 }
267
268 //=============================================================================
269 /*!
270  *  RemoveLastFromPythonScript
271  */
272 //=============================================================================
273 void SMESH_Gen_i::RemoveLastFromPythonScript (int theStudyID)
274 {
275   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
276     int aLen = myPythonScripts[theStudyID]->Length();
277     myPythonScripts[theStudyID]->Remove(aLen);
278   }
279 }
280
281 //=======================================================================
282 //function : AddToCurrentPyScript
283 //purpose  : 
284 //=======================================================================
285
286 void SMESH_Gen_i::AddToCurrentPyScript (const TCollection_AsciiString& theString)
287 {
288   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
289   SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
290   if (aStudy->_is_nil()) return;
291   aSMESHGen->AddToPythonScript(aStudy->StudyId(), theString);
292 }
293
294
295 //=======================================================================
296 //function : AddObject
297 //purpose  : add object to script string
298 //=======================================================================
299
300 TCollection_AsciiString& SMESH_Gen_i::AddObject(TCollection_AsciiString& theStr,
301                                                 CORBA::Object_ptr        theObject)
302 {
303   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
304   SALOMEDS::SObject_var aSO =
305     aSMESHGen->ObjectToSObject(aSMESHGen->GetCurrentStudy(), theObject);
306   if ( !aSO->_is_nil() )
307     theStr += aSO->GetID();
308   else if ( !CORBA::is_nil( theObject ) )
309     theStr += GetORB()->object_to_string( theObject );
310   else
311     theStr += "None";
312
313   return theStr;
314 }
315
316 //=======================================================================
317 //function : SavePython
318 //purpose  : 
319 //=======================================================================
320 void SMESH_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
321 {
322   // Dump trace of API methods calls
323   TCollection_AsciiString aScript = GetNewPythonLines(theStudy->StudyId());
324
325   // Check contents of PythonObject attribute
326   SALOMEDS::SObject_var aSO = theStudy->FindComponent(ComponentDataType());
327   //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
328   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
329   SALOMEDS::GenericAttribute_var anAttr =
330     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
331
332   char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
333   TCollection_AsciiString oldScript (oldValue);
334
335   if (oldScript.Length() > 0) {
336     oldScript += "\n";
337     oldScript += aScript;
338   } else {
339     oldScript = aScript;
340   }
341
342   // Store in PythonObject attribute
343   SALOMEDS::AttributePythonObject::_narrow(anAttr)->SetObject(oldScript.ToCString(), 1);
344
345   // Clean trace of API methods calls
346   CleanPythonTrace(theStudy->StudyId());
347 }
348
349
350 // impl
351
352
353 //=============================================================================
354 /*!
355  *  FindEntries: Returns a sequence of start/end positions of entries in the string
356  */
357 //=============================================================================
358 Handle(TColStd_HSequenceOfInteger) FindEntries (TCollection_AsciiString& theString)
359 {
360   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
361   Standard_Integer aLen = theString.Length();
362   Standard_Boolean isFound = Standard_False;
363
364   char* arr = theString.ToCString();
365   Standard_Integer i = 0, j;
366
367   while(i < aLen) {
368     int c = (int)arr[i];
369     j = i+1;
370     if(c >= 48 && c <= 57) { //Is digit?
371  
372       isFound = Standard_False;
373       while((j < aLen) && ((c >= 48 && c <= 57) || c == 58) ) { //Check if it is an entry
374         c = (int)arr[j++];  
375         if(c == 58) isFound = Standard_True;
376       }
377
378       if (isFound) {
379         int prev = (i < 1) ? 0 : (int)arr[i - 1];
380         // last char should be a diggit,
381         // previous char should not be '"'.
382         if (arr[j-2] != 58 && prev != 34) {
383           aSeq->Append(i+1); // +1 because AsciiString starts from 1
384           aSeq->Append(j-1);
385         }
386       }
387     }
388
389     i = j;
390   }
391
392   return aSeq;
393 }
394
395 //=============================================================================
396 /*!
397  *  DumpPython
398  */
399 //=============================================================================
400 TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
401                         (int theStudyID, 
402                          Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
403                          bool isPublished, 
404                          bool& aValidScript,
405                          const TCollection_AsciiString& theSavedTrace)
406 {
407   TCollection_AsciiString aScript;
408   aScript += "import salome\n";
409   aScript += "import geompy\n\n";
410   aScript += "import SMESH\n";
411   aScript += "import StdMeshers\n\n";
412   aScript += "#import GEOM module\n";
413   aScript += "import string\n";
414   aScript += "import os\n";
415   aScript += "import sys\n";
416   aScript += "sys.path.append( os.path.dirname(__file__) )\n";
417   aScript += "exec(\"from \"+string.replace(__name__,\"SMESH\",\"GEOM\")+\" import *\")\n\n";
418   
419   aScript += "def RebuildData(theStudy):";
420   aScript += "\n\tsmesh = salome.lcc.FindOrLoadComponent(\"FactoryServer\", \"SMESH\")";
421   if ( isPublished )
422     aScript += "\n\tsmesh.SetCurrentStudy(theStudy)";
423   else
424     aScript += "\n\tsmesh.SetCurrentStudy(None)";
425
426   TCollection_AsciiString globalVars;
427
428   // Dump trace of restored study
429   if (theSavedTrace.Length() > 0) {
430     aScript += "\n";
431     aScript += theSavedTrace;
432   }
433
434   // Dump trace of API methods calls
435   TCollection_AsciiString aNewLines = GetNewPythonLines(theStudyID);
436   if (aNewLines.Length() > 0) {
437     aScript += "\n";
438     aScript += aNewLines;
439   }
440
441   // Find entries to be replaced by names
442   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
443   Standard_Integer aLen = aSeq->Length();
444
445   if (aLen == 0)
446     return aScript;
447
448   // Replace entries by the names
449   GEOM::GEOM_Gen_ptr geom = GetGeomEngine();
450   TColStd_SequenceOfAsciiString seqRemoved;
451   Resource_DataMapOfAsciiStringAsciiString mapRemoved;
452   Resource_DataMapOfAsciiStringAsciiString aNames;
453   Standard_Integer objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
454   TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("smeshObj_");
455
456   for (Standard_Integer i = 1; i <= aLen; i += 2) {
457     anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i) - 1);
458     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
459     if (theObjectNames.IsBound(anEntry)) {
460       aName = theObjectNames.Find(anEntry);
461       if (theObjectNames.IsBound(aName) && anEntry != theObjectNames(aName)) {
462         // diff objects have same name - make a new name
463         TCollection_AsciiString aName2;
464         Standard_Integer i = 0;
465         do {
466           aName2 = aName + "_" + ++i;
467         } while (theObjectNames.IsBound(aName2) && anEntry != theObjectNames(aName2));
468         aName = aName2;
469         theObjectNames(anEntry) = aName;
470       }
471     } else {
472       // is a GEOM object?
473       aName = geom->GetDumpName( anEntry.ToCString() );
474       if ( aName.IsEmpty() ) {
475       // ? Removed Object ?
476         do {
477           aName = aBaseName + TCollection_AsciiString(++objectCounter);
478         } while (theObjectNames.IsBound(aName));
479         seqRemoved.Append(aName);
480         mapRemoved.Bind(anEntry, "1");
481       }
482       theObjectNames.Bind(anEntry, aName);
483     }
484     theObjectNames.Bind(aName, anEntry); // to detect same name of diff objects
485
486     anUpdatedScript += aName;
487     aNames.Bind(aName, "1");
488     aStart = aSeq->Value(i + 1) + 1;
489   }
490
491   // add final part of aScript
492   if (aSeq->Value(aLen) < aScriptLength)
493     anUpdatedScript += aScript.SubString(aSeq->Value(aLen) + 1, aScriptLength);
494
495   // Remove removed objects
496   anUpdatedScript += "\n\taStudyBuilder = theStudy.NewBuilder()";
497   for (int ir = 1; ir <= seqRemoved.Length(); ir++) {
498     anUpdatedScript += "\n\tSO = theStudy.FindObjectIOR(theStudy.ConvertObjectToIOR(";
499     anUpdatedScript += seqRemoved.Value(ir);
500     anUpdatedScript += "))\n\tif SO is not None: aStudyBuilder.RemoveObjectWithChildren(SO)";
501   }
502   anUpdatedScript += "\n";
503
504   // Set object names
505   anUpdatedScript += "\n\tisGUIMode = ";
506   anUpdatedScript += isPublished;
507   anUpdatedScript += "\n\tif isGUIMode:";
508   anUpdatedScript += "\n\t\tsmeshgui = salome.ImportComponentGUI(\"SMESH\")";
509   anUpdatedScript += "\n\t\tsmeshgui.Init(theStudy._get_StudyId())";
510   anUpdatedScript += "\n";
511
512   Resource_DataMapOfAsciiStringAsciiString mapEntries;
513   for (Standard_Integer i = 1; i <= aLen; i += 2) {
514     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
515     if (theObjectNames.IsBound(anEntry) &&
516         !mapEntries.IsBound(anEntry) &&
517         !mapRemoved.IsBound(anEntry)) {
518       aName = theObjectNames.Find(anEntry);
519       mapEntries.Bind(anEntry, aName);
520       anUpdatedScript += "\n\t\tsmeshgui.SetName(salome.ObjectToID(";
521       anUpdatedScript += aName + "), \"" + aName + "\")";
522     }
523   }
524   anUpdatedScript += "\n\n\t\tsalome.sg.updateObjBrowser(0)";
525
526   anUpdatedScript += "\n\n\tpass\n";
527
528   aValidScript = true;
529
530   return anUpdatedScript;
531 }
532
533 //=============================================================================
534 /*!
535  *  GetNewPythonLines
536  */
537 //=============================================================================
538 TCollection_AsciiString SMESH_Gen_i::GetNewPythonLines (int theStudyID)
539 {
540   TCollection_AsciiString aScript;
541
542   // Dump trace of API methods calls
543   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
544     Handle(TColStd_HSequenceOfAsciiString) aPythonScript = myPythonScripts[theStudyID];
545     Standard_Integer istr, aLen = aPythonScript->Length();
546     for (istr = 1; istr <= aLen; istr++) {
547       aScript += "\n\t";
548       aScript += aPythonScript->Value(istr);
549     }
550     aScript += "\n";
551   }
552
553   return aScript;
554 }
555
556 //=============================================================================
557 /*!
558  *  CleanPythonTrace
559  */
560 //=============================================================================
561 void SMESH_Gen_i::CleanPythonTrace (int theStudyID)
562 {
563   TCollection_AsciiString aScript;
564
565   // Clean trace of API methods calls
566   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
567     myPythonScripts[theStudyID]->Clear();
568   }
569 }