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