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