Salome HOME
Merge from V6_main 01/04/2013
[modules/med.git] / src / MED / Med_Gen_Driver_i.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  MED MED : implemetation of MED idl descriptions
24 //  File   : Med_Gen_Driver_i.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : MED
27 //
28 #include "Med_Gen_Driver_i.hxx"
29
30 #include "MEDMEM_Mesh_i.hxx"
31 #include "MEDMEM_Med_i.hxx"
32 #include "MEDMEM_FieldTemplate_i.hxx"
33 #include "MEDMEM_Support_i.hxx"
34
35 #include "MEDMEM_Mesh.hxx"
36 #include "MEDMEM_Field.hxx"
37 #include "MEDMEM_MedMeshDriver.hxx"
38 #include "MEDMEM_MedFieldDriver.hxx"
39 #include "MEDMEM_define.hxx"
40 #include "MEDMEM_DriversDef.hxx"
41
42
43 #include "Utils_SINGLETON.hxx"
44 #include "OpUtil.hxx"
45 #include "Utils_CorbaException.hxx"
46 #include "utilities.h"
47
48 #include "SALOMEDS_Tool.hxx"
49
50 #include <string>
51 #include <map>
52
53 #include <HDFascii.hxx>
54
55 using namespace MEDMEM;
56
57 // Initialisation des variables statiques
58 map<string, MEDMEM::MED_i*> Med_Gen_Driver_i::_MedCorbaObj;
59
60 //=============================================================================
61 /*!
62  *  default constructor: not for use
63  */
64 //=============================================================================
65 Med_Gen_Driver_i::Med_Gen_Driver_i()
66 {
67   MESSAGE("Med_Gen_Driver_i::Med_Gen_Driver_i");
68 }
69
70 //=============================================================================
71 /*!
72  *  standard constructor
73  */
74 //=============================================================================
75 Med_Gen_Driver_i::Med_Gen_Driver_i(CORBA::ORB_ptr orb)
76 {
77   MESSAGE("activate object");
78   _driver_orb = CORBA::ORB::_duplicate(orb);
79
80   // get a NamingService interface
81   _NS = SINGLETON_<SALOME_NamingService>::Instance();
82   ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting());
83   _NS->init_orb( _driver_orb );
84 }
85
86 //=============================================================================
87 /*!
88  *  Destructor
89  */
90 //=============================================================================
91 Med_Gen_Driver_i::~Med_Gen_Driver_i()
92 {
93   MESSAGE("Med_Gen_Driver_i::~Med_Gen_Driver_i");
94 }
95
96 //=============================================================================
97 /*!
98  *  GetMED [ static ]
99  *
100  *  Get Med of the study (for persistance)
101  */
102 //=============================================================================
103 MEDMEM::MED_i* Med_Gen_Driver_i::GetMED(SALOMEDS::SComponent_ptr theComponent)
104 {
105   // we have a separate MED_i for each component in a study
106   SALOMEDS::Study_var study = theComponent->GetStudy();
107   ostringstream os;
108   os << study->StudyId() << "_" << theComponent->Tag();
109   string mapKey = os.str();
110
111   MED_i* med_i;
112   map <string, MEDMEM::MED_i*>::iterator id_med;
113   id_med = _MedCorbaObj.find( mapKey );
114   if ( id_med == _MedCorbaObj.end() )
115     _MedCorbaObj[ mapKey ] = med_i = new MED_i();
116   else
117     med_i = id_med->second;
118   return med_i;
119 }
120
121 //=============================================================================
122 /*!
123  *  CORBA: Save Mesh objects (called when a study is saved)
124  */
125 //=============================================================================
126 namespace {
127
128   // names to use instead of true and false
129   enum { SAVE = 1, RESTORE = 0, ASCII = 1, NON_ASCII = 0 };
130
131   //================================================================================
132   /*!
133    * \brief Return path and base name of a file to store med data in
134     * \param theStudy - study being stored or restored
135     * \param theURL - path to file storing the study
136     * \param isMultiFile - storage mode
137     * \param isSave - action kind: SAVE or RESTORE
138     * \retval pair<string,string> - path and file base name
139    */
140   //================================================================================
141   pair<string,string> getPersistanceDirAndFileName(SALOMEDS::SComponent_ptr theComponent,
142                                                    const char*              theURL,
143                                                    const bool               isMultiFile,
144                                                    const bool               isSave)
145   {
146     string path, file;
147     CORBA::String_var compName = theComponent->ComponentDataType();
148     if (isMultiFile) {
149       // file constantly holding data
150       path = theURL;
151       SALOMEDS::Study_var study = theComponent->GetStudy();
152       file = SALOMEDS_Tool::GetNameFromPath( study->URL() );
153       file += string( "_" ) + string( compName ) + ".med";
154     }
155     else {
156       // temporary file
157       path = SALOMEDS_Tool::GetTmpDir();
158       if ( strcmp( "MED", compName ) != 0 )
159         file = string( compName ) + "_"; // not MED
160       file += "tmp.med";
161     }
162     return make_pair ( path, file );
163   }
164
165   //================================================================================
166   /*!
167    * \brief Save med objects published in a study
168     * \param theStudy - study to store
169     * \param theURL - path to store
170     * \param isMultiFile - store mode
171     * \param isAscii - store mode: ASCII or NON_ASCII
172     * \retval SALOMEDS::TMPFile* - result file
173    */
174   //================================================================================
175   SALOMEDS::TMPFile* saveStudy (SALOMEDS::SComponent_ptr theComponent,
176                                 const char*              theURL,
177                                 bool                     isMultiFile,
178                                 bool                     isAscii)
179   {
180     // Write all MEDMEM objects in one med file because of problems with
181     // reference to external mesh when writting field in a separate file.
182     // Actually, writting is OK, but when reading a field, its support
183     // is updated using mesh data missing in the file being read
184
185     // If arises a problem of meshes or other objects having equal names,
186     // the solution can be in renaming them using study entry before writting
187     // and renaming back during restoration, real names will be stored in
188     // LocalPersistentID's for example
189
190     if (CORBA::is_nil(theComponent)) {
191       SALOMEDS::TMPFile_var aStreamFile;
192       return aStreamFile._retn();
193     }
194
195     SALOMEDS::Study_var study = theComponent->GetStudy();
196
197     pair<string,string> aDir_aFileName =
198       getPersistanceDirAndFileName(theComponent, theURL, isMultiFile, SAVE );
199     string& aPath     = aDir_aFileName.first;
200     string& aBaseName = aDir_aFileName.second;
201     string aFile      = aPath + aBaseName;
202
203     SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
204     aSeq->length(1);
205     aSeq[0] = CORBA::string_dup(aBaseName.c_str());
206
207     if (isMultiFile) { // remove existing file
208       //cout << "-----------------Remove " << aPath<< ", "<<aBaseName << endl;
209       SALOMEDS_Tool::RemoveTemporaryFiles(aPath.c_str(), aSeq.in(), true);
210     }
211
212     // First save fields and their meshes and then not saved meshes
213
214     set< ::MEDMEM::GMESH* > savedMeshes;
215     {
216       SALOMEDS::ChildIterator_var anIter = study->NewChildIterator(theComponent);
217       anIter->InitEx(1);
218       for (; anIter->More(); anIter->Next()) {
219         SALOMEDS::SObject_var aSO = anIter->Value();
220         SALOME_MED::FIELD_var myField = SALOME_MED::FIELD::_narrow( aSO->GetObject() );
221         if (! CORBA::is_nil(myField)) {
222           long driverId = myField->addDriver(SALOME_MED::MED_DRIVER,
223                                              aFile.c_str(),
224                                              myField->getName());
225           myField->write(driverId,"");
226           // save mesh
227           SALOME_MED::SUPPORT_var sup = myField->getSupport();
228           if ( !sup->_is_nil() ) {
229             SALOME_MED::GMESH_var mesh = sup->getMesh();
230             if ( !mesh->_is_nil() ) {
231               CORBA::Long corbaID = mesh->getCorbaIndex();
232               ::MEDMEM::GMESH* gmesh = GMESH_i::meshMap[ int(corbaID) ];
233               if ( savedMeshes.insert( gmesh ).second ) {
234                 long driverId = mesh->addDriver(SALOME_MED::MED_DRIVER,
235                                                 aFile.c_str(),
236                                                 mesh->getName());
237                 mesh->write(driverId,"");
238               }
239             }
240           }
241         }
242       }
243     }
244
245     {
246       SALOMEDS::ChildIterator_var anIter = study->NewChildIterator(theComponent);
247       anIter->InitEx(1);
248       for (; anIter->More(); anIter->Next()) {
249         SALOMEDS::SObject_var aSO = anIter->Value();
250         SALOME_MED::MESH_var myMesh = SALOME_MED::MESH::_narrow( aSO->GetObject() );
251         if (! CORBA::is_nil(myMesh)) {
252           CORBA::Long corbaID = myMesh->getCorbaIndex();
253           ::MEDMEM::GMESH* gmesh = GMESH_i::meshMap[ int(corbaID) ];
254           if ( savedMeshes.insert( gmesh ).second ) {
255             long driverId = myMesh->addDriver(SALOME_MED::MED_DRIVER,
256                                               aFile.c_str(),
257                                               myMesh->getName());
258             myMesh->write(driverId,"");
259           }
260         }
261       }
262     }
263
264     if ( isAscii )
265       HDFascii::ConvertFromHDFToASCII( aFile.c_str(), true);
266
267     // Convert a file to the byte stream
268     SALOMEDS::TMPFile_var aStreamFile;
269     aStreamFile = SALOMEDS_Tool::PutFilesToStream(aPath.c_str(), aSeq.in(), isMultiFile);
270
271     // Remove a tmp file and directory
272     if (!isMultiFile) {
273       //cout << "-----------------Remove " << aPath<< ", "<<aBaseName << endl;
274       SALOMEDS_Tool::RemoveTemporaryFiles(aPath.c_str(), aSeq.in(), true);
275     }
276     // Return the created byte stream
277     return aStreamFile._retn();
278   } // end of saveStudy()
279
280   //================================================================================
281   /*!
282    * \brief Load study contents
283     * \param theComponent - component holding med data
284     * \param theURL -
285     * \param isMultiFile -
286     * \param isASCII -
287     * \retval char* -
288    */
289   //================================================================================
290   void loadStudy (SALOMEDS::SComponent_ptr theComponent,
291                   const SALOMEDS::TMPFile& theStream,
292                   const char*              theURL,
293                   CORBA::Boolean           isMultiFile,
294                   CORBA::Boolean           isASCII)
295   {
296     SALOMEDS::Study_var study = theComponent->GetStudy();
297
298     // Get file name
299     pair<string,string> aDir_aFileName = getPersistanceDirAndFileName
300       (theComponent, theURL, isMultiFile, RESTORE);
301     string& aPath     = aDir_aFileName.first;
302     string& aBaseName = aDir_aFileName.second;
303     string aFile      = aPath + aBaseName;
304
305     SALOMEDS::ListOfFileNames_var aSeq =
306       SALOMEDS_Tool::PutStreamToFiles(theStream, aPath.c_str(), isMultiFile);
307
308     string aASCIIPath, aASCIIFile;
309     if (isASCII)
310     {
311       aASCIIPath = HDFascii::ConvertFromASCIIToHDF(aFile.c_str());
312       aASCIIFile = "hdf_from_ascii.hdf";
313       aFile = aASCIIPath + aASCIIFile;
314     }
315
316     MED_i* med_i = Med_Gen_Driver_i::GetMED(theComponent);
317     SALOME_MED::MED_var med = med_i->_this();
318
319     // Read all meshes with supports and all fields
320     try
321     {
322       //cout << "-----------------Filename " << aFile << endl;
323       med_i->initWithFieldType(study, MED_DRIVER, aFile, true);
324
325       // publishing must be done by initWithFieldType according to <persistence> flag
326       med_i->addInStudy(study, med, theComponent, 0);
327     }
328     catch (const std::exception & ex)
329     {
330       MESSAGE("Exception Interceptee : ");
331       SCRUTE(ex.what());
332       THROW_SALOME_CORBA_EXCEPTION("Unable to read a hdf file",SALOME::BAD_PARAM);
333     }
334
335     // Remove tmp files
336     bool keepTmpFiles = getenv( "MEDPERSIST_KEEP_TMP_FILES" ); // DEBUG
337     if ( keepTmpFiles )
338       cout << "TMP FILE: " << aFile << endl;
339     if ( !isMultiFile && !keepTmpFiles ) {
340       aSeq->length(1);
341       aSeq[0]=CORBA::string_dup(aBaseName.c_str());
342       SALOMEDS_Tool::RemoveTemporaryFiles(aPath.c_str(), aSeq.in(), true);
343     }
344     if (isASCII)
345     {
346       aSeq->length(1);
347       aSeq[0] = CORBA::string_dup(aASCIIFile.c_str());
348       //cout << "-----------------Remove " << aASCIIPath<< ", "<<aASCIIFile << endl;
349       SALOMEDS_Tool::RemoveTemporaryFiles(aASCIIPath.c_str(), aSeq, true);
350     }
351   } // end loadStudy()
352
353   //================================================================================
354   /*!
355    * \brief retrieve filed features from LocalPersistentID
356     * \param aLocalPersistentID - ID
357     * \param aFieldName - out filed name
358     * \param aNumOrdre - out NumOrdre
359     * \param anIterNumber - out IterNumber
360    */
361   //================================================================================
362   void getFieldNameAndDtIt (const char*   aLocalPersistentID,
363                             string &      aFieldName,
364                             CORBA::Long & aNumOrdre,
365                             CORBA::Long & anIterNumber)
366   {
367     //     aLocalPersistentID(("_MEDFIELD_"+ myField->getName() +
368     //                       "_ORDRE_"+a.str()+
369     //                       "_ITER_"+b.str()+".med"
370     int aLPIdLen = strlen(aLocalPersistentID);
371     const int _MEDFIELD_Len = strlen("_MEDFIELD_");
372     const int _ORDRE_Len    = strlen("_ORDRE_");
373     const int _ITER_Len     = strlen("_ITER_");
374
375     // Get field name: look for _ORDRE_ in aLocalPersistentID
376     int aFieldNameLen = 0, aFieldNameBeg = _MEDFIELD_Len, _ORDRE_Beg;
377     for ( _ORDRE_Beg = aFieldNameBeg; _ORDRE_Beg < aLPIdLen; ++aFieldNameLen,++_ORDRE_Beg )
378       if ( strncmp( &aLocalPersistentID[ _ORDRE_Beg ], "_ORDRE_", _ORDRE_Len ) == 0 )
379         break;
380     aFieldName = string( &(aLocalPersistentID[aFieldNameBeg]), aFieldNameLen);
381
382     // Get orderNumber
383     int anOrderNumberBeg = _ORDRE_Beg + _ORDRE_Len;
384     aNumOrdre = atoi( & aLocalPersistentID[ anOrderNumberBeg ]);
385
386     // Get iterationNumber: look for _ITER_ in aLocalPersistentID
387     int _ITER_Beg = anOrderNumberBeg;
388     for ( ; _ITER_Beg < aLPIdLen; ++_ITER_Beg )
389       if ( strncmp( &aLocalPersistentID[ _ITER_Beg ], "_ITER_", _ITER_Len ) == 0 )
390         break;
391     anIterNumber = atoi( & aLocalPersistentID[ _ITER_Beg + _ITER_Len ]);
392   }
393
394   //================================================================================
395   /*!
396    * \brief Retrieve from aLocalPersistentID data to get support from med
397     * \param aLocalPersistentID - persistent ID
398     * \param type - string "FAMILY", "GROUP" or "SUPPORT
399     * \param name - support name
400     * \param mesh - mesh name
401     * \param entity - support entity
402     * \retval bool - true if all data found in aLocalPersistentID
403    */
404   //================================================================================
405   bool getSupportData (string aLocalPersistentID,
406                        string & type,
407                        string & name,
408                        string & mesh,
409                        string & entity)
410   {
411     // aLocalPersistentID contains:
412     // _MED_[FAMILY|GROUP|SUPPORT]/support_name/ENS_MAA/mesh_name/ENTITY/entity
413     string::size_type slash1Pos = aLocalPersistentID.find("/");
414     if ( slash1Pos == aLocalPersistentID.npos ) return false;
415     string::size_type ens_maaPos = aLocalPersistentID.find("/ENS_MAA/", slash1Pos);
416     if ( ens_maaPos == aLocalPersistentID.npos ) return false;
417     string::size_type entityPos = aLocalPersistentID.find("/ENTITY/", ens_maaPos);
418     if ( entityPos == aLocalPersistentID.npos ) return false;
419
420     string::size_type medSize = strlen("_MED_");
421     string::size_type ens_maaSize = strlen("/ENS_MAA/");
422     string::size_type entitySize = strlen("/ENTITY/");
423
424     type = aLocalPersistentID.substr( medSize, slash1Pos - medSize );
425     name = aLocalPersistentID.substr( slash1Pos + 1, ens_maaPos - slash1Pos - 1);
426     mesh = aLocalPersistentID.substr( ens_maaPos + ens_maaSize,
427                                       entityPos - ens_maaPos - ens_maaSize);
428     entity = aLocalPersistentID.substr( entityPos + entitySize );
429 //     cout << aLocalPersistentID << endl
430 //          << " type: " << type
431 //          << " name: " << name
432 //          << " mesh: " << mesh
433 //          << " entity: " << entity << endl;
434     return true;
435   }
436 } // no name namespace
437
438 //================================================================================
439 /*!
440  * \brief Save data published under MED component
441   * \param theComponent - MED component
442   * \param theURL - path to store
443   * \param isMultiFile - store mode
444   * \retval SALOMEDS::TMPFile* - result file
445  */
446 //================================================================================
447 SALOMEDS::TMPFile* Med_Gen_Driver_i::Save (SALOMEDS::SComponent_ptr theComponent,
448                                            const char* theURL,
449                                            bool isMultiFile)
450 {
451   return saveStudy ( theComponent, theURL, isMultiFile, NON_ASCII );
452 }
453
454 //================================================================================
455 /*!
456  * \brief Save data published under MED component in ASCII file
457   * \param theComponent - MED component
458   * \param theURL - path to store
459   * \param isMultiFile - store mode
460   * \retval SALOMEDS::TMPFile* - result file
461  */
462 //================================================================================
463 SALOMEDS::TMPFile* Med_Gen_Driver_i::SaveASCII (SALOMEDS::SComponent_ptr theComponent,
464                                                 const char* theURL,
465                                                 bool isMultiFile)
466 {
467   return saveStudy ( theComponent, theURL, isMultiFile, ASCII );
468 }
469
470 //=============================================================================
471 /*!
472  *  CORBA: Load Mesh objects (called when an existing study is opened)
473  */
474 //=============================================================================
475
476 CORBA::Boolean Med_Gen_Driver_i::Load (SALOMEDS::SComponent_ptr theComponent,
477                                        const SALOMEDS::TMPFile& theStream,
478                                        const char* theURL,
479                                        bool isMultiFile)
480 {
481   loadStudy ( theComponent, theStream, theURL, isMultiFile, NON_ASCII );
482
483   return true;
484 }
485
486 CORBA::Boolean Med_Gen_Driver_i::LoadASCII (SALOMEDS::SComponent_ptr theComponent,
487                                             const SALOMEDS::TMPFile& theStream,
488                                             const char* theURL,
489                                             bool isMultiFile)
490 {
491   loadStudy ( theComponent, theStream, theURL, isMultiFile, ASCII );
492   return true;
493 }
494
495 //=============================================================================
496 /*!
497  *  CORBA:
498  */
499 //=============================================================================
500 void Med_Gen_Driver_i::Close (SALOMEDS::SComponent_ptr theComponent)
501 {
502   MESSAGE("Med_Gen_Driver_i::Close");
503   SALOMEDS::SObject_var aMedMeshFather = theComponent->GetStudy()->FindObject("MEDMESH");
504   if (!CORBA::is_nil(aMedMeshFather)) {
505     SALOMEDS::ChildIterator_var anIter = theComponent->GetStudy()->NewChildIterator(aMedMeshFather);
506     for(; anIter->More(); anIter->Next()) {
507       SALOMEDS::SObject_var aSO = anIter->Value();
508       SALOMEDS::GenericAttribute_var anAttr;
509       if (aSO->FindAttribute(anAttr,"AttributeIOR")) {
510         CORBA::Object_var myIOR =
511           _driver_orb->string_to_object(SALOMEDS::AttributeIOR::_narrow(anAttr)->Value());
512         SALOME_MED::MESH_var myMesh = SALOME_MED::MESH::_narrow(myIOR);
513         // here must call method destroy of myMesh, but it not implemented yet
514       }
515     }
516   }
517 }
518
519 //=============================================================================
520 /*!
521  *  CORBA: give a persistent reference of a transient object (for study save)
522  */
523 //=============================================================================
524 char* Med_Gen_Driver_i::IORToLocalPersistentID (SALOMEDS::SObject_ptr theSObject,
525                                                 const char* IORString,
526                                                 CORBA::Boolean isMultiFile,
527                                                 CORBA::Boolean isASCII)
528 {
529   SCRUTE(IORString);
530
531   if (string(IORString).size()==0) return CORBA::string_dup("_MED");
532   // Well, we know where put object (_saveFilename) and we know object (IORString)
533   // cast object :
534   CORBA::Object_var myIOR = _driver_orb->string_to_object(IORString);
535
536   // MED
537   SALOME_MED::MED_var myMed = SALOME_MED::MED::_narrow(myIOR);
538   if (! CORBA::is_nil(myMed))
539   {
540     string str_MedName="_MED Objet Med + /OBJ_MED/";
541     return CORBA::string_dup(str_MedName.c_str());
542   }
543
544   // MESH
545   SALOME_MED::MESH_var myMesh = SALOME_MED::MESH::_narrow(myIOR);
546   if (! CORBA::is_nil(myMesh))
547   {
548     CORBA::String_var aName((string("_MEDMESH_")+ myMesh->getName() + ".med").c_str());
549     return aName._retn();
550   }
551
552   // SUPPORT
553   SALOME_MED::SUPPORT_var mySupport = SALOME_MED::SUPPORT::_narrow(myIOR);
554   if (! CORBA::is_nil(mySupport))
555   {
556     string type, str_SupportName;
557     SALOME_MED::FAMILY_var family = SALOME_MED::FAMILY::_narrow(myIOR);
558     if ( !family->_is_nil() )
559       type = "_MED_FAMILY";
560     else {
561       SALOME_MED::GROUP_var grp = SALOME_MED::GROUP::_narrow(myIOR);
562       if ( !grp->_is_nil() )
563         type = "_MED_GROUP";
564       else
565         type = "_MED_SUPPORT";
566     }
567     try  {
568       ostringstream os;
569       os << type << "/" << mySupport->getName();
570       os << "/ENS_MAA/" << mySupport->getMesh()->getName();
571       os << "/ENTITY/" << mySupport->getEntity();
572       str_SupportName = os.str();
573     }
574     catch(...) {
575       MESSAGE("Unable to save the support");
576       THROW_SALOME_CORBA_EXCEPTION("Unable to save Field in Med"\
577                                    ,SALOME::INTERNAL_ERROR);
578     }
579     return CORBA::string_dup(str_SupportName.c_str());
580   }
581
582   SALOME_MED::FIELD_var myField = SALOME_MED::FIELD::_narrow(myIOR);
583   if (! CORBA::is_nil(myField))
584   {
585     string str_FieldName;
586     ostringstream a,b;
587     a<< myField->getOrderNumber();
588     b<< myField->getIterationNumber();
589     CORBA::String_var aName((string("_MEDFIELD_")+ myField->getName() +
590                              string("_ORDRE_")+a.str()+
591                              string("_ITER_")+b.str() +
592                              ".med").c_str());
593     return aName._retn();
594   }
595
596   //THROW_SALOME_CORBA_EXCEPTION("Unable to save IOR",SALOME::BAD_PARAM);
597   return CORBA::string_dup("_MED");
598 }
599
600 //=============================================================================
601 /*!
602  *  CORBA: give a transient reference (when loading an object, opening study)
603  */
604 //=============================================================================
605 char* Med_Gen_Driver_i::LocalPersistentIDToIOR (SALOMEDS::SObject_ptr theSObject,
606                                                 const char* aLocalPersistentID,
607                                                 CORBA::Boolean isMultiFile,
608                                                 CORBA::Boolean isASCII)
609   throw(SALOME::SALOME_Exception)
610 {
611   // all object are restored in Load() if their name in study coincides
612   // with a default one generated by object.addInStudy(...)
613   CORBA::String_var ior = theSObject->GetIOR();
614   bool restoredByLoad = ( ior.in() && strlen( ior ) > 0 );
615
616   if ( !restoredByLoad )
617   {
618     CORBA::Object_var object;
619     SALOMEDS::SComponent_var component = theSObject->GetFatherComponent();
620     MED_i* med_i = Med_Gen_Driver_i::GetMED(component);
621     SALOME_MED::MED_var med = med_i->_this();
622
623     // MED
624     if (strcmp(aLocalPersistentID, "_MED Objet Med + /OBJ_MED/") == 0)
625     {
626       //object = med;
627       object = SALOME_MED::MED::_duplicate(med);
628     }
629     // MESH
630     else if (strncmp(aLocalPersistentID, "_MEDMESH_",9) == 0)
631     {
632       int aMeshNameLen = strlen(aLocalPersistentID) - 12;
633       string aMeshName( &(aLocalPersistentID[9]), aMeshNameLen);
634       aMeshName[aMeshNameLen-1] = 0;
635       try {
636         object = med->getMeshByName( aMeshName.c_str() );
637         if ( CORBA::is_nil( object )) {
638           aMeshName = healName( aMeshName );
639           object = med->getMeshByName( aMeshName.c_str() );
640         }
641       }
642       catch (const std::exception & ex) {
643         SCRUTE(ex.what());
644         THROW_SALOME_CORBA_EXCEPTION("Unable to find a mesh by name in this file",
645                                      SALOME::INTERNAL_ERROR);
646       }
647     }
648     // FIELD
649     else if (strncmp(aLocalPersistentID, "_MEDFIELD_",10) == 0)
650     {
651       // Field Name
652       string aFieldName;
653       CORBA::Long aNumOrdre, anIterNumber;
654       getFieldNameAndDtIt( aLocalPersistentID, aFieldName, aNumOrdre, anIterNumber );
655       // Get a field that is already read
656       try {
657         object = med->getField( aFieldName.c_str(), anIterNumber, aNumOrdre );
658         if ( CORBA::is_nil( object )) {
659           aFieldName = healName( aFieldName );
660           object = med->getField( aFieldName.c_str(), anIterNumber, aNumOrdre );
661         }
662       }
663       catch (const std::exception & ex) {
664         SCRUTE(ex.what());
665         THROW_SALOME_CORBA_EXCEPTION("Unable to find a field by name in this file",
666                                      SALOME::INTERNAL_ERROR);
667       }
668     }
669     // SUPPORT?
670     else {
671       string type, name, meshName, entity;
672       if ( getSupportData( aLocalPersistentID, type, name, meshName, entity ))
673       {
674         MED_EN::medEntityMesh medEntity( atoi( entity.c_str() ));
675
676         if ( type == "SUPPORT" ) {
677           try {
678             object = med_i->getSupport( meshName, medEntity );
679             if ( CORBA::is_nil( object )) {
680               meshName = healName( meshName );
681               object = med_i->getSupport( meshName, medEntity );
682             }
683           }
684           catch (const std::exception & ex) {
685             SCRUTE(ex.what());
686             THROW_SALOME_CORBA_EXCEPTION("Unable to find support in this file",
687                                          SALOME::INTERNAL_ERROR);
688           }
689         }
690         else {
691           SALOME_MED::GMESH_var mesh;
692           try {
693             mesh = med->getMeshByName( meshName.c_str() );
694             if ( mesh->_is_nil() ) {
695               meshName = healName( meshName );
696               mesh = med->getMeshByName( meshName.c_str() );
697             }
698           }
699           catch (const std::exception & ex) {
700             SCRUTE(ex.what());
701             THROW_SALOME_CORBA_EXCEPTION("Unable to find mesh in this file",
702                                          SALOME::INTERNAL_ERROR);
703           }
704           if ( !mesh->_is_nil() ) {
705             string healedName = healName( name );
706             try {
707               if ( type == "FAMILY" ) {
708                 SALOME_MED::Family_array_var families = mesh->getFamilies( medEntity );
709                 for ( int i = 0; CORBA::is_nil(object) && i <= (int)families->length(); ++i )
710                   if ( families[ i ]->getName() == name ||
711                        families[ i ]->getName() == healedName )
712                     object = SALOME_MED::FAMILY::_duplicate( families[ i ]);
713               }
714               else {
715                 SALOME_MED::Group_array_var groups = mesh->getGroups( medEntity );
716                 for ( int i = 0; CORBA::is_nil(object) && i <= (int)groups->length(); ++i )
717                   if ( groups[ i ]->getName() == name ||
718                        groups[ i ]->getName() == healedName )
719                     object = SALOME_MED::GROUP::_duplicate( groups[ i ]);
720               }
721             }
722             catch (const std::exception & ex) {
723               SCRUTE(ex.what());
724               THROW_SALOME_CORBA_EXCEPTION("Unable to find support in this file",
725                                            SALOME::INTERNAL_ERROR);
726             }
727           }
728         }
729       }
730     }
731     if ( !CORBA::is_nil(object) )
732       ior = _driver_orb->object_to_string( object );
733     else
734       THROW_SALOME_CORBA_EXCEPTION("Unable to find the object in this file",
735                                    SALOME::INTERNAL_ERROR);
736
737   } // !restoredByLoad
738
739   return ior._retn();
740 }
741
742 //=============================================================================
743 /*!
744  *  returns true, if can publish object
745  */
746 //=============================================================================
747 bool Med_Gen_Driver_i::CanPublishInStudy (CORBA::Object_ptr theIOR)
748 {
749   SALOME_MED::MESH_var aMesh = SALOME_MED::MESH::_narrow(theIOR);
750   if ( !aMesh->_is_nil())
751     return true;
752   SALOME_MED::FIELD_var aField = SALOME_MED::FIELD::_narrow(theIOR);
753   if ( !aField->_is_nil())
754     return true;
755   //SALOME_MED::SUPPORT_var aSupport = SALOME_MED::SUPPORT::_narrow(theIOR);
756   //if ( !aSupport->_is_nil())
757   //  return true;
758   return false;
759 }
760
761 //=============================================================================
762 /*!
763  *  publish the given object
764  */
765 //=============================================================================
766 SALOMEDS::SObject_ptr Med_Gen_Driver_i::PublishInStudy (SALOMEDS::Study_ptr theStudy,
767                                                         SALOMEDS::SObject_ptr theSObject,
768                                                         CORBA::Object_ptr theObject,
769                                                         const char* theName)
770   throw (SALOME::SALOME_Exception)
771 {
772   SALOMEDS::SObject_var aResultSO;
773
774   if (CORBA::is_nil(theObject)) return aResultSO;
775   if (theStudy->_is_nil()) return aResultSO;
776
777   SALOMEDS::StudyBuilder_var aBuilder = theStudy->NewBuilder();
778   SALOMEDS::SComponent_var aFather = theStudy->FindComponent(ComponentDataType());
779
780   if (aFather->_is_nil()) {
781     aFather = aBuilder->NewComponent(ComponentDataType());
782     if (aFather->_is_nil()) return aResultSO;
783
784     SALOMEDS::GenericAttribute_var anAttr = aBuilder->FindOrCreateAttribute(aFather, "AttributeName");
785     SALOMEDS::AttributeName_var    aName = SALOMEDS::AttributeName::_narrow(anAttr);
786     //NRI    aName->SetValue("MED");
787
788     CORBA::Object_var objVarN = _NS->Resolve("/Kernel/ModulCatalog");
789     SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
790       SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
791     SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent(ComponentDataType());
792     if (!Comp->_is_nil()) {
793       aName->SetValue(Comp->componentusername());
794     }
795
796     aBuilder->DefineComponentInstance(aFather, GetComponentInstance());
797   }
798
799   if (CORBA::is_nil(theSObject)) {
800     SALOME_MED::MESH_var aMesh = SALOME_MED::MESH::_narrow(theObject);
801     if (!aMesh->_is_nil()) {
802       aMesh->addInStudy(theStudy, aMesh);
803     }
804     else {
805       SALOME_MED::FIELD_var aField = SALOME_MED::FIELD::_narrow(theObject);
806       if (!aField->_is_nil()) {
807         aField->addInStudyToComponent(aFather, aField);
808       }
809       //else {
810       //  SALOME_MED::SUPPORT_var aSupport = SALOME_MED::SUPPORT::_narrow(theObject);
811       //  if (!aSupport->_is_nil())
812       //    aSupport->addInStudy(theStudy, aSupport);
813       //}
814     }
815     aResultSO = theStudy->FindObjectIOR(_driver_orb->object_to_string(theObject));
816   } else {
817     //if (!theSObject->ReferencedObject(aResultSO))
818     //  THROW_SALOME_CORBA_EXCEPTION("Publish in study MED object error",SALOME::BAD_PARAM);
819   }
820   //aBuilder->Addreference(theObject, aResultSO);
821   return aResultSO._retn();
822 }
823
824 //=============================================================================
825 /*!
826  *  returns true, if can copy the object
827  */
828 //=============================================================================
829 CORBA::Boolean Med_Gen_Driver_i::CanCopy (SALOMEDS::SObject_ptr theObject)
830 {
831   // Try to retrieve known by MED component mesh by given IOR
832   SALOMEDS::GenericAttribute_var anAttr;
833   if (!theObject->FindAttribute(anAttr, "AttributeIOR")) return false;
834   try {
835     CORBA::Object_var anObj =
836       _driver_orb->string_to_object(SALOMEDS::AttributeIOR::_narrow(anAttr)->Value());
837     SALOME_MED::MESH_var aMesh = SALOME_MED::MESH::_narrow(anObj);
838     // If the object is null one it can't be copied: return false
839     if (aMesh->_is_nil()) return false;
840   } catch(...) {
841     return false;
842   }
843   return true;
844 }
845
846 //=============================================================================
847 /*!
848  *  create copy of the object and put it to the stream
849  */
850 //=============================================================================
851 SALOMEDS::TMPFile* Med_Gen_Driver_i::CopyFrom (SALOMEDS::SObject_ptr theObject,
852                                                CORBA::Long& theObjectID)
853 {
854   // Declare a sequence of the byte to store the copied object
855   SALOMEDS::TMPFile_var aStreamFile;
856
857   // Try to get GEOM_Shape object by given SObject
858   SALOMEDS::GenericAttribute_var anAttr;
859   if (!theObject->FindAttribute(anAttr, "AttributeIOR")) return new SALOMEDS::TMPFile(0);
860   CORBA::String_var anIOR = CORBA::string_dup(SALOMEDS::AttributeIOR::_narrow(anAttr)->Value());
861   CORBA::Object_var anObj = _driver_orb->string_to_object(anIOR);
862   SALOME_MED::MESH_var aMesh = SALOME_MED::MESH::_narrow(anObj);
863   if (aMesh->_is_nil()) return new SALOMEDS::TMPFile(0);
864
865   // Get a temporary directory to store a temporary file
866   CORBA::String_var aTmpDir = SALOMEDS_Tool::GetTmpDir().c_str();
867   // Create a list to store names of created files
868   SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
869   aSeq->length(1);
870   aSeq[0] = CORBA::string_dup(aMesh->getName());
871   char* aFullName = new char[strlen(aTmpDir)+strlen(aSeq[0])+1];
872   strcpy(aFullName, aTmpDir);
873   strcpy(aFullName+strlen(aTmpDir), aSeq[0]);
874
875   long driverId = aMesh->addDriver(SALOME_MED::MED_DRIVER,aFullName , aMesh->getName());
876   aMesh->write(driverId,"");
877
878   //  aStreamFile = SALOMEDS_Tool::PutFilesToStream(aTmpDir.c_str(), aSeq.in(), false);
879   char* aFullName1 = new char[strlen(aTmpDir)+1];
880   strcpy(aFullName1, aTmpDir);
881   aStreamFile = SALOMEDS_Tool::PutFilesToStream(aFullName1, aSeq.in(), false);
882   //  SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
883   SALOMEDS_Tool::RemoveTemporaryFiles(aFullName1, aSeq.in(), true);
884
885   // Assign an ID = 1 the the type SALOME_MED::MESH
886   theObjectID = 1;
887
888   return aStreamFile._retn();
889 }
890
891 //=============================================================================
892 /*!
893  *  returns true, if can copy the object
894  */
895 //=============================================================================
896 CORBA::Boolean Med_Gen_Driver_i::CanPaste (const char* theComponentName, CORBA::Long theObjectID)
897 {
898   // The MED component can paste only objects copied by MED component
899   // and with the object type = 1 (mesh)
900   if (strcmp(theComponentName, ComponentDataType()) != 0 || theObjectID != 1) return false;
901   return true;
902 }
903
904 //=============================================================================
905 /*!
906  *  returns true, if can copy the object
907  */
908 //=============================================================================
909 SALOMEDS::SObject_ptr Med_Gen_Driver_i::PasteInto (const SALOMEDS::TMPFile& theStream,
910                                                    CORBA::Long theObjectID,
911                                                    SALOMEDS::SObject_ptr theObject)
912 {
913   SALOMEDS::SObject_var aResultSO = SALOMEDS::SObject::_duplicate(theObject);
914   if (theStream.length() == 0) return aResultSO._retn();
915
916   SALOMEDS::Study_var aStudy = theObject->GetStudy();
917
918   CORBA::String_var aTmpDir = CORBA::string_dup(SALOMEDS_Tool::GetTmpDir().c_str());
919   char* aFullName2 = new char[strlen(aTmpDir)+1];
920   strcpy(aFullName2,aTmpDir);
921   //  SALOMEDS::ListOfFileNames_var aSeq = SALOMEDS_Tool::PutStreamToFiles(theStream, aTmpDir, false);
922   SALOMEDS::ListOfFileNames_var aSeq = SALOMEDS_Tool::PutStreamToFiles(theStream, aFullName2, false);
923   CORBA::String_var aMeshName = CORBA::string_dup(aSeq[0]);
924   char* aFullName = new char[strlen(aTmpDir)+strlen(aMeshName)+1];
925   strcpy(aFullName, aTmpDir);
926   strcpy(aFullName+strlen(aTmpDir), aMeshName);
927
928   MESH * myMesh= new MESH();
929   //  myMesh->setName(aMeshName.c_str());
930   char* aFullMeshName = new char[strlen(aMeshName)+1];
931   strcpy(aFullMeshName,aMeshName);
932   myMesh->setName(aFullMeshName);
933   MED_MESH_RDONLY_DRIVER myMeshDriver(aFullName, myMesh);
934   try {
935     myMeshDriver.setMeshName(aFullMeshName);
936     myMeshDriver.open();
937   } catch (const std::exception & ex) {
938     MESSAGE("Exception Interceptee : ");
939     SCRUTE(ex.what());
940     return aResultSO._retn();
941   };
942   try {
943     myMeshDriver.read();
944     MESSAGE("apres read");
945     myMeshDriver.close();
946   } catch (const std::exception & ex) {
947     MESSAGE("Exception Interceptee : ");
948     SCRUTE(ex.what());
949     return aResultSO._retn();
950   };
951   // set new mesh name, becouse now there are no possibility to operate meshes with the same names
952 //    srand((unsigned int)time(NULL));
953   int aRND = rand(); //Get a random number to present a name of a copied mesh
954   char aCopiedMeshName[127];
955   sprintf(aCopiedMeshName,"MESH_COPY_%d",aRND);
956   myMesh->setName(aCopiedMeshName);
957   MESH_i * meshi = new MESH_i(myMesh);
958   SALOME_MED::MESH_ptr mesh = meshi->_this();
959   // add the mesh object in study
960   meshi->addInStudy(aStudy,mesh);
961   // get the IOR attribute of just added mesh
962   CORBA::String_var anIORString = _driver_orb->object_to_string(mesh);
963   aResultSO = aStudy->FindObjectIOR(anIORString);
964
965   char * aFullName1 = new char[strlen(aTmpDir)+1];
966   strcpy(aFullName1,aTmpDir);
967   //  SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
968   SALOMEDS_Tool::RemoveTemporaryFiles(aFullName1, aSeq.in(), true);
969
970   return aResultSO._retn();
971 }