Back to index

salome-smesh  6.5.0
SMESH_DumpPython.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 //  File    : SMESH_DumpPython.cxx
00023 //  Created : Thu Mar 24 17:17:59 2005
00024 //  Author  : Julia DOROVSKIKH
00025 //  Module  : SMESH
00026 
00027 #include "SMESH_PythonDump.hxx"
00028 #include "SMESH_Gen_i.hxx"
00029 #include "SMESH_Filter_i.hxx"
00030 #include "SMESH_MeshEditor_i.hxx"
00031 #include "SMESH_2smeshpy.hxx"
00032 
00033 #include <TColStd_HSequenceOfInteger.hxx>
00034 #include <TCollection_AsciiString.hxx>
00035 #include <SMESH_Comment.hxx>
00036 
00037 
00038 #ifdef _DEBUG_
00039 static int MYDEBUG = 0;
00040 #else
00041 static int MYDEBUG = 0;
00042 #endif
00043 
00044 static TCollection_AsciiString NotPublishedObjectName()
00045 {
00046   return "__NOT__Published__Object__";
00047 }
00048 
00049 namespace SMESH
00050 {
00051 
00052   size_t TPythonDump::myCounter = 0;
00053 
00054   TVar::TVar(CORBA::Double value):myVals(1) { myVals[0] = SMESH_Comment(value); }
00055   TVar::TVar(CORBA::Long   value):myVals(1) { myVals[0] = SMESH_Comment(value); }
00056   TVar::TVar(CORBA::Short  value):myVals(1) { myVals[0] = SMESH_Comment(value); }
00057   TVar::TVar(const SMESH::double_array& value):myVals(value.length())
00058   {
00059     for ( size_t i = 0; i < value.length(); i++)
00060       myVals[i] = SMESH_Comment(value[i]);
00061   }
00062 
00063   TPythonDump::
00064   TPythonDump():myVarsCounter(0)
00065   {
00066     ++myCounter;
00067   }
00068   TPythonDump::
00069   ~TPythonDump()
00070   {
00071     if(--myCounter == 0){
00072       SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
00073       std::string aString = myStream.str();
00074       TCollection_AsciiString aCollection(Standard_CString(aString.c_str()));
00075       SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
00076       if(!aStudy->_is_nil() && !aCollection.IsEmpty()){
00077         aSMESHGen->AddToPythonScript(aStudy->StudyId(),aCollection);
00078         if(MYDEBUG) MESSAGE(aString);
00079         aSMESHGen->UpdateParameters(""); // prevent misuse of already treated variables
00080       }
00081     }
00082   }
00083 
00084   TPythonDump& 
00085   TPythonDump::
00086   operator<<(const TVar& theVarValue)
00087   {
00088     if ( theVarValue.myVals.empty() ) return *this;
00089 
00090     const std::vector< std::string >& varNames = SMESH_Gen_i::GetSMESHGen()->GetLastParameters();
00091     if ( theVarValue.myVals.size() > 1 )
00092     {
00093       myStream << "[ ";
00094       for ( size_t i = 1; i <= theVarValue.myVals.size(); ++i )
00095       {
00096         if ( myVarsCounter < varNames.size() && !varNames[ myVarsCounter ].empty() )
00097           myStream << TVar::Quote() << varNames[ myVarsCounter ] << TVar::Quote();
00098         else
00099           myStream << theVarValue.myVals[i-1];
00100         if ( i < theVarValue.myVals.size() )
00101           myStream << ", ";
00102         ++myVarsCounter;
00103       }
00104       myStream << " ]";
00105     }
00106     else
00107     {
00108       if ( myVarsCounter < varNames.size() && !varNames[ myVarsCounter ].empty() )
00109         myStream << TVar::Quote() << varNames[ myVarsCounter ] << TVar::Quote();
00110       else
00111         myStream << theVarValue.myVals[0];
00112       ++myVarsCounter;
00113     }
00114     return *this;
00115   }
00116 
00117   TPythonDump&
00118   TPythonDump::
00119   operator<<(long int theArg){
00120     myStream<<theArg;
00121     return *this;
00122   }
00123 
00124   TPythonDump&
00125   TPythonDump::
00126   operator<<(int theArg){
00127     myStream<<theArg;
00128     return *this;
00129   }
00130 
00131   TPythonDump&
00132   TPythonDump::
00133   operator<<(double theArg){
00134     myStream<<theArg;
00135     return *this;
00136   }
00137 
00138   TPythonDump&
00139   TPythonDump::
00140   operator<<(float theArg){
00141     myStream<<theArg;
00142     return *this;
00143   }
00144 
00145   TPythonDump&
00146   TPythonDump::
00147   operator<<(const void* theArg){
00148     myStream<<theArg;
00149     return *this;
00150   }
00151 
00152   TPythonDump&
00153   TPythonDump::
00154   operator<<(const char* theArg){
00155     if ( theArg )
00156       myStream<<theArg;
00157     return *this;
00158   }
00159 
00160   TPythonDump&
00161   TPythonDump::
00162   operator<<(const SMESH::ElementType& theArg)
00163   {
00164     myStream<<"SMESH.";
00165     switch(theArg){
00166     case ALL:   myStream<<"ALL";break;
00167     case NODE:  myStream<<"NODE";break;
00168     case EDGE:  myStream<<"EDGE";break;
00169     case FACE:  myStream<<"FACE";break;
00170     case VOLUME:myStream<<"VOLUME";break;
00171     case ELEM0D:myStream<<"ELEM0D";break;
00172     default:    myStream<<"__UNKNOWN__ElementType: " << theArg;
00173     }
00174     return *this;
00175   }
00176 
00177   TPythonDump&
00178   TPythonDump::
00179   operator<<(const SMESH::GeometryType& theArg)
00180   {
00181     myStream<<"SMESH.";
00182     switch(theArg){
00183     case Geom_POINT:      myStream<<"Geom_POINT";      break;
00184     case Geom_EDGE:       myStream<<"Geom_EDGE";       break;
00185     case Geom_TRIANGLE:   myStream<<"Geom_TRIANGLE";   break;
00186     case Geom_QUADRANGLE: myStream<<"Geom_QUADRANGLE"; break;
00187     case Geom_POLYGON:    myStream<<"Geom_POLYGON";    break;
00188     case Geom_TETRA:      myStream<<"Geom_TETRA";      break;
00189     case Geom_PYRAMID:    myStream<<"Geom_PYRAMID";    break;
00190     case Geom_HEXA:       myStream<<"Geom_HEXA";       break;
00191     case Geom_PENTA:      myStream<<"Geom_PENTA";      break;
00192     case Geom_POLYHEDRA:  myStream<<"Geom_POLYHEDRA";  break;
00193     default:    myStream<<"__UNKNOWN__GeometryType: " << theArg;
00194     }
00195     return *this;
00196   }
00197 
00198   template<class TArray>
00199   void DumpArray(const TArray& theArray, TPythonDump & theStream)
00200   {
00201     theStream << "[ ";
00202     for (int i = 1; i <= theArray.length(); i++) {
00203       theStream << theArray[i-1];
00204       if ( i < theArray.length() )
00205         theStream << ", ";
00206     }
00207     theStream << " ]";
00208   }
00209 
00210   TPythonDump&
00211   TPythonDump::operator<<(const SMESH::long_array& theArg)
00212   {
00213     DumpArray( theArg, *this );
00214     return *this;
00215   }
00216 
00217   TPythonDump&
00218   TPythonDump::operator<<(const SMESH::double_array& theArg)
00219   {
00220     DumpArray( theArg, *this );
00221     return *this;
00222   }
00223 
00224   TPythonDump&
00225   TPythonDump::operator<<(const SMESH::string_array& theArray)
00226   {
00227     myStream << "[ ";
00228     for (int i = 1; i <= theArray.length(); i++) {
00229       myStream << "'" << theArray[i-1] << "'";
00230       if ( i < theArray.length() )
00231         myStream << ", ";
00232     }
00233     myStream << " ]";
00234     return *this;
00235   }
00236 
00237   TPythonDump&
00238   TPythonDump::
00239   operator<<(SALOMEDS::SObject_ptr aSObject)
00240   {
00241     if ( !aSObject->_is_nil() )
00242       myStream << aSObject->GetID();
00243     else
00244       myStream << NotPublishedObjectName();
00245     return *this;
00246   }
00247 
00248   TPythonDump&
00249   TPythonDump::
00250   operator<<(CORBA::Object_ptr theArg)
00251   {
00252     SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
00253     SALOMEDS::Study_var aStudy = aSMESHGen->GetCurrentStudy();
00254     SALOMEDS::SObject_var aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
00255     if(!aSObject->_is_nil()) {
00256       CORBA::String_var id = aSObject->GetID();
00257       myStream << id;
00258     } else if ( !CORBA::is_nil(theArg)) {
00259       if ( aSMESHGen->CanPublishInStudy( theArg )) // not published SMESH object
00260         myStream << "smeshObj_" << size_t(theArg);
00261       else
00262         myStream << NotPublishedObjectName();
00263     }
00264     else
00265       myStream << "None";
00266     return *this;
00267   }
00268 
00269   TPythonDump&
00270   TPythonDump::
00271   operator<<(SMESH::SMESH_Hypothesis_ptr theArg)
00272   {
00273     SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->GetCurrentStudy();
00274     SALOMEDS::SObject_var aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
00275     if(aSObject->_is_nil() && !CORBA::is_nil(theArg))
00276       myStream << "hyp_" << theArg->GetId();
00277     else
00278       *this << CORBA::Object_ptr( theArg );
00279     return *this;
00280   }
00281 
00282   TPythonDump&
00283   TPythonDump::
00284   operator<<(SMESH::SMESH_IDSource_ptr theArg)
00285   {
00286     if ( CORBA::is_nil( theArg ) )
00287       return *this << "None";
00288     SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
00289     SALOMEDS::Study_var aStudy = aSMESHGen->GetCurrentStudy();
00290     SALOMEDS::SObject_var aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
00291     if(!aSObject->_is_nil())
00292       return *this << aSObject;
00293     if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theArg ))
00294       return *this << filter;
00295     SMESH::SMESH_Mesh_var mesh = theArg->GetMesh();
00296     if ( !theArg->_is_equivalent( mesh ))
00297     {
00298       SMESH::long_array_var anElementsId = theArg->GetIDs();
00299       SMESH::array_of_ElementType_var types =  theArg->GetTypes();
00300       SMESH::ElementType type = types->length() ? types[0] : SMESH::ALL;
00301       return *this << mesh << ".GetIDSource(" << anElementsId << ", " << type << ")";
00302     }
00303     return *this;
00304   }
00305 
00306   TPythonDump&
00307   TPythonDump::
00308   operator<<(SMESH::FilterLibrary_i* theArg)
00309   {
00310     myStream<<"aFilterLibrary"<<theArg;
00311     return *this;
00312   }
00313 
00314   TPythonDump&
00315   TPythonDump::
00316   operator<<(SMESH::FilterManager_i* theArg)
00317   {
00318     myStream<<"aFilterManager";
00319     return *this;
00320   }
00321 
00322   TPythonDump&
00323   TPythonDump::
00324   operator<<(SMESH::Filter_i* theArg)
00325   {
00326     myStream<<"aFilter"<<theArg;
00327     return *this;
00328   }
00329 
00330   TPythonDump&
00331   TPythonDump::
00332   operator<<(SMESH::Functor_i* theArg)
00333   {
00334     if ( theArg ) {
00335       FunctorType aFunctorType = theArg->GetFunctorType();
00336       switch(aFunctorType){
00337       case FT_AspectRatio:           myStream<< "anAspectRatio";          break;
00338       case FT_AspectRatio3D:         myStream<< "anAspectRatio3D";        break;
00339       case FT_Warping:               myStream<< "aWarping";               break;
00340       case FT_MinimumAngle:          myStream<< "aMinimumAngle";          break;
00341       case FT_Taper:                 myStream<< "aTaper";                 break;
00342       case FT_Skew:                  myStream<< "aSkew";                  break;
00343       case FT_Area:                  myStream<< "aArea";                  break;
00344       case FT_Volume3D:              myStream<< "aVolume3D";              break;
00345       case FT_MaxElementLength2D:    myStream<< "aMaxElementLength2D";    break;
00346       case FT_MaxElementLength3D:    myStream<< "aMaxElementLength3D";    break;
00347       case FT_FreeBorders:           myStream<< "aFreeBorders";           break;
00348       case FT_FreeEdges:             myStream<< "aFreeEdges";             break;
00349       case FT_FreeNodes:             myStream<< "aFreeNodes";             break;
00350       case FT_FreeFaces:             myStream<< "aFreeFaces";             break;
00351       case FT_MultiConnection:       myStream<< "aMultiConnection";       break;
00352       case FT_MultiConnection2D:     myStream<< "aMultiConnection2D";     break;
00353       case FT_Length:                myStream<< "aLength";                break;
00354       case FT_Length2D:              myStream<< "aLength2D";              break;
00355       case FT_BelongToGeom:          myStream<< "aBelongToGeom";          break;
00356       case FT_BelongToPlane:         myStream<< "aBelongToPlane";         break;
00357       case FT_BelongToCylinder:      myStream<< "aBelongToCylinder";      break;
00358       case FT_BelongToGenSurface:    myStream<< "aBelongToGenSurface";    break;
00359       case FT_LyingOnGeom:           myStream<< "aLyingOnGeom";           break;
00360       case FT_CoplanarFaces:         myStream<< "aCoplanarFaces";         break;
00361       case FT_RangeOfIds:            myStream<< "aRangeOfIds";            break;
00362       case FT_BadOrientedVolume:     myStream<< "aBadOrientedVolume";     break;
00363       case FT_BareBorderVolume:      myStream<< "aBareBorderVolume";      break;
00364       case FT_BareBorderFace:        myStream<< "aBareBorderFace";        break;
00365       case FT_OverConstrainedVolume: myStream<< "aOverConstrainedVolume"; break;
00366       case FT_OverConstrainedFace:   myStream<< "aOverConstrainedFace";   break;
00367       case FT_LinearOrQuadratic:     myStream<< "aLinearOrQuadratic";     break;
00368       case FT_GroupColor:            myStream<< "aGroupColor";            break;
00369       case FT_ElemGeomType:          myStream<< "anElemGeomType";         break;
00370       case FT_LessThan:              myStream<< "aLessThan";              break;
00371       case FT_MoreThan:              myStream<< "aMoreThan";              break;
00372       case FT_EqualTo:               myStream<< "anEqualTo";              break;
00373       case FT_LogicalNOT:            myStream<< "aLogicalNOT";            break;
00374       case FT_LogicalAND:            myStream<< "aLogicalAND";            break;
00375       case FT_LogicalOR:             myStream<< "aLogicalOR";             break;
00376       case FT_Undefined:
00377       default:                       myStream<< "anUndefined";            break;
00378       }
00379       myStream<<theArg;
00380     }
00381     return *this;
00382   }
00383 
00384   TPythonDump&
00385   TPythonDump::
00386   operator<<(SMESH::Measurements_i* theArg)
00387   {
00388     myStream<<"aMeasurements";
00389     return *this;
00390   }
00391 
00392 
00393   TPythonDump& TPythonDump:: operator<<(SMESH_Gen_i* theArg)
00394   {
00395     myStream << SMESHGenName(); return *this;
00396   }
00397 
00398   TPythonDump& TPythonDump::operator<<(SMESH_MeshEditor_i* theArg)
00399   {
00400     myStream << MeshEditorName() << "_" << ( theArg ? theArg->GetMeshId() : -1 ); return *this;
00401   }
00402 
00403   TPythonDump& TPythonDump::operator<<(const TCollection_AsciiString & theStr)
00404   {
00405     myStream << theStr; return *this;
00406   }
00407 
00408 
00409   TPythonDump& TPythonDump::operator<<(SMESH::MED_VERSION theVersion)
00410   {
00411     switch (theVersion) {
00412     case SMESH::MED_V2_1: myStream << "SMESH.MED_V2_1"; break;
00413     case SMESH::MED_V2_2: myStream << "SMESH.MED_V2_2"; break;
00414     default: myStream << theVersion;
00415     }
00416     return *this;
00417   }
00418 
00419   TPythonDump& TPythonDump::operator<<(const SMESH::AxisStruct & theAxis)
00420   {
00421     *this << "SMESH.AxisStruct( "
00422           << TVar( theAxis.x  ) << ", "
00423           << TVar( theAxis.y  ) << ", "
00424           << TVar( theAxis.z  ) << ", "
00425           << TVar( theAxis.vx ) << ", "
00426           << TVar( theAxis.vy ) << ", "
00427           << TVar( theAxis.vz ) << " )";
00428     return *this;
00429   }
00430 
00431   TPythonDump& TPythonDump::operator<<(const SMESH::DirStruct & theDir)
00432   {
00433     const SMESH::PointStruct & P = theDir.PS;
00434     *this << "SMESH.DirStruct( SMESH.PointStruct ( "
00435           << TVar( P.x ) << ", "
00436           << TVar( P.y ) << ", "
00437           << TVar( P.z ) << " ))";
00438     return *this;
00439   }
00440 
00441   TPythonDump& TPythonDump::operator<<(const SMESH::PointStruct & P)
00442   {
00443     *this << "SMESH.PointStruct ( "
00444           << TVar( P.x ) << ", "
00445           << TVar( P.y ) << ", "
00446           << TVar( P.z ) << " )";
00447     return *this;
00448   }
00449 
00450   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfGroups& theList)
00451   {
00452     DumpArray( theList, *this );
00453     return *this;
00454   }
00455   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfGroups * theList)
00456   {
00457     DumpArray( *theList, *this );
00458     return *this;
00459   }
00460   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfIDSources& theList)
00461   {
00462     DumpArray( theList, *this );
00463     return *this;
00464   }
00465 
00466   TCollection_AsciiString myLongStringStart( "TPythonDump::LongStringStart" );
00467   TCollection_AsciiString myLongStringEnd  ( "TPythonDump::LongStringEnd" );
00468 
00469   //================================================================================
00476   //================================================================================
00477 
00478   TCollection_AsciiString TPythonDump::LongStringStart(const char* type)
00479   {
00480     return
00481       myLongStringStart +
00482       (Standard_Integer) strlen(type) +
00483       " " +
00484       (char*) type;
00485   }
00486 
00487   //================================================================================
00493   //================================================================================
00494 
00495   TCollection_AsciiString TPythonDump::LongStringEnd()
00496   {
00497     return myLongStringEnd;
00498   }
00499 
00500   //================================================================================
00512   //================================================================================
00513 
00514   bool  TPythonDump::CutoutLongString( TCollection_AsciiString & theText,
00515                                        int                     & theFrom,
00516                                        TCollection_AsciiString & theLongString,
00517                                        TCollection_AsciiString & theStringType)
00518   {
00519     if ( theFrom < 1 || theFrom > theText.Length() )
00520       return false;
00521 
00522     // ...script \  beg marker    \ \ type \       literal              \  end marker  \ script...
00523     //  "theText myLongStringStart7 Pattern!!! SALOME Mesh Pattern file myLongStringEndtextEnd"
00524     //  012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
00525     //  0         1         2         3         4         5         6         7         8
00526 
00527     theFrom = theText.Location( myLongStringStart, theFrom, theText.Length() ); // = 09
00528     if ( !theFrom )
00529       return false;
00530 
00531     // find where literal begins
00532     int literalBeg = theFrom + myLongStringStart.Length(); // = 26
00533     char* typeLenStr = (char*) theText.ToCString() + literalBeg - 1; // = "7 Pattern!!! SALO...."
00534     int typeLen = atoi ( typeLenStr ); // = 7
00535     while ( *typeLenStr != ' ' ) { // look for ' ' after typeLen
00536       literalBeg++; // 26 -> 27
00537       typeLenStr++;
00538     }
00539     literalBeg += typeLen + 1; // = 35
00540     if ( literalBeg > theText.Length() )
00541       return false;
00542 
00543     // where literal ends (i.e. end marker begins)
00544     int literalEnd = theText.Location( myLongStringEnd, literalBeg, theText.Length() ); // = 64
00545     if ( !literalEnd )
00546       literalEnd = theText.Length();
00547 
00548     // literal
00549     theLongString = theText.SubString( literalBeg, literalEnd - 1); // "!!! SALOME Mesh Pattern file "
00550     // type
00551     theStringType = theText.SubString( literalBeg - typeLen, literalBeg - 1 ); // "Pattern"
00552     // cut off literal
00553     literalEnd += myLongStringEnd.Length(); // = 79
00554     TCollection_AsciiString textEnd = theText.SubString( literalEnd, theText.Length() ); // "textE..."
00555     theText = theText.SubString( 1, theFrom - 1 ) + textEnd;
00556 
00557     return true;
00558   }
00559 }
00560 
00561 //=======================================================================
00562 //function : RemoveTabulation
00563 //purpose  : 
00564 //=======================================================================
00565 void RemoveTabulation( TCollection_AsciiString& theScript )
00566 {
00567   std::string aString( theScript.ToCString() );
00568   std::string::size_type aPos = 0;
00569   while( aPos < aString.length() )
00570   {
00571     aPos = aString.find( "\n\t", aPos );
00572     if( aPos == std::string::npos )
00573       break;
00574     aString.replace( aPos, 2, "\n" );
00575     aPos++;
00576   }
00577   theScript = aString.c_str();
00578 }
00579 
00580 //=======================================================================
00581 //function : DumpPython
00582 //purpose  :
00583 //=======================================================================
00584 Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Object_ptr theStudy,
00585                                            CORBA::Boolean isPublished,
00586                                            CORBA::Boolean isMultiFile,
00587                                            CORBA::Boolean& isValidScript)
00588 {
00589   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
00590   if (CORBA::is_nil(aStudy))
00591     return new Engines::TMPFile(0);
00592 
00593   SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
00594   if (CORBA::is_nil(aSO))
00595     return new Engines::TMPFile(0);
00596 
00597   // Map study entries to object names
00598   Resource_DataMapOfAsciiStringAsciiString aMap;
00599   Resource_DataMapOfAsciiStringAsciiString aMapNames;
00600   //TCollection_AsciiString s ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
00601 
00602   SALOMEDS::ChildIterator_var Itr = aStudy->NewChildIterator(aSO);
00603   for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
00604     SALOMEDS::SObject_var aValue = Itr->Value();
00605     CORBA::String_var anID = aValue->GetID();
00606     CORBA::String_var aName = aValue->GetName();
00607     TCollection_AsciiString aGUIName ( (char*) aName.in() );
00608     TCollection_AsciiString anEnrty ( (char*) anID.in() );
00609     if (aGUIName.Length() > 0) {
00610       aMapNames.Bind( anEnrty, aGUIName );
00611       aMap.Bind( anEnrty, aGUIName );
00612     }
00613   }
00614 
00615   // Get trace of restored study
00616   //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
00617   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
00618   SALOMEDS::GenericAttribute_var anAttr =
00619     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
00620 
00621   char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
00622   TCollection_AsciiString aSavedTrace (oldValue);
00623 
00624   // Add trace of API methods calls and replace study entries by names
00625   TCollection_AsciiString aScript;
00626   aScript += DumpPython_impl(aStudy, aMap, aMapNames, isPublished, isMultiFile,
00627                              myIsHistoricalPythonDump, isValidScript, aSavedTrace);
00628 
00629   int aLen = aScript.Length();
00630   unsigned char* aBuffer = new unsigned char[aLen+1];
00631   strcpy((char*)aBuffer, aScript.ToCString());
00632 
00633   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
00634   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aLen+1, aLen+1, anOctetBuf, 1);
00635 
00636   bool hasNotPublishedObjects = aScript.Location( NotPublishedObjectName(), 1, aLen);
00637   isValidScript = isValidScript && !hasNotPublishedObjects;
00638 
00639   return aStreamFile._retn();
00640 }
00641 
00642 //=============================================================================
00646 //=============================================================================
00647 void SMESH_Gen_i::AddToPythonScript (int theStudyID, const TCollection_AsciiString& theString)
00648 {
00649   if (myPythonScripts.find(theStudyID) == myPythonScripts.end()) {
00650     myPythonScripts[theStudyID] = new TColStd_HSequenceOfAsciiString;
00651   }
00652   myPythonScripts[theStudyID]->Append(theString);
00653 }
00654 
00655 //=============================================================================
00659 //=============================================================================
00660 void SMESH_Gen_i::RemoveLastFromPythonScript (int theStudyID)
00661 {
00662   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
00663     int aLen = myPythonScripts[theStudyID]->Length();
00664     myPythonScripts[theStudyID]->Remove(aLen);
00665   }
00666 }
00667 
00668 //=======================================================================
00669 //function : SavePython
00670 //purpose  :
00671 //=======================================================================
00672 void SMESH_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
00673 {
00674   // Dump trace of API methods calls
00675   TCollection_AsciiString aScript = GetNewPythonLines(theStudy->StudyId());
00676 
00677   // Check contents of PythonObject attribute
00678   SALOMEDS::SObject_var aSO = theStudy->FindComponent(ComponentDataType());
00679   //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
00680   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
00681   SALOMEDS::GenericAttribute_var anAttr =
00682     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
00683 
00684   char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
00685   TCollection_AsciiString oldScript (oldValue);
00686 
00687   if (oldScript.Length() > 0) {
00688     oldScript += "\n";
00689     oldScript += aScript;
00690   } else {
00691     oldScript = aScript;
00692   }
00693 
00694   // Store in PythonObject attribute
00695   SALOMEDS::AttributePythonObject::_narrow(anAttr)->SetObject(oldScript.ToCString(), 1);
00696 
00697   // Clean trace of API methods calls
00698   CleanPythonTrace(theStudy->StudyId());
00699 }
00700 
00701 
00702 // impl
00703 
00704 
00705 //=============================================================================
00709 //=============================================================================
00710 Handle(TColStd_HSequenceOfInteger) FindEntries (TCollection_AsciiString& theString)
00711 {
00712   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
00713   Standard_Integer aLen = theString.Length();
00714   Standard_Boolean isFound = Standard_False;
00715 
00716   char* arr = (char*) theString.ToCString();
00717   Standard_Integer i = 0, j;
00718 
00719   while(i < aLen) {
00720     int c = (int)arr[i];
00721     j = i+1;
00722     if ( isdigit( c )) { //Is digit?
00723 
00724       isFound = Standard_False;
00725       while((j < aLen) && ( isdigit(c) || c == ':' )) { //Check if it is an entry
00726         c = (int)arr[j++];
00727         if(c == ':') isFound = Standard_True;
00728       }
00729 
00730       if (isFound) {
00731         int prev = (i < 1) ? 0 : (int)arr[i - 1];
00732         // to distinguish from a sketcher command:
00733         // last char should be a digit, not ":",
00734         // previous char should not be '"'.
00735         if (arr[j-2] != ':' && prev != '"') {
00736           aSeq->Append(i+1); // +1 because AsciiString starts from 1
00737           aSeq->Append(j-1);
00738         }
00739       }
00740     }
00741 
00742     i = j;
00743   }
00744 
00745   return aSeq;
00746 }
00747 
00748 namespace {
00749 
00750   //================================================================================
00756   //================================================================================
00757 
00758   bool fixPythonName(TCollection_AsciiString & aName )
00759   {
00760     const TCollection_AsciiString allowedChars =
00761       "qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_";
00762     bool isValidName = true;
00763     int nbUnderscore = 0;
00764     int p=1; // replace not allowed chars by underscore
00765     while (p <= aName.Length() &&
00766            (p = aName.FirstLocationNotInSet(allowedChars, p, aName.Length())))
00767     {
00768       if ( p == 1 || p == aName.Length() || aName.Value(p-1) == '_')
00769         aName.Remove( p, 1 ); // remove double _ from the start and the end
00770       else
00771         aName.SetValue(p, '_'), nbUnderscore++;
00772       isValidName = false;
00773     }
00774     if ( aName.IsIntegerValue() ) { // aName must not start with a digit
00775       aName.Insert( 1, 'a' );
00776       isValidName = false;
00777     }
00778     // shorten names like CartesianParameters3D_400_400_400_1000000_1
00779     if ( aName.Length() > 20 && nbUnderscore > 2 )
00780     {
00781       p = aName.Location( "_", 20, aName.Length());
00782       if ( p > 1 )
00783         aName.Trunc( p-1 );
00784     }
00785     return isValidName;
00786   }
00787 }
00788 
00789 //=============================================================================
00793 //=============================================================================
00794 TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
00795                         (SALOMEDS::Study_ptr theStudy,
00796                          Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
00797                          Resource_DataMapOfAsciiStringAsciiString& theNames,
00798                          bool isPublished,
00799                          bool isMultiFile,
00800                          bool isHistoricalDump,
00801                          bool& aValidScript,
00802                          const TCollection_AsciiString& theSavedTrace)
00803 {
00804   int aStudyID = theStudy->StudyId();
00805 
00806   TCollection_AsciiString helper; // to comfortably concatenate C strings
00807   TCollection_AsciiString aSmeshpy( SMESH_2smeshpy::SmeshpyName() );
00808   TCollection_AsciiString aSMESHGen( SMESH_2smeshpy::GenName() );
00809   TCollection_AsciiString anOldGen( SMESH::TPythonDump::SMESHGenName() );
00810 
00811   TCollection_AsciiString aScript;
00812   if( isMultiFile )
00813     aScript += "def RebuildData(theStudy):";
00814   aScript += "\n\t";
00815   aScript += helper + "aFilterManager = " + aSMESHGen + ".CreateFilterManager()\n\t";
00816   aScript += helper + "aMeasurements = " + aSMESHGen + ".CreateMeasurements()\n\t";
00817   if ( isPublished )
00818     aScript += aSMESHGen + ".SetCurrentStudy(theStudy)";
00819   else
00820     aScript += aSMESHGen + ".SetCurrentStudy(None)";
00821 
00822   // import python files corresponding to plugins
00823   set<string> moduleNameSet;
00824   map<string, GenericHypothesisCreator_i*>::iterator hyp_creator = myHypCreatorMap.begin();
00825   for ( ; hyp_creator != myHypCreatorMap.end(); ++hyp_creator ) {
00826     string moduleName = hyp_creator->second->GetModuleName();
00827     bool newModule = moduleNameSet.insert( moduleName ).second;
00828     if ( newModule )
00829       aScript += helper + "\n\t" + "import " + (char*) moduleName.c_str();
00830   }
00831 
00832   // Dump trace of restored study
00833   if (theSavedTrace.Length() > 0) {
00834     // For the convertion of IDL API calls -> smesh.py API, "smesh" standing for SMESH_Gen
00835     // was replaces with "smeshgen" (==TPythonDump::SMESHGenName()).
00836     // Change "smesh" -> "smeshgen" in the trace saved before passage to smesh.py API
00837     bool isNewVersion =
00838       theSavedTrace.Location( anOldGen + ".", 1, theSavedTrace.Length() );
00839     if ( !isNewVersion ) {
00840       TCollection_AsciiString aSavedTrace( theSavedTrace );
00841       TCollection_AsciiString aSmeshCall ( "smesh." ), gen( "gen" );
00842       int beg, end = aSavedTrace.Length(), from = 1;
00843       while ( from < end && ( beg = aSavedTrace.Location( aSmeshCall, from, end ))) {
00844         char charBefore = ( beg == 1 ) ? ' ' : aSavedTrace.Value( beg - 1 );
00845         if ( isspace( charBefore ) || charBefore == '=' ) { // "smesh." is not a part of a long word
00846           aSavedTrace.Insert( beg + aSmeshCall.Length() - 1, gen );// "smesh" -> "smeshgen"
00847           end += gen.Length();
00848         }
00849         from = beg + aSmeshCall.Length();
00850       }
00851       aScript += helper + "\n" + aSavedTrace;
00852     }
00853     else
00854       // append a saved trace to the script
00855       aScript += helper + "\n" + theSavedTrace;
00856   }
00857 
00858   // Dump trace of API methods calls
00859   TCollection_AsciiString aNewLines = GetNewPythonLines(aStudyID);
00860   if (aNewLines.Length() > 0) {
00861     aScript += helper + "\n" + aNewLines;
00862   }
00863 
00864   // Convert IDL API calls into smesh.py API.
00865   // Some objects are wrapped with python classes and
00866   // Resource_DataMapOfAsciiStringAsciiString holds methods returning wrapped objects
00867   Resource_DataMapOfAsciiStringAsciiString anEntry2AccessorMethod;
00868   if ( !getenv("NO_2smeshpy_conversion"))
00869     aScript = SMESH_2smeshpy::ConvertScript( aScript, anEntry2AccessorMethod,
00870                                              theObjectNames, theStudy, isHistoricalDump );
00871 
00872   // Replace characters used instead of quote marks to quote notebook variables
00873   {
00874     int pos = 1;
00875     while (( pos = aScript.Location( 1, SMESH::TVar::Quote(), pos, aScript.Length() )))
00876       aScript.SetValue( pos, '"' );
00877   }
00878 
00879   // Find entries to be replaced by names
00880   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
00881   Standard_Integer aLen = aSeq->Length();
00882 
00883   if (aLen == 0 && isMultiFile)
00884     return aScript;
00885 
00886   // Replace entries by the names
00887   GEOM::GEOM_Gen_ptr geom = GetGeomEngine();
00888   TColStd_SequenceOfAsciiString seqRemoved;
00889   Resource_DataMapOfAsciiStringAsciiString mapRemoved;
00890   Standard_Integer objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
00891   TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("smeshObj_");
00892 
00893   // Collect names of GEOM objects to exclude same names of SMESH objects
00894   GEOM::string_array_var aGeomNames = geom->GetAllDumpNames();
00895   int ign = 0, nbgn = aGeomNames->length();
00896   for (; ign < nbgn; ign++) {
00897     aName = aGeomNames[ign];
00898     theObjectNames.Bind(aName, "1");
00899   }
00900 
00901   bool importGeom = false;
00902   for (Standard_Integer i = 1; i <= aLen; i += 2) {
00903     anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i) - 1);
00904     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
00905     // is a GEOM object?
00906     aName = geom->GetDumpName( anEntry.ToCString() );
00907     if (aName.IsEmpty()) {
00908       // is a SMESH object
00909       if (theObjectNames.IsBound(anEntry)) {
00910         // The Object is in Study
00911         aName = theObjectNames.Find(anEntry);
00912         // check validity of aName
00913         bool isValidName = fixPythonName( aName );
00914         if (theObjectNames.IsBound(aName) && anEntry != theObjectNames(aName)) {
00915           // diff objects have same name - make a new name by appending a digit
00916           TCollection_AsciiString aName2;
00917           Standard_Integer i = 0;
00918           do {
00919             aName2 = aName + "_" + ++i;
00920           } while (theObjectNames.IsBound(aName2) && anEntry != theObjectNames(aName2));
00921           aName = aName2;
00922           isValidName = false;
00923         }
00924         if ( !isValidName )
00925           theObjectNames(anEntry) = aName;
00926 
00927       } else {
00928         // Removed Object
00929         do {
00930           aName = aBaseName + (++objectCounter);
00931         } while (theObjectNames.IsBound(aName));
00932         seqRemoved.Append(aName);
00933         mapRemoved.Bind(anEntry, "1");
00934         theObjectNames.Bind(anEntry, aName);
00935       }
00936       theObjectNames.Bind(aName, anEntry); // to detect same name of diff objects
00937     }
00938     else
00939     {
00940       importGeom = true;
00941     }
00942     anUpdatedScript += aName;
00943     aStart = aSeq->Value(i + 1) + 1;
00944   }
00945 
00946   // set initial part of aSript
00947   TCollection_AsciiString initPart = "import ";
00948   if ( isMultiFile )
00949     initPart += helper + "salome, ";
00950   initPart += aSmeshpy + ", SMESH, SALOMEDS\n";
00951   if ( importGeom && isMultiFile )
00952   {
00953     initPart += ("\n## import GEOM dump file ## \n"
00954                  "import string, os, sys, re\n"
00955                  "sys.path.insert( 0, os.path.dirname(__file__) )\n"
00956                  "exec(\"from \"+re.sub(\"SMESH$\",\"GEOM\",__name__)+\" import *\")\n");
00957   }
00958   anUpdatedScript.Insert ( 1, initPart );
00959 
00960   // add final part of aScript
00961   if (aLen && aSeq->Value(aLen) < aScriptLength)
00962     anUpdatedScript += aScript.SubString(aSeq->Value(aLen) + 1, aScriptLength);
00963 
00964   // Remove removed objects
00965   if ( seqRemoved.Length() > 0 ) {
00966     anUpdatedScript += "\n\t## some objects were removed";
00967     anUpdatedScript += "\n\taStudyBuilder = theStudy.NewBuilder()";
00968   }
00969   for (int ir = 1; ir <= seqRemoved.Length(); ir++) {
00970     anUpdatedScript += "\n\tSO = theStudy.FindObjectIOR(theStudy.ConvertObjectToIOR(";
00971     anUpdatedScript += seqRemoved.Value(ir);
00972     // for object wrapped by class of smesh.py
00973     anEntry = theObjectNames( seqRemoved.Value(ir) );
00974     if ( anEntry2AccessorMethod.IsBound( anEntry ) )
00975       anUpdatedScript += helper + "." + anEntry2AccessorMethod( anEntry );
00976     anUpdatedScript += "))\n\tif SO is not None: aStudyBuilder.RemoveObjectWithChildren(SO)";
00977   }
00978 
00979   // Set object names
00980   anUpdatedScript += "\n\t## set object names";
00981 //   anUpdatedScript += "\n\t\tsmeshgui = salome.ImportComponentGUI(\"SMESH\")";
00982 //   anUpdatedScript += "\n\t\tsmeshgui.Init(theStudy._get_StudyId())";
00983 //   anUpdatedScript += "\n";
00984 
00985   TCollection_AsciiString aGUIName;
00986   Resource_DataMapOfAsciiStringAsciiString mapEntries;
00987   for (Standard_Integer i = 1; i <= aLen; i += 2)
00988   {
00989     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
00990     aName = geom->GetDumpName( anEntry.ToCString() );
00991     if (aName.IsEmpty() && // Not a GEOM object
00992         theNames.IsBound(anEntry) &&
00993         !mapEntries.IsBound(anEntry) && // Not yet processed
00994         !mapRemoved.IsBound(anEntry)) // Was not removed
00995     {
00996       aName = theObjectNames.Find(anEntry);
00997       aGUIName = theNames.Find(anEntry);
00998       mapEntries.Bind(anEntry, aName);
00999       anUpdatedScript += helper + "\n\t" + aSMESHGen + ".SetName(" + aName;
01000       if ( anEntry2AccessorMethod.IsBound( anEntry ) )
01001         anUpdatedScript += helper + "." + anEntry2AccessorMethod( anEntry );
01002       anUpdatedScript += helper + ", '" + aGUIName + "')";
01003     }
01004   }
01005 
01006   // Issue 0021249: removed (a similar block is dumped by SALOMEDSImpl_Study)
01007   //anUpdatedScript += "\n\tif salome.sg.hasDesktop():";
01008   //anUpdatedScript += "\n\t\tsalome.sg.updateObjBrowser(0)";
01009 
01010   // -----------------------------------------------------------------
01011   // store visual properties of displayed objects
01012   // -----------------------------------------------------------------
01013 
01014   if (isPublished)
01015   {
01016     //Output the script that sets up the visual parameters.
01017     char* script = theStudy->GetDefaultScript(ComponentDataType(), "\t");
01018     if (script && strlen(script) > 0) {
01019       anUpdatedScript += "\n\n\t### Store presentation parameters of displayed objects\n";
01020       anUpdatedScript += script;
01021       CORBA::string_free(script);
01022     }
01023   }
01024 
01025   if( isMultiFile )
01026     anUpdatedScript += "\n\tpass";
01027   anUpdatedScript += "\n";
01028 
01029   if( !isMultiFile ) // remove unnecessary tabulation
01030     RemoveTabulation( anUpdatedScript );
01031 
01032   // -----------------------------------------------------------------
01033   // put string literals describing patterns into separate functions
01034   // -----------------------------------------------------------------
01035 
01036   TCollection_AsciiString aLongString, aFunctionType;
01037   int where = 1;
01038   set< string > functionNameSet;
01039   while ( SMESH::TPythonDump::CutoutLongString( anUpdatedScript, where, aLongString, aFunctionType ))
01040   {
01041     // make a python string literal
01042     aLongString.Prepend(":\n\treturn '''\n");
01043     aLongString += "\n\t'''\n\tpass\n";
01044 
01045     TCollection_AsciiString functionName;
01046 
01047     // check if the function returning this literal is already defined
01048     int posAlready = anUpdatedScript.Location( aLongString, where, anUpdatedScript.Length() );
01049     if ( posAlready ) // already defined
01050     {
01051       // find the function name
01052       int functBeg = posAlready;
01053       char* script = (char*) anUpdatedScript.ToCString() + posAlready - 1; // look at ":" after "def fuction()"
01054       while ( *script != ' ' ) {
01055         script--;
01056         functBeg--;
01057       }
01058       functBeg++; // do not take ' '
01059       posAlready--; // do not take ':'
01060       functionName = anUpdatedScript.SubString( functBeg, posAlready );
01061     }
01062     else // not defined yet
01063     {
01064       // find a unique function name
01065       fixPythonName( aFunctionType );
01066       Standard_Integer nb = 0;
01067       do functionName = aFunctionType + "_" + ( nb++ ) + "()";
01068       while ( !functionNameSet.insert( functionName.ToCString() ).second );
01069 
01070       // define function
01071       TCollection_AsciiString funDef = helper + "def " + functionName + aLongString;
01072       if ( isMultiFile )
01073       {
01074         anUpdatedScript += helper + "\n\n" + funDef;
01075       }
01076       else
01077       {
01078         funDef += "\n\n";
01079         anUpdatedScript.Insert( 1, funDef);
01080         where += funDef.Length();
01081       }
01082     }
01083     anUpdatedScript.InsertBefore( where, functionName ); // call function
01084   }
01085 
01086   aValidScript = true;
01087 
01088   return anUpdatedScript;
01089 }
01090 
01091 //=============================================================================
01095 //=============================================================================
01096 TCollection_AsciiString SMESH_Gen_i::GetNewPythonLines (int theStudyID)
01097 {
01098   TCollection_AsciiString aScript;
01099 
01100   // Dump trace of API methods calls
01101   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
01102     Handle(TColStd_HSequenceOfAsciiString) aPythonScript = myPythonScripts[theStudyID];
01103     Standard_Integer istr, aLen = aPythonScript->Length();
01104     for (istr = 1; istr <= aLen; istr++) {
01105       aScript += "\n\t";
01106       aScript += aPythonScript->Value(istr);
01107     }
01108     aScript += "\n";
01109   }
01110 
01111   return aScript;
01112 }
01113 
01114 //=============================================================================
01118 //=============================================================================
01119 void SMESH_Gen_i::CleanPythonTrace (int theStudyID)
01120 {
01121   TCollection_AsciiString aScript;
01122 
01123   // Clean trace of API methods calls
01124   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
01125     myPythonScripts[theStudyID]->Clear();
01126   }
01127 }