]> SALOME platform Git repositories - modules/kernel.git/blob - src/SALOMEDSImpl/SALOMEDSImpl_StudyManager.cxx
Salome HOME
50099bcc9cc29bbb1486110446a1b38276be158b
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_StudyManager.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 //  File   : SALOMEDSImpl_StudyManager.cxx
21 //  Author : Sergey RUIN
22 //  Module : SALOME
23
24 #include "SALOMEDSImpl_StudyManager.hxx"
25
26 #include "DF_ChildIterator.hxx"
27 #include "HDFexplorer.hxx"
28
29 #include "SALOMEDSImpl_Attributes.hxx"
30 #include "SALOMEDSImpl_Tool.hxx"
31 #include "SALOMEDSImpl_SComponent.hxx"
32 #include "SALOMEDSImpl_GenericAttribute.hxx"
33 #include <map>
34
35 #include "HDFOI.hxx"
36 #include <iostream>
37 #include <stdlib.h>
38
39 using namespace std;
40
41 #define USE_CASE_LABEL_ID                       "0:2"
42
43 static void SaveAttributes(const SALOMEDSImpl_SObject& SO, HDFgroup *hdf_group_sobject);
44 static void ReadAttributes(SALOMEDSImpl_Study*, const SALOMEDSImpl_SObject&, HDFdataset* );
45 static void BuildTree (SALOMEDSImpl_Study*, HDFgroup*);
46 static void Translate_IOR_to_persistentID (const SALOMEDSImpl_SObject&,
47                                            SALOMEDSImpl_Driver*, bool isMultiFile, bool isASCII);
48
49 //============================================================================
50 /*! Function : SALOMEDSImpl_StudyManager
51  *  Purpose  : SALOMEDSImpl_StudyManager constructor
52  */
53 //============================================================================
54 SALOMEDSImpl_StudyManager::SALOMEDSImpl_StudyManager()
55 {
56   _errorCode = "";
57   _appli = new DF_Application();
58   _IDcounter = 0;
59   _clipboard = _appli->NewDocument("SALOME_STUDY");
60 }
61
62 //============================================================================
63 /*! Function : ~SALOMEDSImpl_StudyManager
64  *  Purpose  : SALOMEDSImpl_StudyManager destructor
65  */
66 //============================================================================
67 SALOMEDSImpl_StudyManager::~SALOMEDSImpl_StudyManager()
68 {
69   // Destroy application
70   delete _appli;    
71 }
72
73
74 //============================================================================
75 /*! Function : NewStudy
76  *  Purpose  : Create a New Study of name study_name
77  */
78 //==================================================T==========================
79 SALOMEDSImpl_Study* SALOMEDSImpl_StudyManager::NewStudy(const string& study_name)
80 {
81   _errorCode = "";
82
83   DF_Document* Doc = _appli->NewDocument("SALOME_STUDY");
84
85   SALOMEDSImpl_Study* Study = new SALOMEDSImpl_Study(Doc, study_name);
86
87   _IDcounter++;
88   Study->StudyId( _IDcounter );
89
90   // set Study properties
91   SALOMEDSImpl_AttributeStudyProperties* aProp = Study->GetProperties();
92   
93   int month=0,day=0,year=0,hh=0,mn=0,ss=0;
94   SALOMEDSImpl_Tool::GetSystemDate(year, month, day, hh, mn, ss);
95   aProp->SetModification(SALOMEDSImpl_Tool::GetUserName(),
96                          mn, hh, day, month, year);
97   aProp->SetCreationMode(1);  //"from scratch"
98
99   return Study;
100 }
101
102 //============================================================================
103 /*! Function : Open
104  *  Purpose  : Open a Study from it's persistent reference
105  */
106 //============================================================================
107 SALOMEDSImpl_Study* SALOMEDSImpl_StudyManager::Open(const string& aUrl)
108 {
109   _errorCode = "";
110
111   // open the HDFFile
112   HDFfile *hdf_file =0;
113   HDFgroup *hdf_group_study_structure =0;
114
115   char* aC_HDFUrl;
116   string aHDFUrl;
117   bool isASCII = false;
118   if (HDFascii::isASCII(aUrl.c_str())) {
119     isASCII = true;
120     char* aResultPath = HDFascii::ConvertFromASCIIToHDF(aUrl.c_str());
121     aC_HDFUrl = new char[strlen(aResultPath) + 19];
122     sprintf(aC_HDFUrl, "%shdf_from_ascii.hdf", aResultPath);
123     delete(aResultPath);
124     aHDFUrl = aC_HDFUrl;
125     delete aC_HDFUrl;
126   } else {
127     aHDFUrl = aUrl;
128   }
129
130   
131   hdf_file = new HDFfile((char*)aHDFUrl.c_str());
132   try {
133     hdf_file->OpenOnDisk(HDF_RDONLY);// mpv: was RDWR, but opened file can be write-protected too
134   }
135   catch (HDFexception)
136     {
137         char *eStr;
138         eStr = new char[strlen(aUrl.c_str())+17];
139         sprintf(eStr,"Can't open file %s",aUrl.c_str());
140          delete [] eStr;
141         _errorCode = string(eStr);
142         return NULL;
143     }
144
145   // Temporary aStudyUrl in place of study name
146   DF_Document* Doc = _appli->NewDocument("SALOME_STUDY");
147
148   SALOMEDSImpl_Study* Study = new SALOMEDSImpl_Study(Doc, aUrl);
149
150   _IDcounter++;
151   Study->StudyId( _IDcounter );
152
153   // Assign the value of the URL in the study object
154   Study->URL (aUrl);
155
156   SALOMEDSImpl_AttributePersistentRef::Set(Doc->Main(), aUrl);
157
158   if (!hdf_file->ExistInternalObject("STUDY_STRUCTURE")) {
159      _errorCode = "Study is empty";
160     return Study;
161   }
162
163   //Create  the Structure of the Document
164   hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
165
166   try {
167     BuildTree (Study, hdf_group_study_structure);
168   }
169   catch (HDFexception)
170     {
171       char *eStr = new char [strlen(aUrl.c_str())+17];
172       sprintf(eStr,"Can't open file %s", aUrl.c_str());
173       _errorCode = string(eStr);
174       return NULL;
175     }
176
177   hdf_file->CloseOnDisk();
178
179   if (isASCII) {
180     vector<string> aFilesToRemove;
181     aFilesToRemove.push_back("hdf_from_ascii.hdf");
182     SALOMEDSImpl_Tool::RemoveTemporaryFiles(SALOMEDSImpl_Tool::GetDirFromPath(aHDFUrl), aFilesToRemove, true);
183   }
184
185   delete hdf_file; // all related hdf objects will be deleted
186
187   return Study;
188 }
189
190
191
192 //============================================================================
193 /*! Function : Close
194  *  Purpose  : Close a study.
195  *             If the study hasn't been saved, ask the user to confirm the
196  *             close action without saving
197  */
198
199 //============================================================================
200 void  SALOMEDSImpl_StudyManager::Close(SALOMEDSImpl_Study* aStudy)
201 {
202   _errorCode = "";
203
204   if(!aStudy) {
205     _errorCode = "Study is null";
206     return;
207   }
208
209   aStudy->Close();
210 }
211
212 //============================================================================
213 /*! Function : Save
214  *  Purpose  : Save a Study to it's persistent reference
215  */
216 //============================================================================
217 bool SALOMEDSImpl_StudyManager::Save(SALOMEDSImpl_Study* aStudy,
218                                      SALOMEDSImpl_DriverFactory* aFactory,
219                                      bool theMultiFile)
220 {
221   _errorCode = "";
222
223   string url = aStudy->URL();
224   if (url.empty()) {
225     _errorCode = "No path specified to save the study. Nothing done";
226     return false;
227   }
228   else {
229     return Impl_SaveAs(url,aStudy, aFactory, theMultiFile, false);
230   }
231
232   return false;
233 }
234
235 bool SALOMEDSImpl_StudyManager::SaveASCII(SALOMEDSImpl_Study* aStudy,
236                                           SALOMEDSImpl_DriverFactory* aFactory,
237                                           bool theMultiFile)
238 {
239   _errorCode = "";
240
241   string url = aStudy->URL();
242   if (url.empty()) {
243     _errorCode = "No path specified to save the study. Nothing done";
244     return false;
245   }
246   else {
247     return Impl_SaveAs(url,aStudy, aFactory, theMultiFile, true);
248   }
249
250   return false;
251 }
252
253 //=============================================================================
254 /*! Function : SaveAs
255  *  Purpose  : Save a study to the persistent reference aUrl
256  */
257 //============================================================================
258 bool SALOMEDSImpl_StudyManager::SaveAs(const string& aUrl,
259                                        SALOMEDSImpl_Study* aStudy,
260                                        SALOMEDSImpl_DriverFactory* aFactory,
261                                        bool theMultiFile)
262 {
263   _errorCode = "";
264   return Impl_SaveAs(aUrl,aStudy, aFactory, theMultiFile, false);
265 }
266
267 bool SALOMEDSImpl_StudyManager::SaveAsASCII(const string& aUrl,
268                                             SALOMEDSImpl_Study* aStudy,
269                                             SALOMEDSImpl_DriverFactory* aFactory,
270                                             bool theMultiFile)
271 {
272   _errorCode = "";
273   return Impl_SaveAs(aUrl,aStudy, aFactory, theMultiFile, true);
274 }
275
276 //============================================================================
277 /*! Function : GetOpenStudies
278  *  Purpose  : Get name list of open studies in the session
279  */
280 //============================================================================
281 vector<SALOMEDSImpl_Study*> SALOMEDSImpl_StudyManager::GetOpenStudies()
282 {
283   _errorCode = "";
284   vector<SALOMEDSImpl_Study*> aList;
285
286   int nbDocs = _appli->NbDocuments();
287
288   if(nbDocs == 0) {
289     _errorCode = "No active study in this session";
290     return aList;
291   }
292   else {
293     SALOMEDSImpl_Study* aStudy;
294     vector<int> ids = _appli->GetDocumentIDs();
295     for (int i = 0, len = ids.size(); i<len; i++) {
296       DF_Document* D = _appli->GetDocument(ids[i]);
297       if(D == _clipboard) continue;
298       aStudy = SALOMEDSImpl_Study::GetStudy(D->Main());
299       if(!aStudy) continue;
300       aList.push_back(aStudy);
301     }
302   }
303
304   return aList;
305 }
306
307 //============================================================================
308 /*! Function : GetStudyByName
309  *  Purpose  : Get a study from its name
310  */
311 //============================================================================
312 SALOMEDSImpl_Study* SALOMEDSImpl_StudyManager::GetStudyByName
313                                    (const string& aStudyName)
314 {
315   _errorCode = "";
316   int nbDocs = _appli->NbDocuments();
317
318   if (nbDocs == 0) {
319     _errorCode = "No active study in this session";
320     return NULL;
321   }
322   else {
323     vector<SALOMEDSImpl_Study*> studies = GetOpenStudies();
324     for (int i = 0, len = studies.size(); i<len; i++) {
325       if (studies[i]->Name() == aStudyName) return studies[i];
326     }
327   }
328
329   _errorCode = string("Found no study with the name ") + aStudyName;
330   return NULL;
331 }
332
333 //============================================================================
334 /*! Function : GetStudyByID
335  *  Purpose  : Get a study from its ID
336  */
337 //============================================================================
338 SALOMEDSImpl_Study* SALOMEDSImpl_StudyManager::GetStudyByID(int aStudyID)
339 {
340   _errorCode = "";
341   int nbDocs = _appli->NbDocuments();
342
343   if (nbDocs == 0) {
344     _errorCode = "No active study in this session";
345     return NULL;
346   }
347   else {
348     vector<SALOMEDSImpl_Study*> studies = GetOpenStudies();
349     for (int i = 0, len = studies.size(); i<len; i++) {
350       if (studies[i]->StudyId() == aStudyID) return studies[i];
351     }
352   }
353
354   _errorCode = "Found no study with the given ID";
355   return NULL;
356 }
357
358 //=============================================================================
359 /*! Function : _SaveProperties
360  *  Purpose  : save the study properties in HDF file
361  */
362 //============================================================================
363 bool SALOMEDSImpl_StudyManager::Impl_SaveProperties(SALOMEDSImpl_Study* aStudy,
364                                                     HDFgroup *hdf_group)
365 {
366   _errorCode = "";
367
368   HDFdataset *hdf_dataset = 0;
369   hdf_size size[1];
370   hdf_int32 name_len;
371
372   // add modifications list (user and date of save)
373   SALOMEDSImpl_AttributeStudyProperties* aProp = aStudy->GetProperties();
374   int aLocked = aProp->IsLocked();
375   if (aLocked) aProp->SetLocked(false);
376
377   int month=0,day=0,year=0,hh=0,mn=0,ss=0;
378   SALOMEDSImpl_Tool::GetSystemDate(year, month, day, hh, mn, ss);
379   aProp->SetModification(SALOMEDSImpl_Tool::GetUserName(),
380                          mn, hh, day, month, year);
381
382   if (aLocked) aProp->SetLocked(true);
383
384   vector<string> aNames;
385   vector<int> aMinutes, aHours, aDays, aMonths, aYears;
386
387   aProp->GetModifications(aNames, aMinutes, aHours, aDays, aMonths, aYears);
388
389   int aLength = 0, anIndex, i;
390   for(i=1; i<=aNames.size(); i++)
391     aLength += aNames[i-1].size() + 1;
392
393   //string length: 1 byte = locked flag, 1 byte = modified flag, (12 + name length + 1) for each name and date, "zero" byte
394   char* aProperty = new char[3 + aLength + 12 * aNames.size()];
395
396
397   sprintf(aProperty,"%c%c", (char)aProp->GetCreationMode(),  (aProp->IsLocked())?'l':'u');
398
399   aLength = aNames.size();
400   int a = 2;
401   for(anIndex = 0; anIndex<aLength; anIndex++) {
402     sprintf(&(aProperty[a]),"%2d%2d%2d%2d%4d%s",
403             (int)(aMinutes[anIndex]),
404             (int)(aHours[anIndex]),
405             (int)(aDays[anIndex]),
406             (int)(aMonths[anIndex]),
407             (int)(aYears[anIndex]),
408             aNames[anIndex].c_str());
409     a = strlen(aProperty);
410     aProperty[a++] = 1;
411   }
412   aProperty[a] = 0;
413
414   name_len = (hdf_int32) a;
415   size[0] = name_len + 1 ;
416   hdf_dataset = new HDFdataset("AttributeStudyProperties",hdf_group,HDF_STRING,size,1);
417   hdf_dataset->CreateOnDisk();
418   hdf_dataset->WriteOnDisk(aProperty);
419   hdf_dataset->CloseOnDisk();
420   hdf_dataset=0; //will be deleted by hdf_sco_group destructor
421   delete [] aProperty;
422
423   aProp->SetModified(0);
424   return true;
425 }
426
427 //=============================================================================
428 /*! Function : _SaveAs
429  *  Purpose  : save the study in HDF file
430  */
431 //============================================================================
432 bool SALOMEDSImpl_StudyManager::Impl_SaveAs(const string& aUrl,
433                                             SALOMEDSImpl_Study* aStudy,
434                                             SALOMEDSImpl_DriverFactory* aFactory,
435                                             bool theMultiFile,
436                                             bool theASCII)
437 {
438   // HDF File will be composed of differents part :
439   // * For each ComponentDataType, all data created by the component
440   //   Informations in data group hdf_group_datacomponent
441   // * Study Structure -> Exactly what is contained in Document
442   //   Informations in data group hdf_group_study_structure
443
444   _errorCode = "";
445
446   HDFfile *hdf_file=0;
447   HDFgroup *hdf_group_study_structure =0;
448   HDFgroup *hdf_sco_group =0;
449   HDFgroup *hdf_sco_group2 =0;
450
451   HDFgroup *hdf_group_datacomponent =0;
452   HDFdataset *hdf_dataset =0;
453   hdf_size size[1];
454   hdf_int32 name_len = 0;
455   string component_name;
456
457   if(!aStudy) {
458     _errorCode = "Study is null";
459     return false;
460   }
461
462   int aLocked = aStudy->GetProperties()->IsLocked();
463   if (aLocked) aStudy->GetProperties()->SetLocked(false);
464
465   SALOMEDSImpl_StudyBuilder* SB= aStudy->NewBuilder();
466   map<string, SALOMEDSImpl_Driver*> aMapTypeDriver;
467
468   try
469     {
470       // mpv 15.12.2003: for saving components we have to load all data from all modules
471       SALOMEDSImpl_SComponentIterator itcomponent1 = aStudy->NewComponentIterator();
472       for (; itcomponent1.More(); itcomponent1.Next())
473         {
474           SALOMEDSImpl_SComponent sco = itcomponent1.Value();
475           // if there is an associated Engine call its method for saving
476           string IOREngine;
477           try {
478             if (!sco.ComponentIOR(IOREngine)) {
479               string aCompType = sco.GetComment();
480               if (!aCompType.empty()) {
481
482                 SALOMEDSImpl_Driver* aDriver = aFactory->GetDriverByType(aCompType);
483                 aMapTypeDriver[aCompType] = aDriver;
484
485                 if (aDriver != NULL) {
486                   if(!SB->LoadWith(sco, aDriver)) {
487                     _errorCode = SB->GetErrorCode();
488                     return false;
489                   }
490                 }
491               }
492             }
493           } catch(...) {
494             _errorCode = "Can not restore information to resave it";
495             return false;
496           }
497         }
498
499       string anOldName = aStudy->Name();
500       aStudy->URL(aUrl);
501
502       // To change for Save
503       // Do not have to do a new file but just a Open??? Rewrite all informations after erasing evrything??
504       hdf_file = new HDFfile((char*)aUrl.c_str());
505       hdf_file->CreateOnDisk();
506
507       //-----------------------------------------------------------------------
508       // 1 - Create a groupe for each SComponent and Update the PersistanceRef
509       //-----------------------------------------------------------------------
510       hdf_group_datacomponent = new HDFgroup("DATACOMPONENT",hdf_file);
511       hdf_group_datacomponent->CreateOnDisk();
512
513       SALOMEDSImpl_SComponentIterator itcomponent = aStudy->NewComponentIterator();
514
515       for (; itcomponent.More(); itcomponent.Next())
516         {
517           SALOMEDSImpl_SComponent sco = itcomponent.Value();
518
519           string scoid = sco.GetID();
520           hdf_sco_group = new HDFgroup((char*)scoid.c_str(), hdf_group_datacomponent);
521           hdf_sco_group->CreateOnDisk();
522
523           string componentDataType = sco.ComponentDataType();
524           string IOREngine;
525           if (sco.ComponentIOR(IOREngine))
526             {
527               SALOMEDSImpl_Driver* Engine = NULL;
528               if(aMapTypeDriver.find(componentDataType) != aMapTypeDriver.end()) {
529                 // we have found the associated engine to write the data
530                 Engine = aMapTypeDriver[componentDataType];
531               }
532               else {
533                 Engine = aFactory->GetDriverByIOR(IOREngine);
534               }
535
536               if (Engine != NULL)
537                 {
538                   SALOMEDSImpl_TMPFile* aStream = NULL;
539                   long length = 0;
540
541                   if (theASCII) aStream = Engine->SaveASCII(sco,
542                                                             SALOMEDSImpl_Tool::GetDirFromPath(aUrl),
543                                                             length,
544                                                             theMultiFile);
545                   else aStream = Engine->Save(sco,
546                                               SALOMEDSImpl_Tool::GetDirFromPath(aUrl),
547                                               length,
548                                               theMultiFile);
549                   HDFdataset *hdf_dataset;
550                   hdf_size aHDFSize[1]; 
551                   if(length > 0) {  //The component saved some auxiliary files, then put them into HDF file
552
553                     aHDFSize[0] = length;
554
555                     HDFdataset *hdf_dataset = new HDFdataset("FILE_STREAM", hdf_sco_group, HDF_STRING, aHDFSize, 1);
556                     hdf_dataset->CreateOnDisk();
557                     hdf_dataset->WriteOnDisk(aStream->Data());  //Save the stream in the HDF file
558                     hdf_dataset->CloseOnDisk();
559                   }
560
561                   if(aStream) delete aStream;
562
563                   // store multifile state
564                   aHDFSize[0] = 2;
565                   hdf_dataset = new HDFdataset("MULTIFILE_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
566                   hdf_dataset->CreateOnDisk();
567                   hdf_dataset->WriteOnDisk((void*)(theMultiFile?"M":"S")); // save: multi or single
568                   hdf_dataset->CloseOnDisk();
569                   hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor
570                   // store ASCII state
571                   aHDFSize[0] = 2;
572                   hdf_dataset = new HDFdataset("ASCII_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
573                   hdf_dataset->CreateOnDisk();
574                   hdf_dataset->WriteOnDisk((void*)(theASCII?"A":"B")); // save: ASCII or BINARY
575                   hdf_dataset->CloseOnDisk();
576                   hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor
577                   // Creation of the persistance reference  attribute
578                   Translate_IOR_to_persistentID (sco, Engine, theMultiFile, theASCII);
579                 }
580             }
581           hdf_sco_group->CloseOnDisk();
582           hdf_sco_group=0; // will be deleted by hdf_group_datacomponent destructor
583         }
584       hdf_group_datacomponent->CloseOnDisk();
585       hdf_group_datacomponent =0;  // will be deleted by hdf_file destructor
586
587       //-----------------------------------------------------------------------
588       //3 - Write the Study Structure
589       //-----------------------------------------------------------------------
590       hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
591       hdf_group_study_structure->CreateOnDisk();
592       // save component attributes
593       SALOMEDSImpl_SComponentIterator itcomp = aStudy->NewComponentIterator();
594       for (; itcomp.More(); itcomp.Next())
595         {
596           SALOMEDSImpl_SComponent SC = itcomp.Value();
597           string scid = SC.GetID();
598           hdf_sco_group2 = new HDFgroup((char*)scid.c_str(), hdf_group_study_structure);
599           hdf_sco_group2->CreateOnDisk();
600           SaveAttributes(SC, hdf_sco_group2);
601           // ComponentDataType treatment
602           component_name = SC.ComponentDataType();
603           name_len = (hdf_int32)component_name.length();
604           size[0] = name_len +1 ;
605           hdf_dataset = new HDFdataset("COMPONENTDATATYPE",hdf_sco_group2,HDF_STRING,size,1);
606           hdf_dataset->CreateOnDisk();
607           hdf_dataset->WriteOnDisk((char*)component_name.c_str());
608           hdf_dataset->CloseOnDisk();
609           hdf_dataset=0; //will be deleted by hdf_sco_group destructor
610           Impl_SaveObject(SC, hdf_sco_group2);
611           hdf_sco_group2->CloseOnDisk();
612           hdf_sco_group2=0; // will be deleted by hdf_group_study_structure destructor
613         }
614       //-----------------------------------------------------------------------
615       //4 - Write the Study UseCases Structure
616       //-----------------------------------------------------------------------
617       SALOMEDSImpl_SObject aSO = aStudy->FindObjectID(USE_CASE_LABEL_ID);
618       if (aSO) {
619         HDFgroup *hdf_soo_group = new HDFgroup(USE_CASE_LABEL_ID,hdf_group_study_structure);
620         hdf_soo_group->CreateOnDisk();
621         SaveAttributes(aSO, hdf_soo_group);
622         Impl_SaveObject(aSO, hdf_soo_group);
623         hdf_soo_group->CloseOnDisk();
624         hdf_soo_group=0; // will be deleted by hdf_group_study_structure destructor
625       }
626
627       if (aLocked) aStudy->GetProperties()->SetLocked(true);
628       //-----------------------------------------------------------------------
629       //5 - Write the Study Properties
630       //-----------------------------------------------------------------------
631       string study_name = aStudy->Name();
632       name_len = (hdf_int32) study_name.size();
633       size[0] = name_len +1 ;
634       hdf_dataset = new HDFdataset("STUDY_NAME",hdf_group_study_structure,HDF_STRING,size,1);
635       hdf_dataset->CreateOnDisk();
636       hdf_dataset->WriteOnDisk((char*)study_name.c_str());
637       hdf_dataset->CloseOnDisk();
638       hdf_dataset=0; // will be deleted by hdf_group_study_structure destructor
639
640       Impl_SaveProperties(aStudy, hdf_group_study_structure);
641       hdf_group_study_structure->CloseOnDisk();
642       hdf_file->CloseOnDisk();
643
644       aStudy->IsSaved(true);
645       hdf_group_study_structure =0; // will be deleted by hdf_file destructor
646       delete hdf_file; // recursively deletes all hdf objects...
647     }
648   catch (HDFexception)
649     {
650       _errorCode = "HDFexception ! ";
651       return false;
652     }
653   catch(std::exception& exc)
654     {
655       _errorCode = const_cast<char*>(exc.what());
656       return false;
657     }
658   catch(...)
659     {
660       _errorCode = "Unknown exception ! ";
661       return false;
662     }
663   if (theASCII) { // save file in ASCII format
664     HDFascii::ConvertFromHDFToASCII(aUrl.c_str(), true);
665   }
666
667   return true;
668 }
669
670 //============================================================================
671 /*! Function : Impl_SaveObject
672  *  Purpose  :
673  */
674 //============================================================================
675 bool SALOMEDSImpl_StudyManager::Impl_SaveObject(const SALOMEDSImpl_SObject& SC,
676                                                 HDFgroup *hdf_group_datatype)
677 {
678   _errorCode = "";
679
680   // Write in group hdf_group_datatype all informations of SObject SC
681   // Iterative function to parse all SObjects under a SComponent
682
683   HDFgroup *hdf_group_sobject = 0;
684
685   DF_ChildIterator itchild(SC.GetLabel());
686   for (; itchild.More(); itchild.Next())
687     {
688
689       // mpv: don't save empty labels
690       vector<DF_Attribute*> attr = itchild.Value().GetAttributes();
691       if (attr.size() == 0) {  //No attributes on the label
692         DF_ChildIterator subchild(itchild.Value());
693         if (!subchild.More()) {
694           continue;
695         }
696         subchild.Init(itchild.Value(), true);
697         bool anEmpty = true;
698         for (; subchild.More() && anEmpty; subchild.Next()) {
699           vector<DF_Attribute*> attr2 = subchild.Value().GetAttributes();
700           if (attr2.size()) {
701             anEmpty = false;  //There are attributes on the child label
702             break;
703           }
704         }
705         if (anEmpty) continue;
706       }
707
708       SALOMEDSImpl_SObject SO = SALOMEDSImpl_Study::SObject(itchild.Value());
709
710       string scoid = SO.GetID();
711       hdf_group_sobject = new HDFgroup(scoid.c_str(), hdf_group_datatype);
712       hdf_group_sobject->CreateOnDisk();
713       SaveAttributes(SO, hdf_group_sobject);
714       Impl_SaveObject(SO, hdf_group_sobject);
715       hdf_group_sobject->CloseOnDisk();
716       hdf_group_sobject =0; // will be deleted by father hdf object destructor
717     }
718
719   return true;
720 }
721
722 //============================================================================
723 /*! Function : Impl_SubstituteSlash
724  *  Purpose  :
725  */
726 //============================================================================
727 string SALOMEDSImpl_StudyManager::Impl_SubstituteSlash(const string& aUrl)
728 {
729   _errorCode = "";
730
731   std::string theUrl(aUrl);
732   for(int i = 0; i<theUrl.size(); i++)
733     if(theUrl[i] == '/') theUrl[i] = ':';
734   return theUrl;
735 }
736
737 //============================================================================
738 /*! Function : GetDocumentOfStudy
739  *  Purpose  :
740  */
741 //============================================================================
742 DF_Document* SALOMEDSImpl_StudyManager::GetDocumentOfStudy(SALOMEDSImpl_Study* theStudy)
743 {
744   _errorCode = "";
745   return theStudy->_doc;
746 }
747
748 //============================================================================
749 /*! Function : CanCopy
750  *  Purpose  :
751  */
752 //============================================================================
753 bool SALOMEDSImpl_StudyManager::CanCopy(const SALOMEDSImpl_SObject& theObject,
754                                         SALOMEDSImpl_Driver* theEngine)
755 {
756   _errorCode = "";
757   SALOMEDSImpl_SComponent aComponent = theObject.GetFatherComponent();
758   if (!aComponent) return false;
759   if (aComponent.GetLabel() == theObject.GetLabel()) return false;
760   string IOREngine;
761   if (!aComponent.ComponentIOR(IOREngine)) return false;
762   if (theEngine == NULL) return false;
763   return theEngine->CanCopy(theObject);
764 }
765
766 //============================================================================
767 /*! Function : CopyLabel
768  *  Purpose  :
769  */
770 //============================================================================
771 bool SALOMEDSImpl_StudyManager::CopyLabel(SALOMEDSImpl_Study* theSourceStudy,
772                                           SALOMEDSImpl_Driver* theEngine,
773                                           const int theSourceStartDepth,
774                                           const DF_Label& theSource,
775                                           const DF_Label& theDestinationMain)
776 {
777   _errorCode = "";
778
779   int a;
780   DF_Label aTargetLabel = theDestinationMain;
781   DF_Label aAuxTargetLabel = theDestinationMain.Father().FindChild(2);
782   for(a = theSource.Depth() - theSourceStartDepth; a > 0 ; a--) {
783     DF_Label aSourceLabel = theSource;
784     for(int aNbFather = 1; aNbFather < a; aNbFather++) aSourceLabel = aSourceLabel.Father();
785     aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
786     aAuxTargetLabel = aAuxTargetLabel.FindChild(aSourceLabel.Tag());
787   }
788   // iterate attributes
789   vector<DF_Attribute*> attrList = theSource.GetAttributes();
790   for(int i = 0, len = attrList.size(); i<len; i++) {
791     DF_Attribute* anAttr = attrList[i];
792     string type = SALOMEDSImpl_GenericAttribute::Impl_GetType(anAttr);
793     if (type.substr(0, 17) == string("AttributeTreeNode")) continue; // never copy tree node attribute
794     if (type == string("AttributeTarget")) continue; // and target attribute
795
796     if (type == string("AttributeReference")) { // reference copied as Comment in aux tree
797       DF_Label aReferenced = dynamic_cast<SALOMEDSImpl_AttributeReference*>(anAttr)->Get();
798       string anEntry = aReferenced.Entry();
799       // store the value of name attribute of referenced label
800       SALOMEDSImpl_AttributeName* aNameAttribute;
801       if ((aNameAttribute=(SALOMEDSImpl_AttributeName*)aReferenced.FindAttribute(SALOMEDSImpl_AttributeName::GetID()))) {
802         anEntry += " ";
803         anEntry += aNameAttribute->Value();
804       }
805       SALOMEDSImpl_AttributeComment::Set(aAuxTargetLabel, anEntry);
806       continue;
807     }
808
809     if (type == string("AttributeIOR")) { // IOR => ID and TMPFile of Engine
810       string anEntry = theSource.Entry();
811       SALOMEDSImpl_SObject aSO = theSourceStudy->FindObjectID(anEntry);
812       int anObjID;
813       long aLen;
814       SALOMEDSImpl_TMPFile* aStream = theEngine->CopyFrom(aSO, anObjID, aLen);
815       string aResStr("");
816       for(a = 0; a < aLen; a++) {
817         aResStr += (char)(aStream->Get(a));
818       }
819
820       if(aStream) delete aStream;
821
822       SALOMEDSImpl_AttributeInteger::Set(aAuxTargetLabel, anObjID);
823       SALOMEDSImpl_AttributeName::Set(aAuxTargetLabel, aResStr);
824       continue;
825     }
826     DF_Attribute* aNewAttribute = anAttr->NewEmpty();
827     aTargetLabel.AddAttribute(aNewAttribute);
828     anAttr->Paste(aNewAttribute);
829   }
830
831   return true;
832 }
833
834 //============================================================================
835 /*! Function : Copy
836  *  Purpose  :
837  */
838 //============================================================================
839 bool SALOMEDSImpl_StudyManager::Copy(const SALOMEDSImpl_SObject& theObject,
840                                      SALOMEDSImpl_Driver* theEngine)
841 {
842   _errorCode = "";
843
844   // adoptation for alliances datamodel copy: without IOR attributes !!!
845   bool aStructureOnly; // copy only SObjects and attributes without component help
846   aStructureOnly = !theObject.GetLabel().IsAttribute(SALOMEDSImpl_AttributeIOR::GetID());
847
848   // get component-engine
849   SALOMEDSImpl_Study* aStudy = theObject.GetStudy();
850
851   // CAF document of current study usage
852   DF_Document* aDocument = GetDocumentOfStudy(aStudy);
853   if (!aDocument) {
854     _errorCode = "Document is null";
855     return false;
856   }
857
858   //Clear the clipboard
859   _clipboard->Main().Root().ForgetAllAttributes(true);
860   _appli->Close(_clipboard);
861   _clipboard = _appli->NewDocument("SALOME_STUDY");
862
863   // set component data type to the name attribute of root label
864   if (!aStructureOnly) {
865     SALOMEDSImpl_AttributeComment::Set(_clipboard->Main().Root(),
866                                        theEngine->ComponentDataType());
867   }
868   // set to the Root label integer attribute: study id
869   SALOMEDSImpl_AttributeInteger::Set(_clipboard->Main().Root(), aStudy->StudyId());
870   // iterate all theObject's label children
871   DF_Label aStartLabel = theObject.GetLabel();
872   int aSourceStartDepth = aStartLabel.Depth();
873
874   // copy main source label
875   CopyLabel(aStudy, theEngine, aSourceStartDepth, aStartLabel, _clipboard->Main());
876
877   // copy all subchildren of the main source label (all levels)
878   DF_ChildIterator anIterator(aStartLabel, true);
879   for(; anIterator.More(); anIterator.Next()) {
880     CopyLabel(aStudy, theEngine, aSourceStartDepth, anIterator.Value(), _clipboard->Main());
881   }
882
883   return true;
884 }
885 //============================================================================
886 /*! Function : CanPaste
887  *  Purpose  :
888  */
889 //============================================================================
890 bool SALOMEDSImpl_StudyManager::CanPaste(const SALOMEDSImpl_SObject& theObject,
891                                          SALOMEDSImpl_Driver* theEngine)
892 {
893   _errorCode = "";
894
895   if (!_clipboard) {
896     _errorCode = "Clipboard is null";
897     return false;
898   }
899
900   SALOMEDSImpl_AttributeComment* aCompName = NULL;
901   if (!(aCompName=(SALOMEDSImpl_AttributeComment*)_clipboard->Main().Root().FindAttribute(SALOMEDSImpl_AttributeComment::GetID()))) {
902     _errorCode = "Clipboard has no component type";
903     return false;
904   }
905   SALOMEDSImpl_AttributeInteger* anObjID;
906   if (!(anObjID=(SALOMEDSImpl_AttributeInteger*)_clipboard->Main().Father().FindChild(2).FindAttribute(SALOMEDSImpl_AttributeInteger::GetID()))) {
907     _errorCode = "Clipboard has no object id";
908     return false;
909   }
910   SALOMEDSImpl_SComponent aComponent = theObject.GetFatherComponent();
911   if (!aComponent) {
912     _errorCode = "Object doesn't belong to component";
913     return false;
914   }
915
916   string IOREngine;
917   if (!aComponent.ComponentIOR(IOREngine)) {
918     _errorCode = "component has no IOR";
919     return false;
920   }
921   return theEngine->CanPaste(aCompName->Value(), anObjID->Value());
922 }
923
924 //============================================================================
925 /*! Function : PasteLabel
926  *  Purpose  :
927  */
928 //============================================================================
929 DF_Label SALOMEDSImpl_StudyManager::PasteLabel(SALOMEDSImpl_Study* theDestinationStudy,
930                                                SALOMEDSImpl_Driver* theEngine,
931                                                const DF_Label& theSource,
932                                                const DF_Label& theDestinationStart,
933                                                const int theCopiedStudyID,
934                                                const bool isFirstElement)
935 {
936   _errorCode = "";
937
938   // get corresponding source, target and auxiliary labels
939   DF_Label aTargetLabel = theDestinationStart;
940
941   DF_Label aAuxSourceLabel = theSource.Root().FindChild(2);
942   int a;
943   if (!isFirstElement) {
944     for(a = theSource.Depth() - 1; a > 0 ; a--) {
945       DF_Label aSourceLabel = theSource;
946       for(int aNbFather = 1; aNbFather < a; aNbFather++) aSourceLabel = aSourceLabel.Father();
947       aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
948       aAuxSourceLabel = aAuxSourceLabel.FindChild(aSourceLabel.Tag());
949     }
950   }
951
952   // check auxiliary label for TMPFile => IOR
953   SALOMEDSImpl_AttributeName* aNameAttribute = NULL;
954   if ((aNameAttribute=(SALOMEDSImpl_AttributeName*)aAuxSourceLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID()))) {
955     SALOMEDSImpl_AttributeInteger* anObjID = (SALOMEDSImpl_AttributeInteger*)aAuxSourceLabel.FindAttribute(SALOMEDSImpl_AttributeInteger::GetID());
956     SALOMEDSImpl_AttributeComment* aComponentName = (SALOMEDSImpl_AttributeComment*)theSource.Root().FindAttribute(SALOMEDSImpl_AttributeComment::GetID());
957     string aCompName = aComponentName->Value();
958
959     if (theEngine->CanPaste(aCompName, anObjID->Value())) {
960       std::string aTMPStr = aNameAttribute->Value();
961       int aLen = aTMPStr.size();
962       unsigned char* aStream = NULL;
963       if(aLen > 0) {
964         aStream = new unsigned char[aLen+10];
965         for(a = 0; a < aLen; a++) {
966           aStream[a] = aTMPStr[a];
967         }
968       }
969
970       string anEntry = aTargetLabel.Entry();
971       SALOMEDSImpl_SObject aPastedSO = theDestinationStudy->FindObjectID(anEntry);
972
973       if (isFirstElement) {
974         string aDestEntry = theEngine->PasteInto(aStream,
975                                                  aLen,
976                                                  anObjID->Value(),
977                                                  aPastedSO.GetFatherComponent());
978         aTargetLabel = DF_Label::Label(theDestinationStart, aDestEntry);
979       } else
980         theEngine->PasteInto(aStream, aLen, anObjID->Value(), aPastedSO);
981
982       if(aStream != NULL) delete []aStream;
983     }
984   }
985
986   // iterate attributes
987   vector<DF_Attribute*> attrList = theSource.GetAttributes();
988   for(int i = 0, len = attrList.size(); i<len; i++) {
989     DF_Attribute* anAttr = attrList[i];
990     if (aTargetLabel.FindAttribute(anAttr->ID())) {
991       aTargetLabel.ForgetAttribute(anAttr->ID());
992     }
993     DF_Attribute* aNewAttribute = anAttr->NewEmpty();
994     aTargetLabel.AddAttribute(aNewAttribute);
995     anAttr->Paste(aNewAttribute);
996   }
997
998   // check auxiliary label for Comment => reference or name attribute of the referenced object
999   SALOMEDSImpl_AttributeComment* aCommentAttribute = NULL;
1000   if ((aCommentAttribute=(SALOMEDSImpl_AttributeComment*)aAuxSourceLabel.FindAttribute(SALOMEDSImpl_AttributeComment::GetID()))) {
1001     char * anEntry = new char[aCommentAttribute->Value().size() + 1];
1002     strcpy(anEntry, string(aCommentAttribute->Value()).c_str());
1003     char* aNameStart = strchr(anEntry, ' ');
1004     if (aNameStart) {
1005       *aNameStart = '\0';
1006       aNameStart++;
1007     }
1008     if (theCopiedStudyID == theDestinationStudy->StudyId()) { // if copy to the same study, reanimate reference
1009       DF_Label aRefLabel = DF_Label::Label(aTargetLabel, anEntry);
1010       SALOMEDSImpl_AttributeReference::Set(aTargetLabel, aRefLabel);
1011       // target attributes structure support
1012       SALOMEDSImpl_AttributeTarget::Set(aRefLabel)->Add(SALOMEDSImpl_Study::SObject(aTargetLabel));
1013     } else {
1014       if (aNameStart) SALOMEDSImpl_AttributeName::Set(aTargetLabel, aNameStart);
1015       else SALOMEDSImpl_AttributeName::Set(aTargetLabel, std::string("Reference to:")+anEntry);
1016     }
1017     delete [] anEntry;
1018   }
1019
1020   return aTargetLabel;
1021 }
1022
1023 //============================================================================
1024 /*! Function : Paste
1025  *  Purpose  :
1026  */
1027 //============================================================================
1028 SALOMEDSImpl_SObject SALOMEDSImpl_StudyManager::Paste(const SALOMEDSImpl_SObject& theObject,
1029                                                SALOMEDSImpl_Driver* theEngine)
1030 {
1031   _errorCode = "";
1032
1033   SALOMEDSImpl_SObject so;
1034   SALOMEDSImpl_Study* aStudy = theObject.GetStudy();
1035
1036   // if study is locked, then paste can't be done
1037   if (aStudy->GetProperties()->IsLocked()) {
1038     _errorCode = "LockProtection";
1039     throw LockProtection("LockProtection");
1040   }
1041
1042   // if there is no component name, then paste only SObjects and attributes: without component help
1043   SALOMEDSImpl_AttributeComment* aComponentName = NULL;
1044   bool aStructureOnly = !(aComponentName=(SALOMEDSImpl_AttributeComment*)_clipboard->Main().Root().FindAttribute(SALOMEDSImpl_AttributeComment::GetID()));
1045
1046   // get copied study ID
1047   SALOMEDSImpl_AttributeInteger* aStudyIDAttribute = NULL;
1048   if (!(aStudyIDAttribute=(SALOMEDSImpl_AttributeInteger*)_clipboard->Main().Root().FindAttribute(SALOMEDSImpl_AttributeInteger::GetID()))) {
1049     _errorCode = "No study ID was found";
1050     return so;
1051   }
1052   int aCStudyID = aStudyIDAttribute->Value();
1053
1054   // CAF document of current study usage
1055   DF_Document* aDocument = GetDocumentOfStudy(aStudy);
1056   if (!aDocument) {
1057     _errorCode = "Document is null";
1058     return so;
1059   }
1060
1061   SALOMEDSImpl_SComponent aComponent = theObject.GetFatherComponent();
1062
1063   // fill root inserted SObject
1064   DF_Label aStartLabel;
1065   if (aStructureOnly) {
1066     DF_Label anObjectLabel = DF_Label::Label(aDocument->Main(), theObject.GetID());
1067     aStartLabel = PasteLabel(aStudy, theEngine, _clipboard->Main(), anObjectLabel, aCStudyID, false);
1068   } else {
1069     DF_Label aComponentLabel = DF_Label::Label(aDocument->Main(), aComponent.GetID());
1070     aStartLabel = PasteLabel(aStudy, theEngine, _clipboard->Main(), aComponentLabel, aCStudyID, true);
1071   }
1072
1073   // paste all sublebels
1074   DF_ChildIterator anIterator(_clipboard->Main(), true);
1075   for(; anIterator.More(); anIterator.Next()) {
1076     PasteLabel(aStudy, theEngine, anIterator.Value(), aStartLabel, aCStudyID, false);
1077   }
1078
1079   return SALOMEDSImpl_Study::SObject(aStartLabel);
1080 }
1081
1082 //#######################################################################################################
1083 //#                                     STATIC PRIVATE FUNCTIONS
1084 //#######################################################################################################
1085
1086 //============================================================================
1087 /*! Function : SaveAttributes
1088  *  Purpose  : Save attributes for object
1089  */
1090 //============================================================================
1091 static void SaveAttributes(const SALOMEDSImpl_SObject& aSO, HDFgroup *hdf_group_sobject)
1092 {
1093   hdf_size size[1];
1094   vector<DF_Attribute*> attrList = aSO.GetLabel().GetAttributes();
1095   DF_Attribute* anAttr = NULL;
1096   for(int i = 0, len = attrList.size(); i<len; i++) {
1097     anAttr = attrList[i];
1098     //The following attributes are not supposed to be written to the file
1099     string type = SALOMEDSImpl_GenericAttribute::Impl_GetType(anAttr);
1100     if(type == string("AttributeIOR")) continue; //IOR attribute is not saved
1101     string aSaveStr =anAttr->Save();
1102     //cout << "Saving: " << aSO.GetID() << " type: "<< type<<"|" << endl;
1103     size[0] = (hdf_int32) strlen(aSaveStr.c_str()) + 1;
1104     HDFdataset *hdf_dataset = new HDFdataset((char*)type.c_str(), hdf_group_sobject, HDF_STRING,size, 1);
1105     hdf_dataset->CreateOnDisk();
1106     hdf_dataset->WriteOnDisk((char*)aSaveStr.c_str());
1107     hdf_dataset->CloseOnDisk();
1108     hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1109   }
1110 }
1111
1112 //===========================================================================
1113 //Function : ReadAttributes
1114 //===========================================================================
1115 static void ReadAttributes(SALOMEDSImpl_Study* theStudy,
1116                            const SALOMEDSImpl_SObject& aSO,
1117                            HDFdataset* hdf_dataset)
1118 {
1119   hdf_dataset->OpenOnDisk();
1120
1121   DF_Attribute* anAttr = NULL;
1122   char* current_string = new char[hdf_dataset->GetSize()+1];
1123   hdf_dataset->ReadFromDisk(current_string);
1124   //cout << "Reading attr type = " << hdf_dataset->GetName() << "  SO = " << aSO.GetID() << endl;
1125   if (!strcmp(hdf_dataset->GetName(),"COMPONENTDATATYPE")) {
1126     anAttr = theStudy->NewBuilder()->FindOrCreateAttribute(aSO, "AttributeComment");
1127   } else if (!strcmp(hdf_dataset->GetName(),"AttributeReference") ||
1128              !strcmp(hdf_dataset->GetName(),"Reference")) { // Old format maintainance
1129     theStudy->NewBuilder()->Addreference(aSO, theStudy->CreateObjectID(current_string));
1130     delete(current_string);
1131     hdf_dataset->CloseOnDisk();
1132     return;
1133   } else {
1134     anAttr = theStudy->NewBuilder()->FindOrCreateAttribute(aSO, hdf_dataset->GetName());
1135   }
1136   
1137   if (anAttr) {
1138     anAttr->Load(current_string);
1139   }
1140   
1141   delete(current_string);
1142   hdf_dataset->CloseOnDisk();
1143 }
1144
1145 //============================================================================
1146 //Function : BuildlTree
1147 //============================================================================
1148 static void BuildTree (SALOMEDSImpl_Study* theStudy, HDFgroup* hdf_current_group)
1149 {
1150   hdf_current_group->OpenOnDisk();
1151   SALOMEDSImpl_SObject aSO;
1152   char* Entry = hdf_current_group->GetName();
1153   if (strcmp(Entry,"STUDY_STRUCTURE") == 0) {
1154     aSO = theStudy->CreateObjectID("0:1");
1155   }
1156   else {
1157     aSO = theStudy->CreateObjectID(Entry);
1158   }
1159
1160   char name[HDF_NAME_MAX_LEN+1];
1161   int nbsons = hdf_current_group->nInternalObjects();
1162   for (int i=0; i<nbsons; i++) {
1163     hdf_current_group->InternalObjectIndentify(i,name);
1164     if (strncmp(name, "INTERNAL_COMPLEX",16) == 0) continue;
1165     hdf_object_type type = hdf_current_group->InternalObjectType(name);
1166
1167     if  (type == HDF_DATASET) {
1168       HDFdataset* new_dataset = new HDFdataset(name,hdf_current_group);
1169       ReadAttributes(theStudy,aSO,new_dataset);
1170       new_dataset = 0; // will be deleted by father destructor
1171
1172     }
1173     else if (type == HDF_GROUP)   {
1174       HDFgroup* new_group = new HDFgroup(name,hdf_current_group);
1175       BuildTree (theStudy, new_group);
1176       new_group = 0; // will be deleted by father destructor
1177     }
1178   }
1179   hdf_current_group->CloseOnDisk();
1180 }
1181
1182
1183 //============================================================================
1184 //Function : Translate_IOR_to_persistentID
1185 //============================================================================
1186 static void Translate_IOR_to_persistentID (const SALOMEDSImpl_SObject& so,
1187                                            SALOMEDSImpl_Driver*                engine,
1188                                            bool                                isMultiFile,
1189                                            bool                                isASCII)
1190 {
1191   DF_ChildIterator itchild(so.GetLabel());
1192   string ior_string,  persistent_string, curid;
1193
1194   for (; itchild.More(); itchild.Next()) {
1195     SALOMEDSImpl_SObject current = SALOMEDSImpl_Study::SObject(itchild.Value());
1196     SALOMEDSImpl_AttributeIOR* IOR = NULL;
1197     if ((IOR=(SALOMEDSImpl_AttributeIOR*)current.GetLabel().FindAttribute(SALOMEDSImpl_AttributeIOR::GetID()))) {
1198       ior_string = IOR->Value();
1199
1200       persistent_string = engine->IORToLocalPersistentID (current, ior_string, isMultiFile, isASCII);
1201       SALOMEDSImpl_AttributePersistentRef::Set(current.GetLabel(), persistent_string);
1202     }
1203     Translate_IOR_to_persistentID (current, engine, isMultiFile, isASCII);
1204   }
1205 }
1206