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