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"
11 #include <TColStd_HSequenceOfInteger.hxx>
12 #include <TCollection_AsciiString.hxx>
16 static int MYDEBUG = 0;
18 static int MYDEBUG = 0;
21 static TCollection_AsciiString NotPublishedObjectName()
23 return "__NOT__Published__Object__";
29 size_t TPythonDump::myCounter = 0;
40 SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
41 SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
42 if(!aStudy->_is_nil()){
43 std::string aString = myStream.str();
44 TCollection_AsciiString aCollection(Standard_CString(aString.c_str()));
45 aSMESHGen->AddToPythonScript(aStudy->StudyId(),aCollection);
46 if(MYDEBUG) MESSAGE(aString);
53 operator<<(long int theArg){
60 operator<<(int theArg){
67 operator<<(double theArg){
74 operator<<(float theArg){
81 operator<<(const void* theArg){
88 operator<<(const char* theArg){
95 operator<<(const SMESH::ElementType& theArg)
121 operator<<(const SMESH::long_array& theArg)
124 CORBA::Long i = 1, iEnd = theArg.length();
125 for(; i <= iEnd; i++) {
126 myStream<<theArg[i-1];
137 operator<<(CORBA::Object_ptr theArg)
139 TCollection_AsciiString aString("None");
140 SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
141 SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
142 SALOMEDS::SObject_var aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
143 if(!aSObject->_is_nil()){
144 aString = aSObject->GetID();
145 }else if(!CORBA::is_nil(theArg)){
146 aString = "smeshObj_";
147 if ( aSMESHGen->CanPublishInStudy( theArg )) // not published SMESH object
148 aString += (int) theArg;
150 aString = NotPublishedObjectName();
152 myStream<<aString.ToCString();
158 operator<<(SMESH::FilterLibrary_i* theArg)
160 myStream<<"aFilterLibrary"<<theArg;
166 operator<<(SMESH::FilterManager_i* theArg)
168 myStream<<"aFilterManager";
174 operator<<(SMESH::Filter_i* theArg)
176 myStream<<"aFilter"<<theArg;
182 operator<<(SMESH::Functor_i* theArg)
184 FunctorType aFunctorType = theArg->GetFunctorType();
185 switch(aFunctorType){
187 myStream<<"anAspectRatio";
189 case FT_AspectRatio3D:
190 myStream<<"anAspectRatio3D";
193 myStream<<"aWarping";
195 case FT_MinimumAngle:
196 myStream<<"aMinimumAngle";
208 myStream<<"aFreeBorders";
211 myStream<<"aFreeEdges";
213 case FT_MultiConnection:
214 myStream<<"aMultiConnection";
216 case FT_MultiConnection2D:
217 myStream<<"aMultiConnection2D";
225 case FT_BelongToGeom:
226 myStream<<"aBelongToGeom";
228 case FT_BelongToPlane:
229 myStream<<"aBelongToPlane";
231 case FT_BelongToCylinder:
232 myStream<<"aBelongToCylinder";
235 myStream<<"aLyingOnGeom";
238 myStream<<"aRangeOfIds";
240 case FT_BadOrientedVolume:
241 myStream<<"aBadOrientedVolume";
244 myStream<<"aLessThan";
247 myStream<<"aMoreThan";
250 myStream<<"anEqualTo";
253 myStream<<"aLogicalNOT";
256 myStream<<"aLogicalAND";
259 myStream<<"aLogicalOR";
262 myStream<<"anUndefined";
270 //=======================================================================
271 //function : DumpPython
273 //=======================================================================
274 Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Object_ptr theStudy,
275 CORBA::Boolean isPublished,
276 CORBA::Boolean& isValidScript)
278 SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
279 if (CORBA::is_nil(aStudy))
280 return new Engines::TMPFile(0);
282 SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
283 if (CORBA::is_nil(aSO))
284 return new Engines::TMPFile(0);
286 // Map study entries to object names
287 Resource_DataMapOfAsciiStringAsciiString aMap;
288 Resource_DataMapOfAsciiStringAsciiString aMapNames;
289 TCollection_AsciiString s ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
291 SALOMEDS::ChildIterator_var Itr = aStudy->NewChildIterator(aSO);
292 for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
293 SALOMEDS::SObject_var aValue = Itr->Value();
294 CORBA::String_var anID = aValue->GetID();
295 CORBA::String_var aName = aValue->GetName();
296 TCollection_AsciiString aGUIName ( (char*) aName.in() );
297 TCollection_AsciiString anEnrty ( (char*) anID.in() );
298 if (aGUIName.Length() > 0) {
299 aMapNames.Bind( anEnrty, aGUIName );
300 aMap.Bind( anEnrty, aGUIName );
304 // Get trace of restored study
305 //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
306 SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
307 SALOMEDS::GenericAttribute_var anAttr =
308 aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
310 char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
311 TCollection_AsciiString aSavedTrace (oldValue);
313 // Add trace of API methods calls and replace study entries by names
314 //TCollection_AsciiString aScript =
315 // SALOMEDSImpl_Study::GetDumpStudyComment("SMESH") + "\n\n" +
316 // DumpPython_impl(aStudy->StudyId(), aMap, aMapNames, isPublished, isValidScript, aSavedTrace);
317 TCollection_AsciiString aScript =
318 "### This file is generated by SALOME automatically by dump python functionality of SMESH component\n\n";
319 aScript += DumpPython_impl(aStudy->StudyId(), aMap, aMapNames,
320 isPublished, isValidScript, aSavedTrace);
322 int aLen = aScript.Length();
323 unsigned char* aBuffer = new unsigned char[aLen+1];
324 strcpy((char*)aBuffer, aScript.ToCString());
326 CORBA::Octet* anOctetBuf = (CORBA::Octet*)aBuffer;
327 Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aLen+1, aLen+1, anOctetBuf, 1);
329 bool hasNotPublishedObjects = aScript.Location( NotPublishedObjectName(), 1, aLen);
330 isValidScript = isValidScript && !hasNotPublishedObjects;
332 return aStreamFile._retn();
335 //=============================================================================
339 //=============================================================================
340 void SMESH_Gen_i::AddToPythonScript (int theStudyID, const TCollection_AsciiString& theString)
342 if (myPythonScripts.find(theStudyID) == myPythonScripts.end()) {
343 myPythonScripts[theStudyID] = new TColStd_HSequenceOfAsciiString;
345 myPythonScripts[theStudyID]->Append(theString);
348 //=============================================================================
350 * RemoveLastFromPythonScript
352 //=============================================================================
353 void SMESH_Gen_i::RemoveLastFromPythonScript (int theStudyID)
355 if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
356 int aLen = myPythonScripts[theStudyID]->Length();
357 myPythonScripts[theStudyID]->Remove(aLen);
361 //=======================================================================
362 //function : AddToCurrentPyScript
364 //=======================================================================
366 void SMESH_Gen_i::AddToCurrentPyScript (const TCollection_AsciiString& theString)
368 SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
369 SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
370 if (aStudy->_is_nil()) return;
371 aSMESHGen->AddToPythonScript(aStudy->StudyId(), theString);
375 //=======================================================================
376 //function : AddObject
377 //purpose : add object to script string
378 //=======================================================================
380 TCollection_AsciiString& SMESH_Gen_i::AddObject(TCollection_AsciiString& theStr,
381 CORBA::Object_ptr theObject)
383 TCollection_AsciiString aString("None");
384 SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
385 SALOMEDS::SObject_var aSObject =
386 aSMESHGen->ObjectToSObject(aSMESHGen->GetCurrentStudy(), theObject);
387 if ( !aSObject->_is_nil() ) {
388 aString = aSObject->GetID();
389 } else if ( !CORBA::is_nil( theObject )) {
390 aString = "smeshObj_";
391 if ( aSMESHGen->CanPublishInStudy( theObject )) // not published SMESH object
392 aString += (int) theObject;
394 aString = NotPublishedObjectName();
400 //=======================================================================
401 //function : SavePython
403 //=======================================================================
404 void SMESH_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
406 // Dump trace of API methods calls
407 TCollection_AsciiString aScript = GetNewPythonLines(theStudy->StudyId());
409 // Check contents of PythonObject attribute
410 SALOMEDS::SObject_var aSO = theStudy->FindComponent(ComponentDataType());
411 //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
412 SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
413 SALOMEDS::GenericAttribute_var anAttr =
414 aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
416 char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
417 TCollection_AsciiString oldScript (oldValue);
419 if (oldScript.Length() > 0) {
421 oldScript += aScript;
426 // Store in PythonObject attribute
427 SALOMEDS::AttributePythonObject::_narrow(anAttr)->SetObject(oldScript.ToCString(), 1);
429 // Clean trace of API methods calls
430 CleanPythonTrace(theStudy->StudyId());
437 //=============================================================================
439 * FindEntries: Returns a sequence of start/end positions of entries in the string
441 //=============================================================================
442 Handle(TColStd_HSequenceOfInteger) FindEntries (TCollection_AsciiString& theString)
444 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
445 Standard_Integer aLen = theString.Length();
446 Standard_Boolean isFound = Standard_False;
448 char* arr = theString.ToCString();
449 Standard_Integer i = 0, j;
454 if(c >= 48 && c <= 57) { //Is digit?
456 isFound = Standard_False;
457 while((j < aLen) && ((c >= 48 && c <= 57) || c == 58) ) { //Check if it is an entry
459 if(c == 58) isFound = Standard_True;
463 int prev = (i < 1) ? 0 : (int)arr[i - 1];
464 // last char should be a diggit,
465 // previous char should not be '"'.
466 if (arr[j-2] != 58 && prev != 34) {
467 aSeq->Append(i+1); // +1 because AsciiString starts from 1
479 //=============================================================================
483 //=============================================================================
484 TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
486 Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
487 Resource_DataMapOfAsciiStringAsciiString& theNames,
490 const TCollection_AsciiString& theSavedTrace)
492 TCollection_AsciiString aScript;
493 aScript = "def RebuildData(theStudy):";
494 aScript += "\n\tsmesh = salome.lcc.FindOrLoadComponent(\"FactoryServer\", \"SMESH\")";
495 aScript += "\n\taFilterManager = smesh.CreateFilterManager()";
497 aScript += "\n\tsmesh.SetCurrentStudy(theStudy)";
499 aScript += "\n\tsmesh.SetCurrentStudy(None)";
501 // Dump trace of restored study
502 if (theSavedTrace.Length() > 0) {
504 aScript += theSavedTrace;
507 // Dump trace of API methods calls
508 TCollection_AsciiString aNewLines = GetNewPythonLines(theStudyID);
509 if (aNewLines.Length() > 0) {
511 aScript += aNewLines;
514 // Find entries to be replaced by names
515 Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
516 Standard_Integer aLen = aSeq->Length();
521 // Replace entries by the names
522 GEOM::GEOM_Gen_ptr geom = GetGeomEngine();
523 TColStd_SequenceOfAsciiString seqRemoved;
524 Resource_DataMapOfAsciiStringAsciiString mapRemoved;
525 Standard_Integer objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
526 TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("smeshObj_"),
527 allowedChars ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
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 // check validity of aName
549 bool isValidName = true;
550 if ( aName.IsIntegerValue() ) { // aName must not start with a digit
551 aName.Insert( 1, 'a' );
554 int p, p2=1; // replace not allowed chars
555 while ((p = aName.FirstLocationNotInSet(allowedChars, p2, aName.Length()))) {
556 aName.SetValue(p, '_');
560 if (theObjectNames.IsBound(aName) && anEntry != theObjectNames(aName)) {
561 // diff objects have same name - make a new name by appending a digit
562 TCollection_AsciiString aName2;
563 Standard_Integer i = 0;
565 aName2 = aName + "_" + ++i;
566 } while (theObjectNames.IsBound(aName2) && anEntry != theObjectNames(aName2));
571 theObjectNames(anEntry) = aName;
576 aName = aBaseName + TCollection_AsciiString(++objectCounter);
577 } while (theObjectNames.IsBound(aName));
578 seqRemoved.Append(aName);
579 mapRemoved.Bind(anEntry, "1");
580 theObjectNames.Bind(anEntry, aName);
582 theObjectNames.Bind(aName, anEntry); // to detect same name of diff objects
588 anUpdatedScript += aName;
589 aStart = aSeq->Value(i + 1) + 1;
592 // set initial part of aSript
593 TCollection_AsciiString initPart = "import salome, SMESH, StdMeshers\n\n";
596 initPart += ("import string, os, sys, re\n"
597 "sys.path.insert( 0, os.path.dirname(__file__) )\n"
598 "exec(\"from \"+re.sub(\"SMESH$\",\"GEOM\",__name__)+\" import *\")\n\n");
600 anUpdatedScript.Insert ( 1, initPart );
602 // add final part of aScript
603 if (aSeq->Value(aLen) < aScriptLength)
604 anUpdatedScript += aScript.SubString(aSeq->Value(aLen) + 1, aScriptLength);
606 // Remove removed objects
607 anUpdatedScript += "\n\taStudyBuilder = theStudy.NewBuilder()";
608 for (int ir = 1; ir <= seqRemoved.Length(); ir++) {
609 anUpdatedScript += "\n\tSO = theStudy.FindObjectIOR(theStudy.ConvertObjectToIOR(";
610 anUpdatedScript += seqRemoved.Value(ir);
611 anUpdatedScript += "))\n\tif SO is not None: aStudyBuilder.RemoveObjectWithChildren(SO)";
615 anUpdatedScript += "\n\n\tisGUIMode = ";
616 anUpdatedScript += isPublished;
617 anUpdatedScript += "\n\tif isGUIMode:";
618 anUpdatedScript += "\n\t\tsmeshgui = salome.ImportComponentGUI(\"SMESH\")";
619 anUpdatedScript += "\n\t\tsmeshgui.Init(theStudy._get_StudyId())";
620 anUpdatedScript += "\n";
622 TCollection_AsciiString aGUIName;
623 Resource_DataMapOfAsciiStringAsciiString mapEntries;
624 for (Standard_Integer i = 1; i <= aLen; i += 2) {
625 anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
626 aName = geom->GetDumpName( anEntry.ToCString() );
627 if (aName.IsEmpty() && // Not a GEOM object
628 theNames.IsBound(anEntry) &&
629 !mapEntries.IsBound(anEntry) && // Not yet processed
630 !mapRemoved.IsBound(anEntry)) { // Was not removed
631 aName = theObjectNames.Find(anEntry);
632 aGUIName = theNames.Find(anEntry);
633 mapEntries.Bind(anEntry, aName);
634 anUpdatedScript += "\n\t\tsmeshgui.SetName(salome.ObjectToID(";
635 anUpdatedScript += aName + "), \"" + aGUIName + "\")";
638 anUpdatedScript += "\n\n\t\tsalome.sg.updateObjBrowser(0)";
640 anUpdatedScript += "\n\n\tpass\n";
644 return anUpdatedScript;
647 //=============================================================================
651 //=============================================================================
652 TCollection_AsciiString SMESH_Gen_i::GetNewPythonLines (int theStudyID)
654 TCollection_AsciiString aScript;
656 // Dump trace of API methods calls
657 if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
658 Handle(TColStd_HSequenceOfAsciiString) aPythonScript = myPythonScripts[theStudyID];
659 Standard_Integer istr, aLen = aPythonScript->Length();
660 for (istr = 1; istr <= aLen; istr++) {
662 aScript += aPythonScript->Value(istr);
670 //=============================================================================
674 //=============================================================================
675 void SMESH_Gen_i::CleanPythonTrace (int theStudyID)
677 TCollection_AsciiString aScript;
679 // Clean trace of API methods calls
680 if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
681 myPythonScripts[theStudyID]->Clear();