Salome HOME
Merge from V6_main (04/10/2012)
[modules/med.git] / src / MEDOP / cmp / MEDDataManager_i.cxx
1 // Copyright (C) 2007-2012  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 // Authors : Guillaume Boulant (EDF) - 01/06/2011
24
25 #include "MEDDataManager_i.hxx"
26 #include "SALOME_KernelServices.hxx"
27 #include "Basics_DirUtils.hxx"
28 #include "Basics_Utils.hxx"
29
30 #include "MEDLoader.hxx"
31 using namespace ParaMEDMEM;
32
33 #include <string>
34 #include <vector>
35 using namespace std;
36
37 MEDDataManager_i * MEDDataManager_i::_instance = NULL;
38 long MEDDataManager_i::LONG_UNDEFINED = -1;
39
40 MEDDataManager_i * MEDDataManager_i::getInstance() {
41   // _GBO_ we will certainly need to define one single DataManager per
42   // SALOME study and not one singleton for the whole session
43   if ( _instance == NULL ) {
44     _instance = new MEDDataManager_i();
45   }
46   return _instance;
47 }
48
49 #define IOR_UNDEF "IOR UNDEFINED"
50 MEDDataManager_i::MEDDataManager_i()
51 {
52   LOG("Creating a MEDDataManager_i instance");
53   _fieldLastId = 0;
54   _sourceLastId = 0;
55   _meshLastId = 0;
56   _fieldseriesLastId = 0;
57   _medEventListenerIOR = NULL;
58 }
59 MEDDataManager_i::~MEDDataManager_i()
60 {
61   LOG("Deleting MEDDataManager_i instance");
62 }
63
64 const char * MEDDataManager_i::file_to_source(const char * filepath)
65 {
66   string * source = new string("file://");
67   source->append(filepath);
68   return source->c_str();;
69 }
70 const char * MEDDataManager_i::source_to_file(const char * source)
71 {
72   string * filepath = new string(source);
73   filepath->replace(0,7,"");
74   return filepath->c_str();
75 }
76
77 /*!
78  * This function loads the meta-data from the specified med file and
79  * returns the associated datasource handler. The data source handler
80  * is a key to retrieve all informations concerning the data (meshes,
81  * fields).
82  */
83 MEDOP::DatasourceHandler * MEDDataManager_i::addDatasource(const char *filepath) {
84
85   // We first check that this datasource is not already registered  
86   long sourceid = getDatasourceId(filepath);
87   if ( sourceid != LONG_UNDEFINED ) {
88     // The file is already registered under the identifier sourceid
89     LOG("WRN: The file "<<filepath<<" is already registered with id="<<ToString(sourceid));
90     return new MEDOP::DatasourceHandler(*_datasourceHandlerMap[sourceid]);
91   }
92
93   // Then we check that the file is readable by MEDLoader
94   MEDLoader::CheckFileForRead(filepath);
95
96   // Initialise the datasource handler
97   MEDOP::DatasourceHandler * datasourceHandler = new MEDOP::DatasourceHandler();
98   datasourceHandler->id = _sourceLastId; _sourceLastId++;
99   datasourceHandler->name = (Kernel_Utils::GetBaseName(filepath)).c_str();
100   datasourceHandler->uri = file_to_source(filepath);
101   _datasourceHandlerMap[datasourceHandler->id] = datasourceHandler;
102
103   // We start by read the list of meshes (spatial supports of fields)
104   vector<string> meshNames = MEDLoader::GetMeshNames(filepath);
105   int nbOfMeshes = meshNames.size();
106   for (int iMesh = 0; iMesh < nbOfMeshes; iMesh++) {
107     const char * meshName = meshNames[iMesh].c_str();
108     LOG("name of mesh " << iMesh << " = " << meshName);
109
110     MEDOP::MeshHandler * meshHandler = new MEDOP::MeshHandler();
111     meshHandler->id       = _meshLastId; _meshLastId++;
112     meshHandler->name     = meshName;
113     meshHandler->sourceid = datasourceHandler->id;
114
115     _meshHandlerMap[meshHandler->id] = meshHandler;
116
117     // For each mesh, we can read the list of the names of the
118     // associated fields, i.e. fields whose spatial support is this
119     // mesh.
120     vector<string> fieldNames = MEDLoader::GetAllFieldNamesOnMesh(filepath,
121                                                                   meshName);
122     int nbOfFields = fieldNames.size();
123     for (int iField = 0; iField < nbOfFields; iField++) {
124       const char * fieldName = fieldNames[iField].c_str();
125       LOG("-- name of field " << iField << " = " << fieldName);
126       
127       // A field name could identify several MEDCoupling fields, that
128       // differ by their spatial discretization on the mesh (values on
129       // cells, values on nodes, ...). This spatial discretization is
130       // specified by the TypeOfField that is an integer value in this
131       // list:
132       // 0 = ON_CELLS   
133       // 1 = ON_NODES   
134       // 2 = ON_GAUSS_PT        
135       // 3 = ON_GAUSS_NE
136
137       // As a consequence, before loading values of a field, we have
138       // to determine the types of spatial discretization defined for
139       // this field and to chooose one.
140
141       vector<TypeOfField> listOfTypes = MEDLoader::GetTypesOfField(filepath,
142                                                                    meshName,
143                                                                    fieldName);
144       int nbOfTypes = listOfTypes.size();
145       for (int iType = 0; iType < nbOfTypes; iType++) {
146         LOG("---- type "<<iType<<" of field "<<iField<< " = " << listOfTypes[iType]);
147
148         // Then, we can get the iterations associated to this field on
149         // this type of spatial discretization:
150         std::vector< std::pair<int,int> > fieldIterations = 
151           MEDLoader::GetFieldIterations(listOfTypes[iType],
152                                         filepath,
153                                         meshName,
154                                         fieldName);
155         
156         int nbFieldIterations = fieldIterations.size();
157         LOG("---- nb. iterations = " << nbFieldIterations);
158
159         // We can define the timeseries of fields (fieldseries) for
160         // this type. A fieldseries is a macro object that handle the whole
161         // set of time iterations of a field.
162         MEDOP::FieldseriesHandler * fieldseriesHandler = new MEDOP::FieldseriesHandler();
163         fieldseriesHandler->id     = _fieldseriesLastId; _fieldseriesLastId++;
164         fieldseriesHandler->name   = fieldName;
165         fieldseriesHandler->type   = listOfTypes[iType];
166         fieldseriesHandler->meshid = meshHandler->id;
167         fieldseriesHandler->nbIter = nbFieldIterations;
168         _fieldseriesHandlerMap[fieldseriesHandler->id] = fieldseriesHandler;
169
170         // We can then load meta-data concerning all iterations
171         for (int iterationIdx=0; iterationIdx<nbFieldIterations; iterationIdx++) {
172           
173           int iteration = fieldIterations[iterationIdx].first;
174           int order = fieldIterations[iterationIdx].second;
175           
176           const char * source = datasourceHandler->uri;
177           MEDOP::FieldHandler * fieldHandler = newFieldHandler(fieldName,
178                                                                meshName,
179                                                                listOfTypes[iType],
180                                                                iteration,
181                                                                order,
182                                                                source);
183           
184           fieldHandler->meshid = meshHandler->id;
185           fieldHandler->fieldseriesId = fieldseriesHandler->id;
186           _fieldHandlerMap[fieldHandler->id] = fieldHandler;
187         }
188       }
189     }
190   }
191   
192   return new MEDOP::DatasourceHandler(*datasourceHandler);
193 }
194
195 long MEDDataManager_i::getDatasourceId(const char *filepath) {
196   const char * uri = file_to_source(filepath);
197   DatasourceHandlerMapIterator it = _datasourceHandlerMap.begin();  
198   while ( it != _datasourceHandlerMap.end() ) {
199     if ( strcmp(it->second->uri,uri) == 0 ) {
200       return it->first;
201     }
202     ++it;
203   }
204   return LONG_UNDEFINED;
205 }
206
207
208 MEDOP::MeshHandler * MEDDataManager_i::getMesh(CORBA::Long meshId) {
209   if ( _meshHandlerMap.count(meshId) == 0 ) {
210     std::string message =
211       std::string("The mesh of id=") + ToString(meshId) +
212       std::string(" does not exist in the data manager");
213     LOG(message);
214     throw KERNEL::createSalomeException(message.c_str());
215   }
216   return new MEDOP::MeshHandler(*(_meshHandlerMap[meshId]));
217 }
218
219
220 /*!
221  * This function returns the list of mesh handlers associated to the
222  * specified datasource. It corresponds to the list ofmeshes defined
223  * in the datasource.
224  */
225 MEDOP::MeshHandlerList * MEDDataManager_i::getMeshList(CORBA::Long datasourceId) {
226
227   // We initiate a list with the maximum lentgh
228   MEDOP::MeshHandlerList_var meshHandlerList = new MEDOP::MeshHandlerList();
229   meshHandlerList->length(_meshHandlerMap.size());
230
231   // Scan the map looking for meshes associated to the specified datasource
232   int itemIdx = 0;
233   MeshHandlerMapIterator meshIt;
234   for ( meshIt=_meshHandlerMap.begin(); meshIt != _meshHandlerMap.end(); meshIt++) {
235     if ( meshIt->second->sourceid == datasourceId ) {
236       meshHandlerList[itemIdx] = *(meshIt->second);
237       itemIdx++;
238     }
239   }
240
241   // Adjust the length to the real number of elements
242   meshHandlerList->length(itemIdx);
243   return meshHandlerList._retn();
244 }
245
246 /*!
247  * This function returns the list of fieldseries defined on the
248  * specified mesh.
249  */
250 MEDOP::FieldseriesHandlerList * MEDDataManager_i::getFieldseriesListOnMesh(CORBA::Long meshId) {
251   // We initiate a list with the maximum lentgh
252   MEDOP::FieldseriesHandlerList_var
253     fieldseriesHandlerList = new MEDOP::FieldseriesHandlerList();
254   fieldseriesHandlerList->length(_fieldseriesHandlerMap.size());
255
256   // Scan the map looking for fieldseries defined on the specified mesh
257   int itemIdx = 0;
258   FieldseriesHandlerMapIterator it;
259   for ( it=_fieldseriesHandlerMap.begin(); it != _fieldseriesHandlerMap.end(); it++) {
260     if ( it->second->meshid == meshId ) {
261       fieldseriesHandlerList[itemIdx] = *(it->second);
262       itemIdx++;
263     }
264   }
265
266   // Adjust the length to the real number of elements
267   fieldseriesHandlerList->length(itemIdx);
268   return fieldseriesHandlerList._retn();
269 }
270
271 /*!
272  * A fieldseries is a timeseries of fields. Then the list of fields is
273  * the different time iterations defined for the specified field id.  
274  */
275 MEDOP::FieldHandlerList * MEDDataManager_i::getFieldListInFieldseries(CORBA::Long fieldseriesId) {
276
277   // We initiate a list with the maximum lentgh
278   MEDOP::FieldHandlerList_var fieldHandlerList = new MEDOP::FieldHandlerList();
279   fieldHandlerList->length(_fieldHandlerMap.size());
280
281   // Scan the map looking for field defined on the specified mesh
282   int itemIdx = 0;
283   FieldHandlerMapIterator it;
284   for ( it=_fieldHandlerMap.begin(); it != _fieldHandlerMap.end(); it++) {
285     if ( it->second->fieldseriesId == fieldseriesId ) {
286       fieldHandlerList[itemIdx] = *(it->second);
287       itemIdx++;
288     }
289   }
290
291   // Adjust the length to the real number of elements
292   fieldHandlerList->length(itemIdx);
293   return fieldHandlerList._retn();
294 }
295
296 /*!
297  * This returns the whole set of fields handlers for all datasource
298  * that have been loaded using addDatasource.
299  */
300 MEDOP::FieldHandlerList * MEDDataManager_i::getFieldHandlerList() {
301   MEDOP::FieldHandlerList_var fieldHandlerSeq = new MEDOP::FieldHandlerList();
302   fieldHandlerSeq->length(_fieldHandlerMap.size());
303
304   int sequenceId = 0;
305   FieldHandlerMapIterator fieldIt;
306   for ( fieldIt=_fieldHandlerMap.begin(); fieldIt != _fieldHandlerMap.end(); fieldIt++) {
307     fieldHandlerSeq[sequenceId] = *(fieldIt->second);
308     sequenceId++;
309   }
310   return fieldHandlerSeq._retn();
311 }
312
313 /*!
314  * This returns a copy of the fieldHandler associated to the specified id.
315  */
316 MEDOP::FieldHandler * MEDDataManager_i::getFieldHandler(CORBA::Long fieldHandlerId) {
317   LOG("getFieldHandler: START")
318
319   FieldHandlerMapIterator fieldIt = _fieldHandlerMap.find(fieldHandlerId);
320   if ( fieldIt != _fieldHandlerMap.end() ) {
321     // >>> WARNING: CORBA struct specification indicates that the
322     // assignement acts as a desctructor for the structure that is
323     // pointed to. The values of the fields are copy first in the new
324     // structure that receives the assignement and finally the initial
325     // structure is destroyed. In the present case, WE WANT to keep
326     // the initial fieldHandler in the map. We must then make a deep
327     // copy of the structure found in the map and return the copy. The
328     // CORBA struct specification indicates that a deep copy can be
329     // done using the copy constructor.  <<<
330     return new MEDOP::FieldHandler(*(fieldIt->second));
331   }
332   return NULL;
333 }
334
335 /*!
336  * This returns a string representation of the field associated to the specified id.
337  */
338 char * MEDDataManager_i::getFieldRepresentation(CORBA::Long fieldHandlerId) {
339   LOG("getFieldRepresentation: START")
340   MEDOP::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId);
341   MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler);
342   return CORBA::string_dup(fieldDouble->getArray()->repr().c_str());
343 }
344
345 void MEDDataManager_i::saveFields(const char * filepath,
346                                   const MEDOP::FieldIdList & fieldIdList)
347 {
348   LOG("saveFields to : " << filepath);
349
350   // We first have to check if the target filepath is writable
351   // (segmentation fault in med otherwise)
352   if (!Kernel_Utils::IsWritable(Kernel_Utils::GetDirName(std::string(filepath)))) {
353     std::string message =
354       std::string("The target filepath ") +
355       std::string(filepath) +
356       std::string(" is not writable");
357     LOG(message);
358     throw KERNEL::createSalomeException(message.c_str());
359   }
360
361   if ( fieldIdList.length() == 0 ) {
362     throw KERNEL::createSalomeException("No fields to save");
363   }
364   
365   // Consider the first field to initiate the med file
366   CORBA::Long fieldHandlerId = fieldIdList[0];
367   MEDOP::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId);
368   MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler);  
369
370   try {
371     bool writeFromScratch = true;
372     MEDLoader::WriteField(filepath, fieldDouble, writeFromScratch);
373     
374     writeFromScratch = false;
375     for(CORBA::ULong i=1; i<fieldIdList.length(); i++) {
376       fieldHandlerId = fieldIdList[i];
377       fieldHandler = getFieldHandler(fieldHandlerId);
378       fieldDouble = getFieldDouble(fieldHandler);  
379       MEDLoader::WriteField(filepath, fieldDouble, writeFromScratch);
380     }
381   }
382   catch (INTERP_KERNEL::Exception &ex) {
383     std::string message = 
384       std::string("Error when saving file ") +
385       std::string(filepath) + std::string(" : ") + ex.what();
386     throw KERNEL::createSalomeException(message.c_str());
387   }
388   catch (const std::exception& ex) {
389     std::string message = 
390       std::string("Error when saving file ") +
391       std::string(filepath) + std::string(" : ") + ex.what();
392     throw KERNEL::createSalomeException(message.c_str());
393   }
394
395 }
396
397 /*!
398  * This function must be used to indicate that the field with the
399  * specified id must be considered as persistent (if persistent is
400  * true) or not persistent (if persistent is false). If a field is
401  * marked as persistent, then it is automatically saved when the
402  * function savePersistentFields is called.
403  */
404 void MEDDataManager_i::markAsPersistent(CORBA::Long fieldHandlerId, bool persistent) {
405   LOG("mark as persistant : id="<<fieldHandlerId);
406   _fieldPersistencyMap[fieldHandlerId] = persistent;
407 }
408
409 void MEDDataManager_i::savePersistentFields(const char * filepath) {
410   LOG("savePersistentFields to : " << filepath);
411   std::vector<long> listId;
412
413   FieldPersistencyMapIterator mapIt;
414   for ( mapIt = _fieldPersistencyMap.begin(); mapIt != _fieldPersistencyMap.end(); mapIt++) {
415     if ( mapIt->second == true ) {
416       listId.push_back(mapIt->first);
417     }
418   }
419   
420   MEDOP::FieldIdList fieldIdList;
421   fieldIdList.length(listId.size());
422   for (int i=0; i<listId.size(); i++) {
423     fieldIdList[i] = CORBA::Long(listId[i]);
424   }
425   
426   try {
427     this->saveFields(filepath, fieldIdList);
428   } 
429   catch (const SALOME::SALOME_Exception & ex) {
430     throw ex;
431   }
432   catch (const std::exception& ex) {
433     std::string message = 
434       std::string("Error when saving file ") +
435       std::string(filepath) + std::string(" : ") + ex.what();
436     throw KERNEL::createSalomeException(message.c_str());
437   }
438 }
439
440 /*!
441  * This function is responsible for creating the FieldHandler
442  * instances. You must use this function because it manages
443  * automatically the identifier value (autoincrementation of a static
444  * variable)
445  */
446 MEDOP::FieldHandler * MEDDataManager_i::newFieldHandler(const char * fieldname,
447                                                         const char * meshname,
448                                                         TypeOfField  type,
449                                                         long         iteration,
450                                                         long         order,
451                                                         const char * source)
452 {
453   MEDOP::FieldHandler * fieldHandler = new MEDOP::FieldHandler();
454   fieldHandler->id = _fieldLastId; _fieldLastId++;
455   fieldHandler->fieldname = fieldname;
456   fieldHandler->meshname  = meshname;
457   fieldHandler->type      = type;
458   fieldHandler->iteration = iteration;
459   fieldHandler->order     = order;
460   fieldHandler->source    = source;
461   return fieldHandler;
462 }
463
464 /*!
465  * This updates the metadata of the field identified by its id with
466  * the data of the given field handler. Returns a copy of the updated
467  * handler (that should be identical to the given field handler for
468  * all data but not for the id that is an invariant for all session
469  * long).
470  * WARN: you should be warned that this function could leave the data
471  * model in a non-coherent state, by example if you change the mesh
472  * name while the mesh has not been updated.
473  */
474 MEDOP::FieldHandler * MEDDataManager_i::updateFieldHandler(CORBA::Long fieldHandlerId,
475                                                            const char * fieldname,
476                                                            long         iteration,
477                                                            long         order,
478                                                            const char * source) {
479   FieldHandlerMapIterator fieldIt = _fieldHandlerMap.find(fieldHandlerId);
480   if ( fieldIt != _fieldHandlerMap.end() ) {
481     // Update the attributes
482     // >>> WARN: note that the id of a handler registered in the map
483     // SHOULD NEVER be modified because it is the identifier used in
484     // the whole application for this field all the session long.
485     // <<<
486     fieldIt->second->fieldname = fieldname;
487     fieldIt->second->iteration = iteration;
488     fieldIt->second->order     = order;
489     fieldIt->second->source    = source;
490     // Return a copy
491     return new MEDOP::FieldHandler(*fieldIt->second);
492   }
493   return NULL;
494 }
495
496 MEDCouplingUMesh * MEDDataManager_i::getUMesh(long meshHandlerId) {
497
498   LOG("getUMesh: START")
499
500   MEDCouplingUMesh * myMesh = NULL;
501   if ( _meshMap.count(meshHandlerId) > 0 ) {
502     // The mesh has been found in the map
503     myMesh = _meshMap[meshHandlerId];
504   } else {
505     // The mesh is not loaded yet ==> load it and register it in the map
506     LOG("getUMesh: the mesh must be loaded. meshid="<<meshHandlerId);    
507     if ( _meshHandlerMap[meshHandlerId] == NULL ) {
508       std::string message = 
509         std::string("No mesh for id=") + ToString(meshHandlerId);
510       LOG("getUMesh: "<<message);
511       throw KERNEL::createSalomeException(message.c_str());
512     }
513
514     long sourceid = _meshHandlerMap[meshHandlerId]->sourceid;
515     const char * filepath = source_to_file((_datasourceHandlerMap[sourceid])->uri);  
516     const char * meshName = _meshHandlerMap[meshHandlerId]->name;
517     int meshDimRelToMax = 0;
518     myMesh = MEDLoader::ReadUMeshFromFile(filepath,meshName,meshDimRelToMax);
519     _meshMap[meshHandlerId] = myMesh;
520   }
521   return myMesh;
522 }
523
524 /**
525  * Try to retrieve the id of the specified mesh, i.e. the key it is
526  * registered with in the internal meshes map.
527  */
528 long MEDDataManager_i::getUMeshId(const MEDCouplingMesh * mesh) {
529   bool found = false;
530   MeshMapIterator it = _meshMap.begin();  
531   while ( it != _meshMap.end() ) {
532     found = (it->second == mesh);
533     if (found) {
534       return it->first;
535     }
536     ++it;
537   }
538   return LONG_UNDEFINED;
539 }
540
541 /*!
542  * This method returns the physical data of the specified field,
543  * i.e. the MEDCoupling field associated to the specified field
544  * handler. If the field source is a file and the data ar not loaded
545  * yet, the this function load the data from the file in a MEDCoupling
546  * field instance. Otherwize, it just returns the MEDCoupling field
547  * instance.
548  */
549 MEDCouplingFieldDouble * MEDDataManager_i::getFieldDouble(const MEDOP::FieldHandler * fieldHandler)
550 {
551
552   LOG("getFieldDouble: START with id="<<fieldHandler->id);
553
554   if ( _fieldDoubleMap.count(fieldHandler->id) > 0 ) {
555   // The MEDCoupling field data are already loaded. Just return the
556   // reference of the MEDCouplingFieldDouble pointer
557     return _fieldDoubleMap[fieldHandler->id];
558   }
559
560   // The MEDCoupling field data are not loaded yet. Load the data and
561   // register the MEDCoupling field in our internal map an all the
562   // associated data if needed (i.e. the underlying mesh).
563
564   // At this step, the mesh handler needs a meshid correctly
565   // set. Normally, we should arrive at this step only in the case
566   // where the field is loaded from a file ==> the meshid is defined
567   // (see the addDatasource function).
568   //
569   // >>>> __GBO__ TO BE CHECKED AND SERIOUSLY TESTED. There at least
570   // one case where we can arrive here with no previous call to
571   // addDataSource: for example the field handler list can be obtained
572   // from a call to addFieldsFromFile instead of addDataSource (see
573   // for exemple the getFieldRepresentation service of the
574   // dataManager, that comes here and then calls getUMesh where we
575   // need a map initialized only in addDataSource) <<<<
576   long meshid = fieldHandler->meshid;
577
578   // We first have to check if the associated mesh is already loaded
579   // and to load it if needed. The loaded meshes are registered in a
580   // map whose key is the mesh handler id. This checking is
581   // automatically done by the function getUMesh. It's important to do
582   // it before the loading of field data to prevent from the case
583   // where the mesh would not have been loaded already (in the
584   // previous field loading).
585   MEDCouplingUMesh * myMesh =this->getUMesh(meshid);
586
587   long sourceid = _meshHandlerMap[meshid]->sourceid;
588
589   const char * filepath = source_to_file((_datasourceHandlerMap[sourceid])->uri);
590   const char * meshName = myMesh->getName();
591   LOG("getFieldDouble: field "<<fieldHandler->fieldname<<" loaded from file "<<filepath);
592   TypeOfField type = (TypeOfField)fieldHandler->type;
593   int meshDimRelToMax = 0;
594   MEDCouplingFieldDouble * myField = MEDLoader::ReadField(type,
595                                                           filepath,
596                                                           meshName,
597                                                           meshDimRelToMax,
598                                                           fieldHandler->fieldname,
599                                                           fieldHandler->iteration,
600                                                           fieldHandler->order);
601   myField->setMesh(myMesh);
602   _fieldDoubleMap[fieldHandler->id] = myField;
603   return myField;
604 }
605
606 /*!
607  * This adds the specified MEDCoupling field in the collection managed
608  * by this DataManager. The associated FieldHandler is returned. This
609  * is typically used in a context where the MEDCoupling field is
610  * created from scratch, for example by operations in the
611  * MEDCalculator.
612  * @param[in] fieldDouble   the MEDCouplingFieldDouble instance to add
613  * @param[in] meshHandlerId the id of the meshHandler this filed is associated to.
614  * @return a copy of the FieldHandler registered in the internal map for this field.
615  */
616 MEDOP::FieldHandler * MEDDataManager_i::addField(MEDCouplingFieldDouble * fieldDouble,
617                                                  long meshHandlerId)
618 {
619   const char * fieldName = fieldDouble->getName();
620   const char * meshName  = fieldDouble->getMesh()->getName();
621   TypeOfField  type      = fieldDouble->getTypeOfField();
622
623   int iteration, order;
624   // WARN: note that the variables "iteration" and "order" are passed
625   // by reference to the function getTime (see documentation of
626   // MEDCouplingField). As a consequence, the values of these
627   // variables are updated by this function call. This is the mean to
628   // retrieve the iteration and order of the field.
629   double timestamp = fieldDouble->getTime(iteration, order);
630   
631   // For the fields that are created in memory (by operations for
632   // example), the convention for the source attribute is to specify
633   // the fielddouble name, because this name describes the operation
634   // the field has been created with.
635   string * source = new string("mem://"); source->append(fieldName);
636   MEDOP::FieldHandler * fieldHandler = newFieldHandler(fieldName,
637                                                        meshName,
638                                                        type,
639                                                        iteration,
640                                                        order,
641                                                        source->c_str());
642
643   if ( meshHandlerId == LONG_UNDEFINED ) {
644     // We have to gess the id of the underlying mesh to preserve data
645     // integrity (a fieldHandler must have an attribute that contains
646     // the id of its underlying mesh):
647     //
648     // WARNING: it's better to let the client code (the one who calls the
649     // function addField) to specify this meshid. This guess procedure is
650     // not reliable, it's just to have a second chance.
651     //
652     LOG("addField: The mesh id is not defined. Trying to guess from the mesh name "<<meshName);
653     long meshid = this->getUMeshId(fieldDouble->getMesh());
654     fieldHandler->meshid = meshid;
655     if ( meshid == LONG_UNDEFINED ) {
656       // No mesh has been found in the internal map
657       LOG("addField: The mesh id for the mesh "<<meshName<<" can't be retrieved from the field "<<fieldName);
658       // _GBO_ : Maybe it could be better to raise an exception
659     }
660   }
661   else {
662     fieldHandler->meshid = meshHandlerId;
663   }
664   
665   _fieldHandlerMap[fieldHandler->id] = fieldHandler;
666   _fieldDoubleMap[fieldHandler->id] = fieldDouble;
667   // >>> WARNING: CORBA structure assignement specification ==> return
668   // >>> a deep copy to avoid the destruction of the fieldHandler
669   // >>> registered in the map (assignement acts as a destructor for
670   // >>> CORBA struct).   
671   return new MEDOP::FieldHandler(*fieldHandler);
672 }
673
674 /*!
675  * This function updates the meta-data "fieldname" associated to the
676  * specified field.
677  */
678 void MEDDataManager_i::updateFieldMetadata(CORBA::Long  fieldHandlerId,
679                                            const char * fieldname,
680                                            CORBA::Long  iteration,
681                                            CORBA::Long  order,
682                                            const char * source)
683 {
684   // We have to update the field handler registered in the internal
685   // map AND the associated fieldDouble loaded in memory.
686   MEDOP::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId);
687   updateFieldHandler(fieldHandlerId,fieldname,iteration,order,source);
688                      
689   MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler);
690   fieldDouble->setName(fieldname);
691
692   // _GBO_ TO BE IMPLEMENTED: iteration and order
693 }
694
695 /**
696  * This can be used to associate to the specified field another mesh
697  * support than its current one. This is typically needed to operate 2
698  * fields defined on the same mesh but coming from different med
699  * files. In this case, the underlying meshes are different mesh
700  * objects (from the MEDCoupling point of view) and then no operation
701  * can be allowed by MEDCoupling. The operation of course fails if the
702  * new mesh is not identical to the old one.
703  */
704 void MEDDataManager_i::changeUnderlyingMesh(CORBA::Long fieldHandlerId, CORBA::Long meshHandlerId) {
705   
706   MEDOP::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId);
707   MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler);
708   MEDCouplingMesh * newMesh = getUMesh(meshHandlerId);
709
710   try {
711     fieldDouble->changeUnderlyingMesh(newMesh,10,1e-12);
712   }
713   catch (INTERP_KERNEL::Exception &ex) {
714     std::string * message = new std::string("Error when changing the underlying mesh : ");
715     message->append(ex.what());
716     throw KERNEL::createSalomeException(message->c_str());
717   }
718
719   // The change of mesh is OK, then we can update the meta-data
720   _fieldHandlerMap[fieldHandlerId]->meshid = meshHandlerId;
721   _fieldHandlerMap[fieldHandlerId]->meshname = _meshHandlerMap[meshHandlerId]->name;
722
723
724   // WARN: if this field has already been request by the tui for
725   // manipulation (in a fieldproxy), then the data should be
726   // synchronized
727 }
728
729
730
731 /*!
732  * This functions display the internal data of the MEDDataManager on
733  * the server side (data in the SALOME container).
734  */
735 void MEDDataManager_i::serverlog() {
736   
737   LOG("==== Field Handler Map ====================================================");
738   LOG("Size = "<<_fieldHandlerMap.size());
739   FieldHandlerMapIterator fhmIt;
740   for ( fhmIt = _fieldHandlerMap.begin(); fhmIt != _fieldHandlerMap.end(); fhmIt++) {
741     long id = fhmIt->first;
742     LOG("------------------------------------- id = "<<ToString(id));
743     LOG("- id        \t= "<<fhmIt->second->id);
744     LOG("- fieldname \t= "<<fhmIt->second->fieldname);
745     LOG("- meshname  \t= "<<fhmIt->second->meshname);
746   }
747
748   LOG("==== Field Double Map ====================================================");
749   LOG("Size = "<<_fieldDoubleMap.size());
750   FieldDoubleMapIterator fdmIt;
751   for ( fdmIt = _fieldDoubleMap.begin(); fdmIt != _fieldDoubleMap.end(); fdmIt++) {
752     long id = (*fdmIt).first;
753     MEDCouplingFieldDouble * fieldDouble = (*fdmIt).second;
754     LOG("------------------------------------- id = "<<ToString(id));
755     LOG("- fieldname \t= "<<fieldDouble->getName());
756     LOG("- meshname  \t= "<<fieldDouble->getMesh()->getName());
757   }
758 }
759
760 /*!
761  * The event listener is created inside the GUI by the
762  * WorkspaceController. This function is called by the WorkspaceController to
763  * store the event listener IOR for the time of the session. Then this
764  * IOR can be available to any point of the application that can
765  * request the data manager (the python console for example).
766  */
767 void MEDDataManager_i::setEventListenerIOR(const char * ior) {
768   if ( _medEventListenerIOR != NULL ) {
769     free(_medEventListenerIOR);
770   }
771   _medEventListenerIOR = (char *)malloc(sizeof(char)*strlen(ior));
772   strcpy(_medEventListenerIOR, ior);
773 }
774 /*!
775  * Return the IOR of the event listener that resides in the
776  * GUI. Having the IOR, you can restore the CORBA object by using:
777  *
778  * In a python SALOME context:
779  *
780  * >>> import salome
781  * >>> salome.salome_init()
782  * >>> myobject = salome.orb.string_to_object(ior)
783  *
784  * In a C++ SALOME context: (to do if needed)
785  */
786 char * MEDDataManager_i::getEventListenerIOR() {
787   if ( _medEventListenerIOR == NULL ) {
788     throw KERNEL::createSalomeException("The event listener IOR is not defined");
789   }
790   // WARN: return a copy because the pointer memory will be released
791   // (CORBA specification)
792   char * ior = (char *)malloc(sizeof(char)*strlen(_medEventListenerIOR));
793   strcpy(ior, _medEventListenerIOR);
794   return ior;
795 }