1 // File : SMESH_Gen_i_DumpPython.cxx
2 // Created : Thu Mar 24 17:17:59 2005
3 // Author : Julia DOROVSKIKH
7 #include "SMESH_PythonDump.hxx"
8 #include "SMESH_Gen_i.hxx"
9 #include "SMESH_Filter_i.hxx"
10 #include "SALOMEDSImpl_Study.hxx"
12 #include <TColStd_HSequenceOfInteger.hxx>
13 #include <TCollection_AsciiString.hxx>
17 static int MYDEBUG = 0;
19 static int MYDEBUG = 0;
22 static TCollection_AsciiString NotPublishedObjectName()
24 return "__NOT__Published__Object__";
30 size_t TPythonDump::myCounter = 0;
41 SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
42 SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
43 if(!aStudy->_is_nil()){
44 std::string aString = myStream.str();
45 TCollection_AsciiString aCollection(Standard_CString(aString.c_str()));
46 aSMESHGen->AddToPythonScript(aStudy->StudyId(),aCollection);
47 if(MYDEBUG) MESSAGE(aString);
54 operator<<(long int theArg){
61 operator<<(int theArg){
68 operator<<(double theArg){
75 operator<<(float theArg){
82 operator<<(const void* theArg){
89 operator<<(const char* theArg){
96 operator<<(const SMESH::ElementType& theArg)
122 operator<<(const SMESH::long_array& theArg)
125 CORBA::Long i = 1, iEnd = theArg.length();
126 for(; i <= iEnd; i++) {
127 myStream<<theArg[i-1];
138 operator<<(CORBA::Object_ptr theArg)
140 TCollection_AsciiString aString("None");
141 SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
142 SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
143 SALOMEDS::SObject_var aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
144 if(!aSObject->_is_nil()){
145 aString = aSObject->GetID();
146 }else if(!CORBA::is_nil(theArg)){
147 aString = "smeshObj_";
148 if ( aSMESHGen->CanPublishInStudy( theArg )) // not published SMESH object
149 aString += (int) theArg;
151 aString = NotPublishedObjectName();
153 myStream<<aString.ToCString();
159 operator<<(SMESH::FilterLibrary_i* theArg)
161 myStream<<"aFilterLibrary"<<theArg;
167 operator<<(SMESH::FilterManager_i* theArg)
169 myStream<<"aFilterManager";
175 operator<<(SMESH::Filter_i* theArg)
177 myStream<<"aFilter"<<theArg;
183 operator<<(SMESH::Functor_i* theArg)
185 FunctorType aFunctorType = theArg->GetFunctorType();
186 switch(aFunctorType){
188 myStream<<"anAspectRatio";
190 case FT_AspectRatio3D:
191 myStream<<"anAspectRatio3D";
194 myStream<<"aWarping";
196 case FT_MinimumAngle:
197 myStream<<"aMinimumAngle";
209 myStream<<"aFreeBorders";
212 myStream<<"aFreeEdges";
214 case FT_MultiConnection:
215 myStream<<"aMultiConnection";
217 case FT_MultiConnection2D:
218 myStream<<"aMultiConnection2D";
226 case FT_BelongToGeom:
227 myStream<<"aBelongToGeom";
229 case FT_BelongToPlane:
230 myStream<<"aBelongToPlane";
232 case FT_BelongToCylinder:
233 myStream<<"aBelongToCylinder";
236 myStream<<"aLyingOnGeom";
239 myStream<<"aRangeOfIds";
241 case FT_BadOrientedVolume:
242 myStream<<"aBadOrientedVolume";
245 myStream<<"aLessThan";
248 myStream<<"aMoreThan";
251 myStream<<"anEqualTo";
254 myStream<<"aLogicalNOT";
257 myStream<<"aLogicalAND";
260 myStream<<"aLogicalOR";
263 myStream<<"anUndefined";
271 //=======================================================================
272 //function : DumpPython
274 //=======================================================================
275 Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Object_ptr theStudy,
276 CORBA::Boolean isPublished,
277 CORBA::Boolean& isValidScript)
279 SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
280 if (CORBA::is_nil(aStudy))
281 return new Engines::TMPFile(0);
283 SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
284 if (CORBA::is_nil(aSO))
285 return new Engines::TMPFile(0);
287 // Map study entries to object names
288 Resource_DataMapOfAsciiStringAsciiString aMap;
289 Resource_DataMapOfAsciiStringAsciiString aMapNames;
290 TCollection_AsciiString s ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
292 SALOMEDS::ChildIterator_var Itr = aStudy->NewChildIterator(aSO);
293 for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
294 SALOMEDS::SObject_var aValue = Itr->Value();
296 TCollection_AsciiString aName (aValue->GetName());
297 TCollection_AsciiString aGUIName (aName);
298 if (aName.Length() > 0) {
299 aMapNames.Bind(TCollection_AsciiString(aValue->GetID()), aGUIName);
300 int p, p2 = 1, e = aName.Length();
301 while ((p = aName.FirstLocationNotInSet(s, p2, e))) {
302 aName.SetValue(p, '_');
305 aMap.Bind(TCollection_AsciiString(aValue->GetID()), aName);
309 // Get trace of restored study
310 //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
311 SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
312 SALOMEDS::GenericAttribute_var anAttr =
313 aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
315 char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
316 TCollection_AsciiString aSavedTrace (oldValue);
318 // Add trace of API methods calls and replace study entries by names
319 TCollection_AsciiString aScript =
320 SALOMEDSImpl_Study::GetDumpStudyComment("SMESH") + "\n\n" +
321 DumpPython_impl(aStudy->StudyId(), aMap, aMapNames, isPublished, isValidScript, aSavedTrace);
323 int aLen = aScript.Length();
324 unsigned char* aBuffer = new unsigned char[aLen+1];
325 strcpy((char*)aBuffer, aScript.ToCString());
327 CORBA::Octet* anOctetBuf = (CORBA::Octet*)aBuffer;
328 Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aLen+1, aLen+1, anOctetBuf, 1);
330 bool hasNotPublishedObjects = aScript.Location( NotPublishedObjectName(), 1, aLen);
331 isValidScript = isValidScript && !hasNotPublishedObjects;
333 return aStreamFile._retn();
336 //=============================================================================
340 //=============================================================================
341 void SMESH_Gen_i::AddToPythonScript (int theStudyID, const TCollection_AsciiString& theString)
343 if (myPythonScripts.find(theStudyID) == myPythonScripts.end()) {
344 myPythonScripts[theStudyID] = new TColStd_HSequenceOfAsciiString;
346 myPythonScripts[theStudyID]->Append(theString);
349 //=============================================================================
351 * RemoveLastFromPythonScript
353 //=============================================================================
354 void SMESH_Gen_i::RemoveLastFromPythonScript (int theStudyID)
356 if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
357 int aLen = myPythonScripts[theStudyID]->Length();
358 myPythonScripts[theStudyID]->Remove(aLen);
362 //=======================================================================
363 //function : AddToCurrentPyScript
365 //=======================================================================
367 void SMESH_Gen_i::AddToCurrentPyScript (const TCollection_AsciiString& theString)
369 SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
370 SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
371 if (aStudy->_is_nil()) return;
372 aSMESHGen->AddToPythonScript(aStudy->StudyId(), theString);
376 //=======================================================================
377 //function : AddObject
378 //purpose : add object to script string
379 //=======================================================================
381 TCollection_AsciiString& SMESH_Gen_i::AddObject(TCollection_AsciiString& theStr,
382 CORBA::Object_ptr theObject)
384 TCollection_AsciiString aString("None");
385 SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
386 SALOMEDS::SObject_var aSObject =
387 aSMESHGen->ObjectToSObject(aSMESHGen->GetCurrentStudy(), theObject);
388 if ( !aSObject->_is_nil() ) {
389 aString = aSObject->GetID();
390 } else if ( !CORBA::is_nil( theObject )) {
391 aString = "smeshObj_";
392 if ( aSMESHGen->CanPublishInStudy( theObject )) // not published SMESH object
393 aString += (int) theObject;
395 aString = NotPublishedObjectName();
401 //=======================================================================
402 //function : SavePython
404 //=======================================================================
405 void SMESH_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
407 // Dump trace of API methods calls
408 TCollection_AsciiString aScript = GetNewPythonLines(theStudy->StudyId());
410 // Check contents of PythonObject attribute
411 SALOMEDS::SObject_var aSO = theStudy->FindComponent(ComponentDataType());
412 //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
413 SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
414 SALOMEDS::GenericAttribute_var anAttr =
415 aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
417 char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
418 TCollection_AsciiString oldScript (oldValue);
420 if (oldScript.Length() > 0) {
422 oldScript += aScript;
427 // Store in PythonObject attribute
428 SALOMEDS::AttributePythonObject::_narrow(anAttr)->SetObject(oldScript.ToCString(), 1);
430 // Clean trace of API methods calls
431 CleanPythonTrace(theStudy->StudyId());
438 //=============================================================================
440 * FindEntries: Returns a sequence of start/end positions of entries in the string
442 //=============================================================================
443 Handle(TColStd_HSequenceOfInteger) FindEntries (TCollection_AsciiString& theString)
445 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
446 Standard_Integer aLen = theString.Length();
447 Standard_Boolean isFound = Standard_False;
449 char* arr = theString.ToCString();
450 Standard_Integer i = 0, j;
455 if(c >= 48 && c <= 57) { //Is digit?
457 isFound = Standard_False;
458 while((j < aLen) && ((c >= 48 && c <= 57) || c == 58) ) { //Check if it is an entry
460 if(c == 58) isFound = Standard_True;
464 int prev = (i < 1) ? 0 : (int)arr[i - 1];
465 // last char should be a diggit,
466 // previous char should not be '"'.
467 if (arr[j-2] != 58 && prev != 34) {
468 aSeq->Append(i+1); // +1 because AsciiString starts from 1
480 //=============================================================================
484 //=============================================================================
485 TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
487 Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
488 Resource_DataMapOfAsciiStringAsciiString& theNames,
491 const TCollection_AsciiString& theSavedTrace)
493 TCollection_AsciiString aScript;
494 aScript = "def RebuildData(theStudy):";
495 aScript += "\n\tsmesh = salome.lcc.FindOrLoadComponent(\"FactoryServer\", \"SMESH\")";
496 aScript += "\n\taFilterManager = smesh.CreateFilterManager()";
498 aScript += "\n\tsmesh.SetCurrentStudy(theStudy)";
500 aScript += "\n\tsmesh.SetCurrentStudy(None)";
502 // Dump trace of restored study
503 if (theSavedTrace.Length() > 0) {
505 aScript += theSavedTrace;
508 // Dump trace of API methods calls
509 TCollection_AsciiString aNewLines = GetNewPythonLines(theStudyID);
510 if (aNewLines.Length() > 0) {
512 aScript += aNewLines;
515 // Find entries to be replaced by names
516 Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
517 Standard_Integer aLen = aSeq->Length();
522 // Replace entries by the names
523 GEOM::GEOM_Gen_ptr geom = GetGeomEngine();
524 TColStd_SequenceOfAsciiString seqRemoved;
525 Resource_DataMapOfAsciiStringAsciiString mapRemoved;
526 Standard_Integer objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
527 TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("smeshObj_");
529 // Collect names of GEOM objects to exclude same names for SMESH objects
530 GEOM::string_array_var aGeomNames = geom->GetAllDumpNames();
531 int ign = 0, nbgn = aGeomNames->length();
532 for (; ign < nbgn; ign++) {
533 aName = aGeomNames[ign];
534 theObjectNames.Bind(aName, "1");
537 bool importGeom = false;
538 for (Standard_Integer i = 1; i <= aLen; i += 2) {
539 anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i) - 1);
540 anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
542 aName = geom->GetDumpName( anEntry.ToCString() );
543 if (aName.IsEmpty()) {
545 if (theObjectNames.IsBound(anEntry)) {
546 // The Object is in Study
547 aName = theObjectNames.Find(anEntry);
548 if ( aName.IsIntegerValue() ) // aName must not start with a digit
549 aName.Insert( 1, 'a' );
550 if (theObjectNames.IsBound(aName) && anEntry != theObjectNames(aName)) {
551 // diff objects have same name - make a new name
552 TCollection_AsciiString aName2;
553 Standard_Integer i = 0;
555 aName2 = aName + "_" + ++i;
556 } while (theObjectNames.IsBound(aName2) && anEntry != theObjectNames(aName2));
558 theObjectNames(anEntry) = aName;
563 aName = aBaseName + TCollection_AsciiString(++objectCounter);
564 } while (theObjectNames.IsBound(aName));
565 seqRemoved.Append(aName);
566 mapRemoved.Bind(anEntry, "1");
567 theObjectNames.Bind(anEntry, aName);
569 theObjectNames.Bind(aName, anEntry); // to detect same name of diff objects
575 anUpdatedScript += aName;
576 aStart = aSeq->Value(i + 1) + 1;
579 // set initial part of aSript
580 TCollection_AsciiString initPart = "import salome, SMESH, StdMeshers\n\n";
583 initPart += ("import string, os, sys, re\n"
584 "sys.path.insert( 0, os.path.dirname(__file__) )\n"
585 "exec(\"from \"+re.sub(\"SMESH$\",\"GEOM\",__name__)+\" import *\")\n\n");
587 anUpdatedScript.Insert ( 1, initPart );
589 // add final part of aScript
590 if (aSeq->Value(aLen) < aScriptLength)
591 anUpdatedScript += aScript.SubString(aSeq->Value(aLen) + 1, aScriptLength);
593 // Remove removed objects
594 anUpdatedScript += "\n\taStudyBuilder = theStudy.NewBuilder()";
595 for (int ir = 1; ir <= seqRemoved.Length(); ir++) {
596 anUpdatedScript += "\n\tSO = theStudy.FindObjectIOR(theStudy.ConvertObjectToIOR(";
597 anUpdatedScript += seqRemoved.Value(ir);
598 anUpdatedScript += "))\n\tif SO is not None: aStudyBuilder.RemoveObjectWithChildren(SO)";
602 anUpdatedScript += "\n\n\tisGUIMode = ";
603 anUpdatedScript += isPublished;
604 anUpdatedScript += "\n\tif isGUIMode:";
605 anUpdatedScript += "\n\t\tsmeshgui = salome.ImportComponentGUI(\"SMESH\")";
606 anUpdatedScript += "\n\t\tsmeshgui.Init(theStudy._get_StudyId())";
607 anUpdatedScript += "\n";
609 TCollection_AsciiString aGUIName;
610 Resource_DataMapOfAsciiStringAsciiString mapEntries;
611 for (Standard_Integer i = 1; i <= aLen; i += 2) {
612 anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
613 aName = geom->GetDumpName( anEntry.ToCString() );
614 if (aName.IsEmpty() && // Not a GEOM object
615 theNames.IsBound(anEntry) &&
616 !mapEntries.IsBound(anEntry) && // Not yet processed
617 !mapRemoved.IsBound(anEntry)) { // Was not removed
618 aName = theObjectNames.Find(anEntry);
619 aGUIName = theNames.Find(anEntry);
620 mapEntries.Bind(anEntry, aName);
621 anUpdatedScript += "\n\t\tsmeshgui.SetName(salome.ObjectToID(";
622 anUpdatedScript += aName + "), \"" + aGUIName + "\")";
625 anUpdatedScript += "\n\n\t\tsalome.sg.updateObjBrowser(0)";
627 anUpdatedScript += "\n\n\tpass\n";
631 return anUpdatedScript;
634 //=============================================================================
638 //=============================================================================
639 TCollection_AsciiString SMESH_Gen_i::GetNewPythonLines (int theStudyID)
641 TCollection_AsciiString aScript;
643 // Dump trace of API methods calls
644 if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
645 Handle(TColStd_HSequenceOfAsciiString) aPythonScript = myPythonScripts[theStudyID];
646 Standard_Integer istr, aLen = aPythonScript->Length();
647 for (istr = 1; istr <= aLen; istr++) {
649 aScript += aPythonScript->Value(istr);
657 //=============================================================================
661 //=============================================================================
662 void SMESH_Gen_i::CleanPythonTrace (int theStudyID)
664 TCollection_AsciiString aScript;
666 // Clean trace of API methods calls
667 if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
668 myPythonScripts[theStudyID]->Clear();