Salome HOME
Fix Compilation issue
[modules/multipr.git] / src / MULTIPR / MULTIPR_i.cxx
index e9dd3a2a335a9872fc2155b76918cdf3e69cb145..7e2b7db45edf2d7ce39259fad0b888d6a8a28228 100644 (file)
  * \brief   see MULTIPR_i.hxx
  *
  * \author  Olivier LE ROUX - CS, Virtual Reality Dpt
- * 
+ *
  * \date    01/2007
  */
+
 
 //*****************************************************************************
 // Includes section
 //*****************************************************************************
+
 using namespace std;
 
 #include "MULTIPR_i.hxx"
 #include "utilities.h"
 
 #include <string>
+#include <sstream>
 
 #include "MULTIPR_API.hxx"
 #include "MULTIPR_Exceptions.hxx"
+#include "MULTIPR_Utils.hxx"
+
+#include <SALOMEDS_Tool.hxx>
+
+#include CORBA_CLIENT_HEADER(SALOMEDS)
+#include CORBA_CLIENT_HEADER(SALOMEDS_Attributes)
+
+#ifdef _DEBUG_
+static int MYDEBUG = 1;
+#else
+static int MYDEBUG = 0;
+#endif
+
+// Dump Python utilities
+namespace MULTIPR
+{
+  class TPythonDump
+  {
+    std::ostringstream myStream;
+    static size_t myCounter;
+    //MULTIPR_ORB::MULTIPR_Gen_ptr myEngine;
+    MULTIPR_Gen_i* myEngine;
+
+  public:
+    //TPythonDump (MULTIPR_ORB::MULTIPR_Gen_ptr theEngine);
+    TPythonDump (MULTIPR_Gen_i* theEngine);
+    virtual ~TPythonDump();
+
+    TPythonDump& operator<< (long int theArg);
+    TPythonDump& operator<< (int theArg);
+    TPythonDump& operator<< (double theArg);
+    TPythonDump& operator<< (float theArg);
+    TPythonDump& operator<< (const void* theArg);
+    TPythonDump& operator<< (const char* theArg);
+
+    TPythonDump& operator<< (SALOMEDS::SObject_ptr theArg);
+    TPythonDump& operator<< (CORBA::Object_ptr theArg);
+
+    TPythonDump& operator<< (MULTIPR_ORB::MULTIPR_Gen_ptr theArg);
+    TPythonDump& operator<< (MULTIPR_ORB::MULTIPR_Obj_ptr theArg);
+
+    TPythonDump& operator<< (MULTIPR_Gen_i* theArg);
+    TPythonDump& operator<< (MULTIPR_Obj_i* theArg);
+
+    static char* MULTIPRGenName() { return "mpr_gen"; }
+    static char* MULTIPRObjName() { return "mpr_obj"; }
+  };
+
+  size_t TPythonDump::myCounter = 0;
+
+  //TPythonDump::TPythonDump (MULTIPR_ORB::MULTIPR_Gen_ptr theEngine)
+  TPythonDump::TPythonDump (MULTIPR_Gen_i* theEngine)
+  {
+    ++myCounter;
+    //myEngine = MULTIPR_ORB::MULTIPR_Gen::_duplicate(theEngine);
+    myEngine = theEngine;
+  }
+
+  TPythonDump::~TPythonDump()
+  {
+    if (--myCounter == 0)
+    {
+      SALOMEDS::Study_ptr aStudy = myEngine->GetCurrentStudy();
+      int aStudyID = -1;
+      if (!aStudy->_is_nil()) aStudyID = aStudy->StudyId();
+
+      std::string aString = myStream.str();
+      myEngine->AddToPythonScript(aStudyID, aString);
+      //if(MYDEBUG) MESSAGE(" *DP* " << aString.c_str());
+    }
+  }
+
+  TPythonDump& TPythonDump::operator<< (long int theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (int theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (double theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (float theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
 
+  TPythonDump& TPythonDump::operator<< (const void* theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (const char* theArg)
+  {
+    if (theArg)
+      myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (SALOMEDS::SObject_ptr aSObject)
+  {
+    if (aSObject->_is_nil())
+      myStream << "None";
+    else
+      myStream << "theStudy.FindObjectID(\"" << aSObject->GetID() << "\")";
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (CORBA::Object_ptr theArg)
+  {
+    if (CORBA::is_nil(theArg))
+      myStream << "None";
+    else
+      myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (MULTIPR_ORB::MULTIPR_Gen_ptr theArg)
+  {
+    myStream << MULTIPRGenName();
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (MULTIPR_ORB::MULTIPR_Obj_ptr theArg)
+  {
+    myStream << MULTIPRObjName();
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (MULTIPR_Gen_i* theArg)
+  {
+    myStream << MULTIPRGenName();
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (MULTIPR_Obj_i* theArg)
+  {
+    myStream << MULTIPRObjName();
+    return *this;
+  }
+}
 
 //*****************************************************************************
 // Class MULTIPR_Gen_i implementation
 //*****************************************************************************
 
 MULTIPR_Gen_i::MULTIPR_Gen_i(
-       CORBA::ORB_ptr orb,
-       PortableServer::POA_ptr poa,
-       PortableServer::ObjectId* contId, 
-       const char* instanceName, 
-       const char* interfaceName) :
-       Engines_Component_i(orb, poa, contId, instanceName, interfaceName)
+    CORBA::ORB_ptr orb,
+    PortableServer::POA_ptr poa,
+    PortableServer::ObjectId* contId,
+    const char* instanceName,
+    const char* interfaceName) :
+    Engines_Component_i(orb, poa, contId, instanceName, interfaceName)
 {
-       MESSAGE("activate object");
-       _thisObj = this ;
-       _id = _poa->activate_object(_thisObj);
+    MESSAGE("activate object");
+    _thisObj = this ;
+    _id = _poa->activate_object(_thisObj);
 }
 
 
@@ -55,96 +206,91 @@ MULTIPR_Gen_i::~MULTIPR_Gen_i()
 //-----------------------------------------------------------------------------
 
 char* MULTIPR_Gen_i::getVersion()
-       throw (SALOME::SALOME_Exception)
+    throw (SALOME::SALOME_Exception)
 {
-       return CORBA::string_dup(multipr::getVersion());
+    return CORBA::string_dup(multipr::getVersion());
 }
 
 
 void MULTIPR_Gen_i::partitionneDomaine(
-       const char* medFilename, 
-       const char* meshName)
-       throw (SALOME::SALOME_Exception)
-{
-       try
-       {
-               multipr::partitionneDomaine(medFilename, meshName);
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("partitionneDomaine() failed", SALOME::INTERNAL_ERROR);
-       }
-}
-
-
-void MULTIPR_Gen_i::partitionneGrain(
-       const char* medFilename, 
-       const char* partName, 
-       CORBA::Long nbParts, 
-       CORBA::Long partitionner)
-       throw (SALOME::SALOME_Exception)
-{
-       try
-       {
-               multipr::partitionneGrain(
-                       medFilename,
-                       partName,
-                       nbParts,
-                       partitionner);
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("partitionneGrain() failed", SALOME::INTERNAL_ERROR);
-       }
+    const char* medFilename,
+    const char* meshName)
+    throw (SALOME::SALOME_Exception)
+{
+    try
+    {
+        multipr::partitionneDomaine(medFilename, meshName);
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("partitionneDomaine() failed", SALOME::INTERNAL_ERROR);
+    }
+}
+
+
+void MULTIPR_Gen_i::partitionneGroupe(
+    const char* medFilename,
+    const char* partName,
+    CORBA::Long nbParts,
+    CORBA::Long partitionner)
+    throw (SALOME::SALOME_Exception)
+{
+    try
+    {
+        multipr::partitionneGroupe(
+            medFilename,
+            partName,
+            nbParts,
+            partitionner);
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("partitionneGroupe() failed", SALOME::INTERNAL_ERROR);
+    }
 }
 
 
 void MULTIPR_Gen_i::decimePartition(
-       const char*   medFilename, 
-       const char*   partName, 
-       const char*   fieldName,
-       CORBA::Long   fieldIt,
-       const char*   filterName,
-       CORBA::Double tmed,
-       CORBA::Double tlow,
-       CORBA::Double radius,
-       CORBA::Long   boxing)
-       throw (SALOME::SALOME_Exception)
-{
-       /*
-       // debug
-       cout << "File  : " << medFilename << endl;
-       cout << "Part  : " << partName    << endl;
-       cout << "Field : " << fieldName   << endl;
-       cout << "It    : " << fieldIt     << endl;
-       cout << "Filter: " << filterName  << endl;
-       cout << "Med   : " << tmed        << endl;
-       cout << "Low   : " << tlow        << endl;
-       cout << "Rad   : " << radius      << endl;
-       cout << "Box   : " << boxing      << endl;
-       cout << endl;
-       */
-       
-       try
-       {
-               multipr::decimePartition(
-                       medFilename, 
-                       partName, 
-                       fieldName,
-                       fieldIt,
-                       filterName,
-                       tmed,
-                       tlow,
-                       radius,
-                       boxing);
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("decimePartition() failed", SALOME::INTERNAL_ERROR);
-       }
+    const char*   medFilename,
+    const char*   partName,
+    const char*   fieldName,
+    CORBA::Long   fieldIt,
+    const char*   filterName,
+    const char*   filterParams)
+    throw (SALOME::SALOME_Exception)
+{
+
+    /*
+    // debug
+    cout << "File  : " << medFilename << endl;
+    cout << "Part  : " << partName    << endl;
+    cout << "Field : " << fieldName   << endl;
+    cout << "It    : " << fieldIt     << endl;
+    cout << "Filter: " << filterName  << endl;
+    cout << "Med   : " << tmed        << endl;
+    cout << "Low   : " << tlow        << endl;
+    cout << "Rad   : " << radius      << endl;
+    cout << "Box   : " << boxing      << endl;
+    cout << endl;
+    */
+
+    try
+    {
+        multipr::decimePartition(
+            medFilename,
+            partName,
+            fieldName,
+            fieldIt,
+            filterName,
+            filterParams);
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("decimePartition() failed", SALOME::INTERNAL_ERROR);
+    }
 }
 
 
@@ -153,333 +299,1413 @@ void MULTIPR_Gen_i::decimePartition(
 //-----------------------------------------------------------------------------
 
 MULTIPR_ORB::MULTIPR_Obj_ptr MULTIPR_Gen_i::getObject(const char* medFilename)
-       throw (SALOME::SALOME_Exception)
+    throw (SALOME::SALOME_Exception)
+{
+    MULTIPR_Obj_i* obj = new MULTIPR_Obj_i(_poa, medFilename);
+    obj->setEngine(this);
+
+    // Dump Python
+    MULTIPR::TPythonDump(this) << obj << " = " << this << ".getObject(\"" << medFilename << "\")";
+
+    return obj->POA_MULTIPR_ORB::MULTIPR_Obj::_this();
+}
+
+
+void MULTIPR_Gen_i::ObjModified (MULTIPR_ORB::MULTIPR_Obj_ptr theObj)
 {
-    MULTIPR_Obj_i* obj = new MULTIPR_Obj_i(medFilename);
-       return obj->POA_MULTIPR_ORB::MULTIPR_Obj::_this();
+  // Mark current study as modified, if theObj is published in it
+  if (!CORBA::is_nil(myCurrentStudy) && !CORBA::is_nil(theObj))
+  {
+    SALOMEDS::SObject_var aSO = myCurrentStudy->FindObjectIOR(_orb->object_to_string(theObj));
+    // if published
+    if (!CORBA::is_nil(aSO))
+      myCurrentStudy->Modified();
+  }
 }
 
 
-MULTIPR_Obj_i::MULTIPR_Obj_i(const char* medFilename)
-       throw (SALOME::SALOME_Exception)
+MULTIPR_Obj_i::MULTIPR_Obj_i(PortableServer::POA_ptr thePOA,
+                              const char* medFilename,
+                              bool isPersistence,
+                              bool isMultifile)
+    throw (SALOME::SALOME_Exception)
+    : SALOME::GenericObj_i(thePOA),
+      mBoxing(100),
+      _engine(NULL),
+      mIsTmp(isPersistence && !isMultifile)
 {
-       mObj    = new multipr::Obj();
-       mBoxing = 100;
-       
-       try
-       {
-               cout << "Load " << medFilename << endl;
-               mObj->create(medFilename);
-               cout << endl;
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               delete mObj;
-               mObj = NULL;
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to create object", SALOME::INTERNAL_ERROR);
-       }
+    mObj    = new multipr::Obj();
+
+    try
+    {
+        cout << "Load " << medFilename << endl;
+        if (isPersistence)
+          mObj->restorePersistent(medFilename);
+        else
+          mObj->create(medFilename);
+        cout << endl;
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        delete mObj;
+        mObj = NULL;
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to create object", SALOME::INTERNAL_ERROR);
+    }
 }
 
 
 MULTIPR_Obj_i::~MULTIPR_Obj_i()
 {
-       if (mObj != NULL)
-       {
-               delete mObj;
-               mObj = NULL;
-       }
+    if (mObj != NULL)
+    {
+        if (mIsTmp)
+        {
+            // Remove temporary files, created during study loading, together with directory
+            std::string strFile = mObj->getMEDFilename();
+            std::string strPath = multipr::getPath(strFile.c_str());
+#ifdef WNT
+            //std::string cmd_rm ("del /F \"");
+#else
+            std::string cmd_rm ("rm -rf \"");
+#endif
+            cmd_rm += strPath + "\"";
+            system(cmd_rm.c_str());
+        }
+
+        if(MYDEBUG) MESSAGE("MULTIPR_Obj_i: Destructor: remove mObj");
+        delete mObj;
+        mObj = NULL;
+    }
 }
 
+void MULTIPR_Obj_i::reset()
+        throw (SALOME::SALOME_Exception)
+{
+    mObj->reset();
+}
 
 CORBA::Boolean MULTIPR_Obj_i::isValidSequentialMEDFile()
-               throw (SALOME::SALOME_Exception)
+        throw (SALOME::SALOME_Exception)
 {
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       return mObj->isValidSequentialMEDFile();
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    return mObj->isValidSequentialMEDFile();
 }
 
 
 CORBA::Boolean MULTIPR_Obj_i::isValidDistributedMEDFile()
-       throw (SALOME::SALOME_Exception)
+    throw (SALOME::SALOME_Exception)
+{
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    return mObj->isValidDistributedMEDFile();
+}
+
+
+char* MULTIPR_Obj_i::getFilename()
+        throw (SALOME::SALOME_Exception)
 {
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       return mObj->isValidDistributedMEDFile();
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    return CORBA::string_dup(mObj->getMEDFilename().c_str());
+}
+
+
+char* MULTIPR_Obj_i::getSeqFilename()
+        throw (SALOME::SALOME_Exception)
+{
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    return CORBA::string_dup(mObj->getSequentialMEDFilename().c_str());
 }
 
 
 void MULTIPR_Obj_i::setMesh(const char* meshName)
-               throw (SALOME::SALOME_Exception)
+        throw (SALOME::SALOME_Exception)
 {
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       try
-       {
-               mObj->setMesh(meshName);
-               
-               cout << "Set mesh OK" << endl << endl;
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to set mesh", SALOME::INTERNAL_ERROR);
-       }
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    try
+    {
+        mObj->setMesh(meshName);
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << this << ".setMesh(\"" << meshName << "\")";
+
+        if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::setMesh - OK");
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to set mesh", SALOME::INTERNAL_ERROR);
+    }
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+}
+
+std::string MULTIPR_Obj_i::getMeshName() const
+        throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+  return mObj->getMeshName();
 }
 
 
 void MULTIPR_Obj_i::setBoxing(CORBA::Long pBoxing)
-       throw (SALOME::SALOME_Exception)
+    throw (SALOME::SALOME_Exception)
 {
-       if (mBoxing < 0) THROW_SALOME_CORBA_EXCEPTION("Invalid boxing parameter; should be >= 1", SALOME::INTERNAL_ERROR);
-       if (mBoxing > 200) THROW_SALOME_CORBA_EXCEPTION("Invalid boxing parameter; should be <= 200", SALOME::INTERNAL_ERROR);
-       
-       mBoxing = pBoxing;
+    if (mBoxing < 0) THROW_SALOME_CORBA_EXCEPTION("Invalid boxing parameter; should be >= 1", SALOME::INTERNAL_ERROR);
+    if (mBoxing > 200) THROW_SALOME_CORBA_EXCEPTION("Invalid boxing parameter; should be <= 200", SALOME::INTERNAL_ERROR);
+
+    mBoxing = pBoxing;
+
+    // Dump Python
+    MULTIPR::TPythonDump(_engine) << this << ".setBoxing(" << pBoxing << ")";
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
 }
 
 
-MULTIPR_ORB::string_array* MULTIPR_Obj_i::getMeshes() 
-       throw (SALOME::SALOME_Exception)
+MULTIPR_ORB::string_array* MULTIPR_Obj_i::getMeshes()
+    throw (SALOME::SALOME_Exception)
 {
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-       
-       try
-       {
-               std::vector<std::string> listMeshes = mObj->getMeshes();
-               mySeq->length(listMeshes.size());
-               
-               for (int i = 0 ; i < listMeshes.size() ; i++)
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
+
+    try
+    {
+        std::vector<std::string> listMeshes = mObj->getMeshes();
+        mySeq->length(listMeshes.size());
+
+        for (size_t i = 0 ; i < listMeshes.size() ; i++)
         {
-               mySeq[i] = CORBA::string_dup(listMeshes[i].c_str());
+            mySeq[i] = CORBA::string_dup(listMeshes[i].c_str());
         }
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to get meshes", SALOME::INTERNAL_ERROR);
-       }
-       
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to get meshes", SALOME::INTERNAL_ERROR);
+    }
+
     return mySeq._retn();
 }
 
 
-MULTIPR_ORB::string_array* MULTIPR_Obj_i::getFields(
-       throw (SALOME::SALOME_Exception)
+MULTIPR_ORB::string_array* MULTIPR_Obj_i::getFields(const char* pPartList)
+    throw (SALOME::SALOME_Exception)
 {
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-       
-       try
-       {
-               std::vector<std::string> listFields = mObj->getFields();
-               mySeq->length(listFields.size());
-               
-               for (int i = 0 ; i < listFields.size() ; i++)
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
+
+    try
+    {
+        std::vector<std::string> listFields = mObj->getFields(pPartList);
+        mySeq->length(listFields.size());
+
+        for (size_t i = 0 ; i < listFields.size() ; i++)
         {
-               mySeq[i] = CORBA::string_dup(listFields[i].c_str());
+            mySeq[i] = CORBA::string_dup(listFields[i].c_str());
         }
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to get fields", SALOME::INTERNAL_ERROR);
-       }
-       
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to get fields", SALOME::INTERNAL_ERROR);
+    }
+
     return mySeq._retn();
 }
 
 
-CORBA::Long MULTIPR_Obj_i::getTimeStamps(const char* fieldName)
-       throw (SALOME::SALOME_Exception)
+CORBA::Long MULTIPR_Obj_i::getTimeStamps(const char* pPartList, const char* fieldName)
+    throw (SALOME::SALOME_Exception)
 {
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       try
-       {
-               return mObj->getTimeStamps(fieldName);
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to get time stamps", SALOME::INTERNAL_ERROR);
-       }
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    try
+    {
+        return mObj->getTimeStamps(pPartList, fieldName);
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to get time stamps", SALOME::INTERNAL_ERROR);
+    }
 }
 
+void MULTIPR_Obj_i::getFieldMinMax(const char* pPartName, const char* pFieldName,
+                                   CORBA::Float& pMin, CORBA::Float& pMax)
+    throw (SALOME::SALOME_Exception)
+{
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+    try
+    {
+        mObj->getFieldMinMax(pPartName, pFieldName, pMin, pMax);
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to get parts", SALOME::INTERNAL_ERROR);
+    }
+}
 
 MULTIPR_ORB::string_array* MULTIPR_Obj_i::getParts()
-       throw (SALOME::SALOME_Exception)
-{
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-       
-       try
-       {
-               std::vector<std::string> listParts = mObj->getParts();
-               mySeq->length(listParts.size());
-               
-               for (int i = 0 ; i < listParts.size() ; i++)
+    throw (SALOME::SALOME_Exception)
+{
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
+
+    try
+    {
+        std::vector<std::string> listParts = mObj->getParts();
+        mySeq->length(listParts.size());
+
+        for (size_t i = 0 ; i < listParts.size() ; i++)
         {
-               mySeq[i] = CORBA::string_dup(listParts[i].c_str());
+            mySeq[i] = CORBA::string_dup(listParts[i].c_str());
         }
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to get parts", SALOME::INTERNAL_ERROR);
-       }
-       
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to get parts", SALOME::INTERNAL_ERROR);
+    }
+
     return mySeq._retn();
 }
 
 
 char* MULTIPR_Obj_i::getPartInfo(const char* pPartName)
-               throw (SALOME::SALOME_Exception)
+    throw (SALOME::SALOME_Exception)
 {
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       return CORBA::string_dup(mObj->getPartInfo(pPartName).c_str());
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    return CORBA::string_dup(mObj->getPartInfo(pPartName).c_str());
 }
 
 
 MULTIPR_ORB::string_array* MULTIPR_Obj_i::partitionneDomaine()
-       throw (SALOME::SALOME_Exception)
-{
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-       
-       try
-       {
-               std::vector<std::string> listParts = mObj->partitionneDomaine();
-               mySeq->length(listParts.size());
-               
-               for (int i = 0 ; i < listParts.size() ; i++)
+    throw (SALOME::SALOME_Exception)
+{
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
+
+    try
+    {
+        std::vector<std::string> listParts = mObj->partitionneDomaine();
+        mySeq->length(listParts.size());
+
+        for (size_t i = 0 ; i < listParts.size() ; i++)
         {
-               mySeq[i] = CORBA::string_dup(listParts[i].c_str());
+            mySeq[i] = CORBA::string_dup(listParts[i].c_str());
         }
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to partition mesh", SALOME::INTERNAL_ERROR);
-       }
-       
-    return mySeq._retn();
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << "parts = " << this << ".partitionneDomaine()";
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to partition mesh", SALOME::INTERNAL_ERROR);
+    }
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+
+  return mySeq._retn();
 }
 
 
-MULTIPR_ORB::string_array* MULTIPR_Obj_i::partitionneGrain(
-               const char* pPartName, 
-               CORBA::Long pNbParts, 
-               CORBA::Long pPartitionner)
-               throw (SALOME::SALOME_Exception)
-{
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-       
-       try
-       {
-               std::vector<std::string> listParts = mObj->partitionneGrain(
-                       pPartName,
-                       pNbParts,
-                       pPartitionner);
-                       
-               mySeq->length(listParts.size());
-               
-               for (int i = 0 ; i < listParts.size() ; i++)
+MULTIPR_ORB::string_array* MULTIPR_Obj_i::partitionneGroupe(
+        const char* pPartName,
+        CORBA::Long pNbParts,
+        CORBA::Long pPartitionner)
+        throw (SALOME::SALOME_Exception)
+{
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
+
+    try
+    {
+        std::vector<std::string> listParts = mObj->partitionneGroupe(
+            pPartName,
+            pNbParts,
+            pPartitionner);
+
+        mySeq->length(listParts.size());
+
+        for (size_t i = 0 ; i < listParts.size() ; i++)
         {
-               mySeq[i] = CORBA::string_dup(listParts[i].c_str());
+            mySeq[i] = CORBA::string_dup(listParts[i].c_str());
         }
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to partition group", SALOME::INTERNAL_ERROR);
-       }
-       
-    return mySeq._retn();
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << "new_parts = " << this << ".partitionneGroupe(\""
+        << pPartName << "\", " << pNbParts << ", " << pPartitionner << ")";
+    }
+    catch (std::exception& exc)
+    {
+        THROW_SALOME_CORBA_EXCEPTION(exc.what(), SALOME::INTERNAL_ERROR);
+    }
+    catch (multipr::RuntimeException& exc)
+    {
+        std::ostringstream aStream;
+        exc.dump(aStream);
+        aStream<<ends;
+        THROW_SALOME_CORBA_EXCEPTION(aStream.str().c_str(), SALOME::INTERNAL_ERROR);
+    }
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+
+  return mySeq._retn();
 }
 
 
 MULTIPR_ORB::string_array* MULTIPR_Obj_i::decimePartition(
-               const char*   pPartName,
-               const char*   pFieldName,
-               CORBA::Long   pFieldIt,
-               const char*   pFilterName,
-               CORBA::Double pTmed,
-               CORBA::Double pTlow,
-               CORBA::Double pRadius)
-               throw (SALOME::SALOME_Exception)
-{
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-       
-       try
-       {
-               std::vector<std::string> listParts = mObj->decimePartition(
-                       pPartName,
-                       pFieldName,
-                       pFieldIt,
-                       pFilterName,
-                       pTmed,
-                       pTlow,
-                       pRadius,
-                       mBoxing);
-               
-               mySeq->length(listParts.size());
-               
-               for (int i = 0 ; i < listParts.size() ; i++)
+        const char*   pPartName,
+        const char*   pFieldName,
+        CORBA::Long   pFieldIt,
+        const char*   pFilterName,
+        const char*   pFilterParams)
+        throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL)
+  {
+    THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+  }
+    MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
+
+    try
+    {
+        std::vector<std::string> listParts = mObj->decimePartition(
+            pPartName,
+            pFieldName,
+            pFieldIt,
+            pFilterName,
+            pFilterParams);
+        mySeq->length(listParts.size());
+        for (size_t i = 0 ; i < listParts.size() ; i++)
         {
-               mySeq[i] = CORBA::string_dup(listParts[i].c_str());
+            mySeq[i] = CORBA::string_dup(listParts[i].c_str());
         }
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to decimate", SALOME::INTERNAL_ERROR);
-       }
-       
-       return mySeq._retn();
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << "parts = " << this << ".decimePartition(\""
+                                      << pPartName << "\", \"" << pFieldName << "\", "
+                                      << pFieldIt << ", \"" << pFilterName << "\", \""
+                                      << pFilterParams << "\")";
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to decimate", SALOME::INTERNAL_ERROR);
+    }
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+
+  return mySeq._retn();
+}
+
+/*
+MULTIPR_ORB::string_array* MULTIPR_Obj_i::decimatePart(
+        const char*   pPartName,
+        const char*   pFieldName,
+        CORBA::Long   pFieldIt,
+        const char*   pFilterName,
+        const char*   pFilterParams)
+        throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+  MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
+
+  try
+  {
+    std::list<std::string> emptyParts;
+    mObj->decimePartition(pPartName,
+                          pFieldName,
+                          pFieldIt,
+                          pFilterName,
+                          pFilterParams,
+                          emptyParts);
+
+    mySeq->length(emptyParts.size());
+    std::list<std::string>::const_iterator it = emptyParts.begin(), end = emptyParts.end();
+    for (size_t i = 0; it != end; it++, i++)
+    {
+      mySeq[i] = CORBA::string_dup((*it).c_str());
+    }
+
+    // Dump Python
+    MULTIPR::TPythonDump(_engine) << "empty_parts = " << this << ".decimatePart(\""
+                                  << pPartName << "\", \"" << pFieldName << "\", "
+                                  << pFieldIt << ", \"" << pFilterName << "\", \""
+                                  << pFilterParams << "\")";
+  }
+  catch (multipr::RuntimeException& e)
+  {
+    e.dump(cout);
+    THROW_SALOME_CORBA_EXCEPTION("Unable to decimate", SALOME::INTERNAL_ERROR);
+  }
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+
+  return mySeq._retn();
+}
+*/
+
+char* MULTIPR_Obj_i::evalDecimationParams(
+    const char* pPartName,
+    const char* pFieldName,
+    CORBA::Long pFieldIt,
+    const char* pFilterName,
+    const char* pFilterParams)
+    throw (SALOME::SALOME_Exception)
+{
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    try
+    {
+        string res = mObj->evalDecimationParams(
+            pPartName,
+            pFieldName,
+            pFieldIt,
+            pFilterName,
+            pFilterParams);
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << "dec_params = " << this << ".evalDecimationParams(\""
+                                      << pPartName << "\", \"" << pFieldName << "\", " << pFieldIt
+                                      << ", \"" << pFilterName << "\", \"" << pFilterParams
+                                      << "\") # " << res.c_str();
+        return CORBA::string_dup(res.c_str());
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to evaluate decimation parameters", SALOME::INTERNAL_ERROR);
+    }
+}
+
+
+void MULTIPR_Obj_i::removeParts(const char* pPrefixPartName)
+    throw (SALOME::SALOME_Exception)
+{
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+    mObj->removeParts(pPrefixPartName);
+
+    // Dump Python
+    MULTIPR::TPythonDump(_engine) << this << ".removeParts(\"" << pPrefixPartName << "\")";
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+}
+
+char* MULTIPR_Obj_i::getMEDInfo(const char* pPartName)
+  throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+  char res[128];
+
+  mObj->getMEDInfo(res, const_cast<char*>(pPartName));
+  return CORBA::string_dup(res);
+}
+
+void MULTIPR_Obj_i::save(const char* pPath)
+    throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+  try
+  {
+    std::string strFile = mObj->getMEDFilename();
+
+    // Do Save
+    mObj->save(pPath);
+
+    // Remove temporary files, if needed
+    if (mIsTmp)
+    {
+      mIsTmp = false;
+
+      // Remove temporary files, created during study loading, together with directory
+      std::string strPath = multipr::getPath(strFile.c_str());
+#ifdef WNT
+      //std::string cmd_rm ("del /F \"");
+#else
+      std::string cmd_rm ("rm -rf \"");
+#endif
+      cmd_rm += strPath + "\"";
+      system(cmd_rm.c_str());
+    }
+  }
+  catch (multipr::RuntimeException& e)
+  {
+    e.dump(cout);
+    THROW_SALOME_CORBA_EXCEPTION("Unable to save MED file", SALOME::INTERNAL_ERROR);
+  }
+
+  // Dump Python
+  MULTIPR::TPythonDump(_engine) << this << ".save(\"" << pPath << "\")";
 }
 
+CORBA::Long MULTIPR_Obj_i::getSaveProgress()
+{
+  return mObj->getProgress();
+}
 
-void MULTIPR_Obj_i::save()
-       throw (SALOME::SALOME_Exception)
+void MULTIPR_Obj_i::resetSaveProgress()
 {
-       if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-       
-       try
-       {
-               mObj->save();
-               
-       }
-       catch (multipr::RuntimeException& e)
-       {
-               e.dump(cout);
-               THROW_SALOME_CORBA_EXCEPTION("Unable to save MED file", SALOME::INTERNAL_ERROR);
-       }
+  mObj->resetProgress();
 }
 
+//-----------------------------------------------------------------------------
+// savePersistent and setEngine (for Persistence & Dump Python)
+//-----------------------------------------------------------------------------
+
+void MULTIPR_Obj_i::savePersistent (const char* pPath)
+    throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
 
+  try
+  {
+    mObj->savePersistent(pPath);
+  }
+  catch (multipr::RuntimeException& e)
+  {
+    e.dump(cout);
+    THROW_SALOME_CORBA_EXCEPTION("Unable to save MED file", SALOME::INTERNAL_ERROR);
+  }
+}
+
+void MULTIPR_Obj_i::setEngine (MULTIPR_Gen_i* theEngine)
+{
+  _engine = theEngine;
+}
+
+
+//-----------------------------------------------------------------------------
+// Set/Get current study (for Persistence & Dump Python)
+//-----------------------------------------------------------------------------
+
+/*! Set current study
+ */
+void MULTIPR_Gen_i::SetCurrentStudy (SALOMEDS::Study_ptr theStudy)
+{
+  //if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::SetCurrentStudy");
+
+  // theStudy or myCurrentStudy may be nil
+  if (!CORBA::is_nil(theStudy))
+  {
+    if (CORBA::is_nil(myCurrentStudy))
+    {
+      // move python trace of unknown study to the real study
+      int studyId = theStudy->StudyId();
+      if (myPythonScripts.find(-1) != myPythonScripts.end())
+      {
+        myPythonScripts[studyId].insert(myPythonScripts[studyId].begin(), // at
+                                        myPythonScripts[-1].begin(), // from
+                                        myPythonScripts[-1].end());  // to
+        myPythonScripts[-1].clear();
+      }
+    }
+  }
+
+  myCurrentStudy = SALOMEDS::Study::_duplicate(theStudy);
+}
+
+/*! Get current study
+ */
+SALOMEDS::Study_ptr MULTIPR_Gen_i::GetCurrentStudy()
+{
+  //if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::GetCurrentStudy: study Id = " << GetCurrentStudyID());
+  return SALOMEDS::Study::_duplicate(myCurrentStudy);
+}
+
+//-----------------------------------------------------------------------------
+// SALOMEDS::Driver methods (Persistence & Dump Python)
+//-----------------------------------------------------------------------------
+
+/*! Get component data type
+ */
+char* MULTIPR_Gen_i::ComponentDataType()
+{
+  if(MYDEBUG) MESSAGE( "MULTIPR_Gen_i::ComponentDataType" );
+  return CORBA::string_dup( "MULTIPR" );
+}
+
+/*! Clears study-connected data when it is closed
+ */
+void MULTIPR_Gen_i::Close (SALOMEDS::SComponent_ptr theComponent)
+{
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::Close");
+}
+
+/*! Save MULTIPR module's data
+ */
+SALOMEDS::TMPFile* MULTIPR_Gen_i::Save (SALOMEDS::SComponent_ptr theComponent,
+                                        const char*              theURL,
+                                        bool                     isMultiFile)
+{
+  INFOS( "MULTIPR_Gen_i::Save" );
+
+  if (myCurrentStudy->_is_nil() ||
+      theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId())
+    SetCurrentStudy(theComponent->GetStudy());
+
+  // Store study contents as a set of python commands
+  SavePython(myCurrentStudy);
+
+  // Study name (for tmp directory and tmp files naming)
+  std::string aStudyName;
+  if (isMultiFile)
+    aStudyName = SALOMEDS_Tool::GetNameFromPath(myCurrentStudy->URL());
+
+  // Declare a byte stream
+  SALOMEDS::TMPFile_var aStreamFile;
+
+  SALOMEDS::ChildIterator_ptr obj_it (myCurrentStudy->NewChildIterator(theComponent));
+
+  // TODO: iterate on all objects under theComponent
+  if (!obj_it->More())
+    return aStreamFile._retn();
+
+  SALOMEDS::SObject_ptr aSObj = obj_it->Value();
+  CORBA::Object_var anObj = aSObj->GetObject();
+  MULTIPR_ORB::MULTIPR_Obj_ptr obj = MULTIPR_ORB::MULTIPR_Obj::_narrow(anObj);
+  if (CORBA::is_nil(obj))
+    return aStreamFile._retn();
+
+  // Obtain a temporary directory
+  std::string tmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
+
+  // Directory for MED data to be stored in a distributed MED file
+  std::string subDir  = aStudyName + "_MULTIPR_MED";
+  std::string meshDir = tmpDir + subDir;
+
+  // Create a new dir <meshDir> to save the sequential/distributed file in.
+  // Remove all the files in <meshDir> if they exist.
+#ifdef WNT
+  std::string dirSeparator = "\\";
+  //std::string cmd_mk ("mkdir /F \"");
+  //std::string cmd_rm ("del /F \"");
+#else
+  std::string dirSeparator = "/";
+  std::string cmd_mk ("mkdir \"");
+  std::string cmd_rm ("rm -rf \"");
+#endif
+  cmd_mk += meshDir + "\"";
+  cmd_rm += meshDir + dirSeparator + "\"*";
+  system(cmd_mk.c_str());
+  system(cmd_rm.c_str());
+
+  // Create a sequence of files processed
+  SALOMEDS::ListOfFileNames_var aFileSeq = new SALOMEDS::ListOfFileNames;
+
+  if (obj->isValidSequentialMEDFile())
+  {
+    std::string aFile = obj->getFilename();
+    std::string aFileName = multipr::getFilenameWithoutPath(aFile.c_str());
+
+    // Copy initial sequential MED file to <meshDir>
+#ifdef WNT
+    std::string dirSeparator = "\\";
+    //std::string cmd_cp ("copy \"");
+#else
+    std::string dirSeparator = "/";
+    std::string cmd_cp ("cp \"");
+#endif
+    cmd_cp += aFile + "\" \"" + meshDir + dirSeparator + "\"";
+    system(cmd_cp.c_str());
+
+    // Set names of temporary files
+    std::string aFileNameRel = subDir + dirSeparator + aFileName;
+    aFileSeq->length(1);
+    aFileSeq[0] = CORBA::string_dup(aFileNameRel.c_str()); // sequential MED file
+  }
+  else if (obj->isValidDistributedMEDFile())
+  {
+    // Save distributed MED file to the <meshDir>
+    PortableServer::Servant aServant = _poa->reference_to_servant(obj);
+    MULTIPR_Obj_i* objServant = dynamic_cast<MULTIPR_Obj_i*>(aServant);
+    if (!objServant)
+    {
+      // TODO: exception
+      return aStreamFile._retn();
+    }
+    objServant->savePersistent(meshDir.c_str());
+
+    // ASCII master file name
+    std::string aMaitreFile = obj->getFilename();
+    std::string aMaitreFileName = multipr::getFilenameWithoutPath(aMaitreFile.c_str());
+    // just after partitionneDomaine() the state is MULTIPR_OBJ_STATE_DIS_MEM,
+    // and getFilename() returns name of sequential file
+    // (because distributed file is not created on disk yet). So, build the name:
+    if (aMaitreFile == obj->getSeqFilename())
+    {
+      std::string strExtension (".med");
+      std::string strNamePrefix =
+        multipr::removeExtension(aMaitreFileName.c_str(), strExtension.c_str());
+      aMaitreFileName = strNamePrefix + "_grains_maitre" + strExtension;
+    }
+    //std::string aMaitreFileName = SALOMEDS_Tool::GetNameFromPath(aMaitreFile);
+    std::string aMaitreFileNameRel = subDir + dirSeparator + aMaitreFileName;
+
+    // Set names of temporary files
+    MULTIPR_ORB::string_array* listParts = obj->getParts();
+    unsigned int nbParts = listParts->length();
+    aFileSeq->length(nbParts + 1);
+
+    char   lMeshName[256];
+    int    lId;
+    char   lPartName[256];
+    char   lPath[256];
+    char   lMEDFileName[256];
+
+    for (unsigned int i = 0; i < nbParts; i++) // each part MED files
+    {
+      const char* strPartName = (*listParts)[i];
+      char* strPartInfo = obj->getPartInfo(strPartName);
+
+      // parse infos
+      int ret = sscanf(strPartInfo, "%s %d %s %s %s",
+                       lMeshName, &lId, lPartName, lPath, lMEDFileName);
+
+      if (ret != 5)
+      {
+        // TODO: exception
+        return aStreamFile._retn();
+      }
+
+      std::string aPartFileName = multipr::getFilenameWithoutPath(lMEDFileName);
+      std::string aPartFileNameRel = subDir + dirSeparator + aPartFileName;
+
+      aFileSeq[i] = CORBA::string_dup(aPartFileNameRel.c_str()); // part MED file
+    }
+    aFileSeq[nbParts] = CORBA::string_dup(aMaitreFileNameRel.c_str()); // ASCII master file
+  }
+  else
+  {
+    // TODO: exception
+    return aStreamFile._retn();
+  }
+
+  // Convert temporary files to stream
+  aStreamFile = SALOMEDS_Tool::PutFilesToStream(tmpDir, aFileSeq.in(), isMultiFile);
+
+  // Remove temporary files and directory
+  if (!isMultiFile)
+  {
+    //SALOMEDS_Tool::RemoveTemporaryFiles(tmpDir, aFileSeq.in(), true);
+    // remove with shell command, because SALOMEDS_Tool::RemoveTemporaryFiles does not remove sub-folders
+#ifdef WNT
+    //std::string cmd_rm ("del /F \"");
+#else
+    std::string cmd_rm ("rm -rf \"");
+#endif
+    cmd_rm += tmpDir + "\"";
+    system(cmd_rm.c_str());
+  }
+
+  INFOS("MULTIPR_Gen_i::Save() completed");
+  return aStreamFile._retn();
+}
+
+/*! Save MULTIPR module's data in ASCII format
+ */
+SALOMEDS::TMPFile* MULTIPR_Gen_i::SaveASCII (SALOMEDS::SComponent_ptr theComponent,
+                                             const char*              theURL,
+                                             bool                     isMultiFile)
+{
+  if(MYDEBUG) MESSAGE( "MULTIPR_Gen_i::SaveASCII" );
+  SALOMEDS::TMPFile_var aStreamFile = Save(theComponent, theURL, isMultiFile);
+  return aStreamFile._retn();
+}
+
+/*! Load MULTIPR module's data
+ */
+bool MULTIPR_Gen_i::Load (SALOMEDS::SComponent_ptr theComponent,
+                          const SALOMEDS::TMPFile& theStream,
+                          const char*              theURL,
+                          bool                     isMultiFile)
+{
+  INFOS("MULTIPR_Gen_i::Load");
+
+  if (myCurrentStudy->_is_nil() ||
+      theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId())
+    SetCurrentStudy(theComponent->GetStudy());
+
+  // Get temporary files location
+  std::string tmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
+
+  INFOS("THE URL++++++++++++++");
+  INFOS(theURL);
+  INFOS("THE TMP PATH+++++++++");
+  INFOS(tmpDir.c_str());
+
+  // For LocalPersistentIDToIOR():
+  myTmpDir = tmpDir;
+
+  // Create a new dir <meshDir> to restore the distributed/sequential
+  // MED file in. It is needed only if not multifile, because in
+  // multifile study all required files are already on disk.
+  if (!isMultiFile)
+  {
+    std::string subDir  = "_MULTIPR_MED";
+    std::string meshDir = tmpDir + subDir;
+#ifdef WNT
+    //std::string cmd_mk ("mkdir /F \"");
+#else
+    std::string cmd_mk ("mkdir \"");
+#endif
+    cmd_mk += meshDir + "\"";
+    system(cmd_mk.c_str());
+  }
+
+  // Convert the stream into sequence of files to process
+  SALOMEDS::ListOfFileNames_var aFileSeq =
+    SALOMEDS_Tool::PutStreamToFiles(theStream, tmpDir.c_str(), isMultiFile);
+
+  //TCollection_AsciiString aStudyName;
+  //if (isMultiFile)
+  //  aStudyName = ((char*)SALOMEDS_Tool::GetNameFromPath(myCurrentStudy->URL()).c_str());
+
+  // Set names of "temporary" files
+  //TCollection_AsciiString filename = tmpDir + aStudyName + TCollection_AsciiString( "_MULTIPR.hdf" );
+  //TCollection_AsciiString meshfile = tmpDir + aStudyName + TCollection_AsciiString( "_MULTIPR_Mesh.med" );
+
+  // Remove temporary files created from the stream
+  //if (!isMultiFile)
+  //  SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
+
+  INFOS("MULTIPR_Gen_i::Load completed");
+  return true;
+}
+
+/*! Load MULTIPR module's data in ASCII format
+ */
+bool MULTIPR_Gen_i::LoadASCII (SALOMEDS::SComponent_ptr theComponent,
+                               const SALOMEDS::TMPFile& theStream,
+                               const char*              theURL,
+                               bool                     isMultiFile)
+{
+  if(MYDEBUG) MESSAGE( "MULTIPR_Gen_i::LoadASCII" );
+  return Load(theComponent, theStream, theURL, isMultiFile);
+}
+
+/*! Transform data from transient form to persistent
+ */
+char* MULTIPR_Gen_i::IORToLocalPersistentID (SALOMEDS::SObject_ptr /*theSObject*/,
+                                             const char*           IORString,
+                                             CORBA::Boolean        isMultiFile,
+                                             CORBA::Boolean        /*isASCII*/ )
+{
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::IORToLocalPersistentID");
+
+  MULTIPR_ORB::MULTIPR_Obj_ptr obj =
+    MULTIPR_ORB::MULTIPR_Obj::_narrow(_orb->string_to_object(IORString));
+
+  if (!CORBA::is_nil(obj))
+  {
+    std::string aStudyName;
+    if (isMultiFile)
+      aStudyName = SALOMEDS_Tool::GetNameFromPath(myCurrentStudy->URL());
+
+    std::string subDir  = aStudyName + "_MULTIPR_MED";
+
+    std::string aFile = obj->getFilename();
+    std::string aFileName = multipr::getFilenameWithoutPath(aFile.c_str());
+
+    // Get servant (to call methods, not present in IDL interface
+    PortableServer::Servant aServant = _poa->reference_to_servant(obj);
+    MULTIPR_Obj_i* objServant = dynamic_cast<MULTIPR_Obj_i*>(aServant);
+    if (!objServant)
+    {
+      // TODO: exception
+      return CORBA::string_dup("");
+    }
+
+    std::string strSeparator ("|");
+    if (obj->isValidSequentialMEDFile())
+    {
+      // Save Boxing
+      char strBoxing[32];
+      sprintf(strBoxing, "%d", objServant->getBoxing());
+      aFileName += strSeparator + strBoxing;
+
+      // Save Mesh Name
+      std::string aMeshName = objServant->getMeshName();
+      if (!aMeshName.empty())
+      {
+        aFileName += strSeparator + aMeshName;
+      }
+    }
+    else if (obj->isValidDistributedMEDFile())
+    {
+      // just after partitionneDomaine() the state is MULTIPR_OBJ_STATE_DIS_MEM,
+      // and getFilename() returns name of sequential file
+      // (because distributed file is not created on disk yet). So, build the name:
+      if (aFile == obj->getSeqFilename())
+      {
+        std::string strExtension (".med");
+        std::string strNamePrefix =
+          multipr::removeExtension(aFileName.c_str(), strExtension.c_str());
+        aFileName = strNamePrefix + "_grains_maitre" + strExtension;
+      }
+
+      // Save Boxing
+      char strBoxing[32];
+      sprintf(strBoxing, "%d", objServant->getBoxing());
+      aFileName += strSeparator + strBoxing;
+    }
+    else
+    {
+      // TODO: exception
+      return CORBA::string_dup("");
+    }
+
+    // PersistentID will be a relative path to MED file (relatively tmp dir)
+    // plus additianal parameters, separated by '|' (see above)
+#ifdef WNT
+    std::string dirSeparator = "\\";
+#else
+    std::string dirSeparator = "/";
+#endif
+    aFileName = subDir + dirSeparator + aFileName;
+
+    if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::IORToLocalPersistentID: id = " << aFileName.c_str());
+
+    return CORBA::string_dup(aFileName.c_str());
+  }
+  return CORBA::string_dup("");
+}
+
+/*! Transform data from persistent form to transient
+ */
+char* MULTIPR_Gen_i::LocalPersistentIDToIOR (SALOMEDS::SObject_ptr /*theSObject*/,
+                                             const char*           aLocalPersistentID,
+                                             CORBA::Boolean        isMultiFile,
+                                             CORBA::Boolean        /*isASCII*/)
+{
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID);
+
+  if (strlen(aLocalPersistentID) > 0)
+  {
+    // Extract relative path
+    std::string strLocalPersistentID (aLocalPersistentID);
+    int nb = strLocalPersistentID.find("|");
+    if (nb < 1) nb = strLocalPersistentID.size();
+    if (nb < 1)
+    {
+      // TODO: exception
+      return CORBA::string_dup("");
+    }
+    std::string strRelativePath = strLocalPersistentID.substr(0, nb);
+    strLocalPersistentID.erase(0, nb); // erase <strRelativePath>
+    if (strLocalPersistentID.size() > 0) strLocalPersistentID.erase(0, 1); // erase "|"
+
+    // the only kind of available objects is a MULTIPR_ORB::MULTIPR_Obj,
+    // representing a sequential or a distributed MED file.
+    std::string medFilename = myTmpDir + strRelativePath; // myTmpDir already contains dir separator
+
+    // create MULTIPR_Obj from file
+    //MULTIPR_ORB::MULTIPR_Obj_ptr obj = getObject(medFilename.c_str());
+    MULTIPR_Obj_i* obj_i = new MULTIPR_Obj_i (_poa,
+                                              medFilename.c_str(),
+                                              /*isPersistence = */true,
+                                              isMultiFile);
+    obj_i->setEngine(this);
+    MULTIPR_ORB::MULTIPR_Obj_ptr obj = obj_i->POA_MULTIPR_ORB::MULTIPR_Obj::_this();
+
+    // Set boxing and mesh name, if provided
+    nb = strLocalPersistentID.find("|");
+    if (nb < 1) nb = strLocalPersistentID.size();
+    if (nb > 0)
+    {
+      std::string strBoxing = strLocalPersistentID.substr(0, nb);
+      strLocalPersistentID.erase(0, nb); // erase <strBoxing>
+      if (strLocalPersistentID.size() > 0) strLocalPersistentID.erase(0, 1); // erase "|"
+      int aBoxing = atoi(strBoxing.c_str());
+      obj->setBoxing(aBoxing);
+    }
+
+    if (obj->isValidSequentialMEDFile())
+    {
+      nb = strLocalPersistentID.size();
+      if (nb > 0)
+      {
+        std::string strMeshName = strLocalPersistentID.substr(0, nb);
+        obj->setMesh(strMeshName.c_str());
+        // we do not cut <strLocalPersistentID> here,
+        // because we do not expect to find in it anything
+      }
+    }
+
+    // get IOR string
+    CORBA::String_var anIORString = _orb->object_to_string(obj);
+    return CORBA::string_dup(anIORString);
+  }
+  return CORBA::string_dup("");
+}
+
+/*! Transform data from persistent form to transient
+ */
+Engines::TMPFile* MULTIPR_Gen_i::DumpPython (CORBA::Object_ptr theStudy,
+                                             CORBA::Boolean isPublished,
+                                             CORBA::Boolean& isValidScript)
+{
+  isValidScript = false;
+
+  SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
+  if (CORBA::is_nil(aStudy))
+    return new Engines::TMPFile(0);
+
+  /*
+  SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
+  if (CORBA::is_nil(aSO))
+    return new Engines::TMPFile(0);
+
+  // Map study entries to object names
+  Resource_DataMapOfAsciiStringAsciiString aMap;
+  Resource_DataMapOfAsciiStringAsciiString aMapNames;
+
+  SALOMEDS::ChildIterator_var Itr = aStudy->NewChildIterator(aSO);
+  for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
+    SALOMEDS::SObject_var aValue = Itr->Value();
+    CORBA::String_var anID = aValue->GetID();
+    CORBA::String_var aName = aValue->GetName();
+    TCollection_AsciiString aGUIName ( (char*) aName.in() );
+    TCollection_AsciiString anEnrty ( (char*) anID.in() );
+    if (aGUIName.Length() > 0) {
+      aMapNames.Bind( anEnrty, aGUIName );
+      aMap.Bind( anEnrty, aGUIName );
+    }
+  }
+  //*/
+
+  // Get trace of restored study
+  SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
+  SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
+  SALOMEDS::GenericAttribute_var anAttr =
+    aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
+
+  char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
+  std::string aSavedTrace (oldValue);
+
+  // Add trace of API methods calls and replace study entries by names
+  std::string aScript =
+    "### This file is generated by SALOME automatically "
+    "by dump python functionality of MULTIPR component\n\n";
+  aScript += DumpPython_impl(aStudy->StudyId(), isPublished, isValidScript, aSavedTrace);
+
+  int aLen = aScript.length();
+  unsigned char* aBuffer = new unsigned char[aLen+1];
+  strcpy((char*)aBuffer, aScript.c_str());
+
+  CORBA::Octet* anOctetBuf = (CORBA::Octet*)aBuffer;
+  Engines::TMPFile_var aStreamFile = new Engines::TMPFile (aLen+1, aLen+1, anOctetBuf, 1);
+
+  //bool hasNotPublishedObjects = aScript.Location( NotPublishedObjectName(), 1, aLen);
+  //isValidScript = isValidScript && !hasNotPublishedObjects;
+
+  return aStreamFile._retn();
+}
+
+/*! DumpPython_impl
+ */
+std::string MULTIPR_Gen_i::DumpPython_impl (int theStudyID,
+                                            bool isPublished,
+                                            bool& aValidScript,
+                                            std::string theSavedTrace)
+{
+  std::string helper;
+  std::string aGen = MULTIPR::TPythonDump::MULTIPRGenName();
+
+  // set initial part of a script
+  std::string aScript ("import salome\n");
+  aScript += "import MULTIPR_ORB\n\n";
+  aScript += "def RebuildData(theStudy):\n";
+
+  aScript += helper + "\tmpr_comp = salome.lcc.FindOrLoadComponent(\"FactoryServer\", \"" +
+             ComponentDataType() + "\")\n";
+  aScript += helper + "\t" + aGen + " = mpr_comp._narrow(MULTIPR_ORB.MULTIPR_Gen)\n";
+
+  //if ( isPublished )
+  //  aScript += helper + "\t" + aGen + ".SetCurrentStudy(theStudy)";
+  //else
+  //  aScript += helper + "\t" + aGen + ".SetCurrentStudy(None)";
+  aScript += helper + "\t" + aGen + ".SetCurrentStudy(theStudy)\n";
+
+  // Dump trace of restored study
+  if (theSavedTrace.length() > 0)
+  {
+    aScript += helper + "\n" + theSavedTrace;
+  }
+
+  // Dump trace of API methods calls
+  std::string aNewLines = GetNewPythonLines(theStudyID);
+  if (aNewLines.length() > 0)
+  {
+    aScript += helper + "\n" + aNewLines;
+  }
+
+  // add final part of a script
+  //aScript += helper + "\n\tisGUIMode = " + isPublished;
+  //aScript += "\n\tif isGUIMode and salome.sg.hasDesktop():";
+  //aScript += "\n\t\tsalome.sg.updateObjBrowser(0)";
+  aScript += "\n\n\tpass\n";
+
+  aValidScript = true;
+
+  return aScript;
+}
+
+/*! GetNewPythonLines
+ */
+std::string MULTIPR_Gen_i::GetNewPythonLines (int theStudyID)
+{
+  std::string aScript;
+
+  // Dump trace of API methods calls
+  if (myPythonScripts.find(theStudyID) != myPythonScripts.end())
+  {
+    std::vector <std::string> aPythonScript = myPythonScripts[theStudyID];
+    int istr, aLen = aPythonScript.size();
+    for (istr = 0; istr < aLen; istr++)
+    {
+      aScript += "\n\t";
+      aScript += aPythonScript[istr];
+    }
+    aScript += "\n";
+  }
+
+  return aScript;
+}
+
+/*! CleanPythonTrace
+ */
+void MULTIPR_Gen_i::CleanPythonTrace (int theStudyID)
+{
+  // Clean trace of API methods calls
+  if (myPythonScripts.find(theStudyID) != myPythonScripts.end())
+  {
+    myPythonScripts[theStudyID].clear();
+  }
+}
+
+/*! AddToPythonScript
+ */
+void MULTIPR_Gen_i::AddToPythonScript (int theStudyID, std::string theString)
+{
+  //if (myPythonScripts.find(theStudyID) == myPythonScripts.end())
+  //{
+  //  myPythonScripts[theStudyID] = std::vector<std::string>;
+  //}
+  myPythonScripts[theStudyID].push_back(theString);
+}
+
+/*! SavePython
+ */
+void MULTIPR_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
+{
+  // Dump trace of API methods calls
+  std::string aScript = GetNewPythonLines(theStudy->StudyId());
+
+  // Check contents of PythonObject attribute
+  SALOMEDS::SObject_var aSO = theStudy->FindComponent(ComponentDataType());
+  SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
+  SALOMEDS::GenericAttribute_var anAttr =
+    aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
+
+  char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
+  std::string oldScript (oldValue);
+
+  if (oldScript.length() > 0) {
+    oldScript += "\n";
+    oldScript += aScript;
+  }
+  else {
+    oldScript = aScript;
+  }
+
+  // Store in PythonObject attribute
+  SALOMEDS::AttributePythonObject::_narrow(anAttr)->SetObject(oldScript.c_str(), 1);
+
+  // Clean trace of API methods calls
+  CleanPythonTrace(theStudy->StudyId());
+}
+
+
+/*! Returns true if object can be published in the study
+ */
+bool MULTIPR_Gen_i::CanPublishInStudy (CORBA::Object_ptr theIOR)
+{
+  //if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::CanPublishInStudy - " << !CORBA::is_nil(myCurrentStudy));
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::CanPublishInStudy");
+
+  //if (CORBA::is_nil(myCurrentStudy))
+  //  return false;
+
+  MULTIPR_ORB::MULTIPR_Obj_var anObj = MULTIPR_ORB::MULTIPR_Obj::_narrow(theIOR);
+  if (!anObj->_is_nil())
+    return true;
+
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::CanPublishInStudy - CANNOT");
+  return false;
+}
+
+/*! Publish object in the study
+ */
+SALOMEDS::SObject_ptr MULTIPR_Gen_i::PublishInStudy (SALOMEDS::Study_ptr   theStudy,
+                                                     SALOMEDS::SObject_ptr theSObject,
+                                                     CORBA::Object_ptr     theIOR,
+                                                     const char*           theName)
+     throw (SALOME::SALOME_Exception)
+{
+  //Unexpect aCatch(SALOME_SalomeException);
+
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::PublishInStudy");
+
+  //if (myCurrentStudy->_is_nil() || theStudy->StudyId() != myCurrentStudy->StudyId())
+  if (myCurrentStudy->_is_nil())
+    SetCurrentStudy(theStudy);
+
+  SALOMEDS::SObject_var aSO;
+  if (CORBA::is_nil(theStudy) || CORBA::is_nil(theIOR))
+    return aSO._retn();
+
+  // Publishing a MULTIPR_Object
+  MULTIPR_ORB::MULTIPR_Obj_var anObj = MULTIPR_ORB::MULTIPR_Obj::_narrow(theIOR);
+  if (!anObj->_is_nil())
+  {
+    aSO = theStudy->FindObjectIOR(_orb->object_to_string(anObj));
+    if (aSO->_is_nil())
+    {
+      SALOMEDS::GenericAttribute_var anAttr;
+      SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
+
+      SALOMEDS::SComponent_var aFather = theStudy->FindComponent(ComponentDataType());
+      if (aFather->_is_nil())
+      {
+        aFather = aStudyBuilder->NewComponent(ComponentDataType());
+        anAttr = aStudyBuilder->FindOrCreateAttribute(aFather, "AttributeName");
+        SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
+        aName->SetValue("MULTI-PR");
+        //anAttr = aStudyBuilder->FindOrCreateAttribute(aFather, "AttributePixMap");
+        //SALOMEDS::AttributePixMap::_narrow(anAttr)->SetPixMap("ICON_OBJBROWSER_MULTIPR");
+        //aStudyBuilder->DefineComponentInstance(aFather, MULTIPR_ORB::MULTIPR_Gen::_this());
+        aStudyBuilder->DefineComponentInstance(aFather, MULTIPR_Gen::_this());
+      }
+      if (aFather->_is_nil()) return aSO._retn();
+
+      if (CORBA::is_nil(theSObject))
+      {
+        aSO = aStudyBuilder->NewObject(aFather);
+      }
+      else
+      {
+        if (!theSObject->ReferencedObject(aSO))
+          aSO = SALOMEDS::SObject::_duplicate(theSObject);
+      }
+
+      anAttr = aStudyBuilder->FindOrCreateAttribute(aSO, "AttributeIOR");
+      SALOMEDS::AttributeIOR_var anIORAttr = SALOMEDS::AttributeIOR::_narrow(anAttr);
+      CORBA::String_var anIOR = _orb->object_to_string(anObj);
+      anIORAttr->SetValue(anIOR);
+
+      //anAttr = aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePixMap");
+      //SALOMEDS::AttributePixMap_var aPixmap = SALOMEDS::AttributePixMap::_narrow(anAttr);
+      //aPixmap->SetPixMap("ICON_OBJBROWSER_GROUP_PNT");
+
+      anAttr = aStudyBuilder->FindOrCreateAttribute(aSO, "AttributeName");
+      SALOMEDS::AttributeName_var aNameAttrib = SALOMEDS::AttributeName::_narrow(anAttr);
+      if (strlen(theName) == 0)
+        aNameAttrib->SetValue(anObj->getFilename());
+      else
+        aNameAttrib->SetValue(theName);
+
+      // Dump Python
+      MULTIPR::TPythonDump(this) << "sobj = " << this << ".PublishInStudy(theStudy, "
+                                 << theSObject << ", " << anObj << ", \"" << theName
+                                 << "\") # " << aSO->GetID();
+    }
+  }
+
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::PublishInStudy - END");
+
+  return aSO._retn();
+}
+
+/*
+SALOMEDS::SComponent_ptr _Gen_i::PublishComponent(SALOMEDS::Study_ptr theStudy)
+{
+  if ( CORBA::is_nil( theStudy ))
+    return SALOMEDS::SComponent::_nil();
+  if(MYDEBUG) MESSAGE("PublishComponent");
+
+  SALOMEDS::SComponent_var father =
+    SALOMEDS::SComponent::_narrow( theStudy->FindComponent( ComponentDataType() ) );
+  if ( !CORBA::is_nil( father ) )
+    return father._retn();
+
+  SALOME_ModuleCatalog::ModuleCatalog_var aCat =
+    SALOME_ModuleCatalog::ModuleCatalog::_narrow( GetNS()->Resolve("/Kernel/ModulCatalog") );
+  if ( CORBA::is_nil( aCat ) )
+    return father._retn();
+
+  SALOME_ModuleCatalog::Acomponent_var aComp = aCat->GetComponent( ComponentDataType() );
+  if ( CORBA::is_nil( aComp ) )
+    return father._retn();
+
+  SALOMEDS::StudyBuilder_var     aStudyBuilder = theStudy->NewBuilder();
+  SALOMEDS::GenericAttribute_var anAttr;
+  SALOMEDS::AttributePixMap_var  aPixmap;
+
+  father  = aStudyBuilder->NewComponent( ComponentDataType() );
+  aStudyBuilder->DefineComponentInstance( father, SMESH_Gen::_this() );
+  anAttr  = aStudyBuilder->FindOrCreateAttribute( father, "AttributePixMap" );
+  aPixmap = SALOMEDS::AttributePixMap::_narrow( anAttr );
+  aPixmap ->SetPixMap( "ICON_OBJBROWSER_SMESH" );
+  SetName( father, aComp->componentusername(), "MESH" );
+  if(MYDEBUG) MESSAGE("PublishComponent--END");
+
+  return father._retn();
+}
+//*/
+
+
+/*!
+ *  MULTIPREngine_factory
+ *
+ *  C factory, accessible with dlsym, after dlopen
+ */
 extern "C"
 {
-       PortableServer::ObjectId* MULTIPREngine_factory(
-               CORBA::ORB_ptr orb,
-               PortableServer::POA_ptr poa, 
-               PortableServer::ObjectId * contId,
-               const char* instanceName, 
-               const char* interfaceName)
-       {
-               MESSAGE("PortableServer::ObjectId* MULTIPREngine_factory()");
-               SCRUTE(interfaceName);
-               MULTIPR_Gen_i* myMULTIPR = new MULTIPR_Gen_i(orb, poa, contId, instanceName, interfaceName);
-               return myMULTIPR->getId();
-       }
+    PortableServer::ObjectId* MULTIPREngine_factory(
+        CORBA::ORB_ptr orb,
+        PortableServer::POA_ptr poa,
+        PortableServer::ObjectId * contId,
+        const char* instanceName,
+        const char* interfaceName)
+    {
+        MESSAGE("PortableServer::ObjectId* MULTIPREngine_factory()");
+        SCRUTE(interfaceName);
+        MULTIPR_Gen_i* myMULTIPR = new MULTIPR_Gen_i(orb, poa, contId, instanceName, interfaceName);
+        return myMULTIPR->getId();
+    }
 }