Salome HOME
PR: mergefrom_BSEC_br1_14Mar04
[modules/yacs.git] / src / SALOMEDS / SALOMEDS_StudyManager_i.cxx
1 //  SALOME SALOMEDS : data structure of SALOME and sources of Salome data server 
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOMEDS_StudyManager_i.cxx
25 //  Author : Yves FRICAUD 
26 //  Module : SALOME
27 //  $Header$
28
29 #include "utilities.h"
30 #include "SALOME_LifeCycleCORBA.hxx"
31 #include "SALOMEDS_StudyManager_i.hxx"
32 #include "SALOMEDS_Study_i.hxx"
33 #include "SALOMEDS_SComponent_i.hxx"
34
35 #include "SALOMEDS_IORAttribute.hxx"
36 #include "SALOMEDS_PersRefAttribute.hxx"
37 #include "SALOMEDS_Tool.hxx"
38
39 #include <TDF_Label.hxx>
40 #include <TDataStd_Name.hxx>
41 #include <TDataStd_Comment.hxx>
42 #include <TDataStd_TreeNode.hxx>
43 #include <TDataStd_UAttribute.hxx> 
44 #include <TDF_Tool.hxx>
45 #include <TDF_Reference.hxx>
46 #include <TDF_Data.hxx>
47 #include <TDF_RelocationTable.hxx>
48 #include <TDF_AttributeIterator.hxx>
49 //  #include <TDocStd_Owner.hxx>
50 #include <TColStd_HArray1OfCharacter.hxx>
51 #include <TCollection_ExtendedString.hxx>
52 #include "HDFexplorer.hxx"
53 #include "SALOMEDS_SequenceOfRealAttribute.hxx"
54 #include "SALOMEDS_SequenceOfIntegerAttribute.hxx"
55 #include <TColStd_HSequenceOfReal.hxx>
56 #include <TColStd_HSequenceOfInteger.hxx>
57 #include "SALOMEDS_PixMapAttribute.hxx"
58 #include "SALOMEDS_DrawableAttribute.hxx"
59 #include "SALOMEDS_SelectableAttribute.hxx"
60 #include "SALOMEDS_ExpandableAttribute.hxx"
61 #include "SALOMEDS_OpenedAttribute.hxx"
62 #include "SALOMEDS_TextColorAttribute.hxx"
63 #include "SALOMEDS_TextHighlightColorAttribute.hxx"
64 #include "SALOMEDS_LocalIDAttribute.hxx"
65 #include "SALOMEDS_TargetAttribute.hxx"
66 #include "SALOMEDS_TableOfIntegerAttribute.hxx"
67 #include "SALOMEDS_TableOfRealAttribute.hxx"
68 #include "SALOMEDS_TableOfStringAttribute.hxx"
69 #include "SALOMEDS_StudyPropertiesAttribute.hxx"
70 #include "SALOMEDS_PythonObjectAttribute.hxx"
71 #include <OSD_Process.hxx>
72 #include <Quantity_Date.hxx>
73
74 #include "Utils_CorbaException.hxx"
75
76 #include <strstream>
77 using namespace std;
78
79 #include <SALOME_GenericObj_i.hh>
80
81 #define USE_CASE_LABEL_ID             "0:2"
82 #define AUTO_SAVE_GUID                "128268A3-71C9-4036-89B1-F81BD6A4FCF2"
83 #define AUTO_SAVE_TAG                 "0:8"
84 #define AUTO_SAVE_TIME_OUT_IN_SECONDS 1200
85 //===========================================================================
86 //Function : LoadAttributes
87 //===========================================================================
88 static void ReadAttributes(Handle(TDF_Data)& DF,
89                            TDF_Label& Lab, 
90                            HDFdataset* hdf_dataset)
91 {
92   hdf_dataset->OpenOnDisk();
93   
94   if (hdf_dataset->GetType() == HDF_STRING) {
95
96     if (!strncmp(hdf_dataset->GetName(),"AttributeTreeNode",17)) {
97       MESSAGE("Create a Attribute :     AttributeTreeNode");
98       char current_strings[5][hdf_dataset->GetSize()/5];
99 //       char **current_strings = new (char*)[5];
100 //       for(int i=0;i<5;i++)
101 //         current_strings[i] = new char[hdf_dataset->GetSize()/5+1];
102       hdf_dataset->ReadFromDisk(current_strings);
103
104       MESSAGE("Create an Attribute :     AttributeTreeNode"); 
105       Standard_GUID aGUID(current_strings[4]);
106       Handle(TDataStd_TreeNode) aNewNode = TDataStd_TreeNode::Set(Lab,aGUID);
107       TDF_Label aLabel;
108       Handle(TDataStd_TreeNode) aNode;
109       if (current_strings[0][0]) {
110         TDF_Tool::Label(DF,current_strings[0],aLabel,1);
111         if (!aLabel.FindAttribute(aGUID,aNode)) aNode = TDataStd_TreeNode::Set(aLabel,aGUID);
112         aNewNode->SetFather(aNode);
113       }
114       if (current_strings[1][0]) {
115         TDF_Tool::Label(DF,current_strings[1],aLabel,1);
116        if (!aLabel.FindAttribute(aGUID,aNode)) aNode = TDataStd_TreeNode::Set(aLabel,aGUID);
117         aNewNode->SetPrevious(aNode);
118       }
119       if (current_strings[2][0]) {
120         TDF_Tool::Label(DF,current_strings[2],aLabel,1);
121         if (!aLabel.FindAttribute(aGUID,aNode)) aNode = TDataStd_TreeNode::Set(aLabel,aGUID);
122         aNewNode->SetNext(aNode);
123       }
124       if (current_strings[3][0]) {
125         TDF_Tool::Label(DF,current_strings[3],aLabel,1);
126         if (!aLabel.FindAttribute(aGUID,aNode)) aNode = TDataStd_TreeNode::Set(aLabel,aGUID);
127         aNewNode->SetFirst(aNode);
128       }
129 //       for(int i=0;i<5;i++)
130 //         delete[] current_strings[i];
131 //       delete[] current_strings;
132     } else {
133
134       int size =  hdf_dataset->GetSize();
135       char* current_string = new char[size];
136       hdf_dataset->ReadFromDisk(current_string);
137
138       if (!strcmp(hdf_dataset->GetName(),"COMPONENTDATATYPE")) {      
139         MESSAGE("Create a OCAF Attribute :    COMPONENTDATATYPE");
140         TDataStd_Comment::Set         (Lab,current_string); 
141       }
142       else if (!strcmp(hdf_dataset->GetName(),"AttributeComment")) {
143         MESSAGE("Create an Attribute :     AttributeComment"); 
144         TDataStd_Comment::Set         (Lab,current_string); 
145       }
146       else if (!strcmp(hdf_dataset->GetName(),"AttributeName")) {
147         MESSAGE("Create an  Attribute :     AttributeName");       
148         TDataStd_Name::Set            (Lab,current_string);
149       }
150       else if (!strcmp(hdf_dataset->GetName(),"AttributePersistentRef")) { 
151         MESSAGE("Create an Attribute :     AttributePersistentRef"); 
152         SALOMEDS_PersRefAttribute::Set(Lab,current_string);
153       }
154       else if (!strcmp(hdf_dataset->GetName(),"Reference")) {
155         MESSAGE("Create a OCAF Attribute :     Reference"); 
156         TDF_Label RefLab;
157         TDF_Tool::Label(DF,current_string,RefLab,1);
158         TDF_Reference::Set(Lab,RefLab);
159         SALOMEDS_TargetAttribute::Set(RefLab)->Append(Lab);
160       }
161       else if (!strcmp(hdf_dataset->GetName(),"AttributeReal")) {
162         MESSAGE("Create a Attribute :     AttributeReal");
163         char * err = NULL;
164         CORBA::Double r =  strtod(current_string, &err);
165         SCRUTE(r);
166         if (err == current_string) {
167           MESSAGE("AtttributeReal : conversion impossible");
168         }
169         else TDataStd_Real::Set (Lab,r);
170       }
171       else if (!strcmp(hdf_dataset->GetName(),"AttributeInteger")) {
172         MESSAGE("Create a Attribute :     AttributeInteger");
173         CORBA::Long r =  atol(current_string);
174         SCRUTE(r);
175         TDataStd_Integer::Set (Lab,r);
176       }
177       else if (!strcmp(hdf_dataset->GetName(),"AttributePixMap")) {
178         MESSAGE("Create an  Attribute :     AttributePixMap");       
179         SALOMEDS_PixMapAttribute::Set (Lab,current_string);
180       }
181       else if (!strcmp(hdf_dataset->GetName(),"AttributeDrawable")) {
182         MESSAGE("Create a Attribute :     DrawableAttribute");
183         CORBA::Long r =  atol(current_string);
184         SCRUTE(r);
185         SALOMEDS_DrawableAttribute::Set (Lab,r);
186       }
187       else if (!strcmp(hdf_dataset->GetName(),"AttributeSelectable")) {
188         MESSAGE("Create a Attribute :     AttributeSelectable");
189         CORBA::Long r =  atol(current_string);
190         SCRUTE(r);
191         SALOMEDS_SelectableAttribute::Set (Lab,r);
192       }
193       else if (!strcmp(hdf_dataset->GetName(),"AttributeExpandable")) {
194         MESSAGE("Create a Attribute :     AttributeExpandable");
195         CORBA::Long r =  atol(current_string);
196         SCRUTE(r);
197         SALOMEDS_ExpandableAttribute::Set (Lab,r);
198       }
199       else if (!strcmp(hdf_dataset->GetName(),"AttributeOpened")) {
200         MESSAGE("Create a Attribute :     AttributeOpened");
201         CORBA::Long r =  atol(current_string);
202         SCRUTE(r);
203         SALOMEDS_OpenedAttribute::Set (Lab,r);
204       }
205       else if (!strcmp(hdf_dataset->GetName(),"AttributeLocalID")) {
206         MESSAGE("Create a Attribute :     AttributeLocalID");
207         CORBA::Long r =  atol(current_string);
208         SCRUTE(r);
209         SALOMEDS_LocalIDAttribute::Set (Lab,r);
210       }
211       else if (!strncmp(hdf_dataset->GetName(),"AttributeUserID",15)) {
212         MESSAGE("Create an  Attribute :     AttributeUserID");       
213         TDataStd_UAttribute::Set       (Lab,Standard_GUID(current_string));
214       }
215       else if (!strcmp(hdf_dataset->GetName(),"AttributeTableOfInteger")) {
216         MESSAGE("Create a Attribute :     AttributeTableOfInteger");
217         int size = hdf_dataset->GetSize();
218         Handle(SALOMEDS_TableOfIntegerAttribute) Attr = SALOMEDS_TableOfIntegerAttribute::Set(Lab);
219         unsigned char* aBuffer = new unsigned char[size];
220         if(aBuffer == NULL) throw HDFexception("Unable to open dataset AttributeTableOfInteger");
221         hdf_dataset->ReadFromDisk(aBuffer);
222         SALOMEDS::TMPFile_var aTMPFile = new SALOMEDS::TMPFile(size, size, aBuffer, 1);
223         istrstream aStream((char*)&aTMPFile[0], aTMPFile->length());
224         Attr->RestoreFromString(aStream);
225       }
226       else if (!strcmp(hdf_dataset->GetName(),"AttributeTableOfReal")) {
227         MESSAGE("Create a Attribute :     AttributeTableOfReal");
228         int size = hdf_dataset->GetSize();
229         Handle(SALOMEDS_TableOfRealAttribute) Attr = SALOMEDS_TableOfRealAttribute::Set(Lab);
230         unsigned char* aBuffer = new unsigned char[size];
231         if(aBuffer == NULL) throw HDFexception("Unable to open dataset AttributeTableOfReal");
232         hdf_dataset->ReadFromDisk(aBuffer);
233         SALOMEDS::TMPFile_var aTMPFile = new SALOMEDS::TMPFile(size, size, aBuffer, 1);
234         istrstream aStream((char*)&aTMPFile[0], aTMPFile->length());
235         Attr->RestoreFromString(aStream);
236       }
237       else if (!strcmp(hdf_dataset->GetName(),"AttributeTableOfString")) {
238         MESSAGE("Create a Attribute :     AttributeTableOfString");
239         int size = hdf_dataset->GetSize();
240         Handle(SALOMEDS_TableOfStringAttribute) Attr = SALOMEDS_TableOfStringAttribute::Set(Lab);
241         unsigned char* aBuffer = new unsigned char[size];
242         if(aBuffer == NULL) throw HDFexception("Unable to open dataset AttributeTableOfString");
243         hdf_dataset->ReadFromDisk(aBuffer);
244         SALOMEDS::TMPFile_var aTMPFile = new SALOMEDS::TMPFile(size, size, aBuffer, 1);
245         istrstream aStream((char*)&aTMPFile[0], aTMPFile->length());
246         Attr->RestoreFromString(aStream);
247       }
248       else if (!strcmp(hdf_dataset->GetName(),"AttributeStudyProperties")) {
249         MESSAGE("Create an  Attribute :     AttributeStudyProperties");     
250 //      MESSAGE("current string :"<<current_string);
251         Handle(SALOMEDS_StudyPropertiesAttribute) aProp = SALOMEDS_StudyPropertiesAttribute::Set (Lab);
252         switch (current_string[0]) {
253         case 'f': aProp->SetCreationMode(1);break;
254         case 'c': aProp->SetCreationMode(2);break;
255         }
256
257         int anIndex;
258         for(anIndex = 2; anIndex + 2 < size ;) {
259           char str[10];
260           Standard_Integer aMinute, aHour, aDay, aMonth, aYear;
261           str[0] = current_string[anIndex++];
262           str[1] = current_string[anIndex++];
263           str[2] = 0;
264           aMinute = atoi(str);
265           str[0] = current_string[anIndex++];
266           str[1] = current_string[anIndex++];
267           aHour =  atoi(str);
268           str[0] = current_string[anIndex++];
269           str[1] = current_string[anIndex++];
270           aDay =  atoi(str);
271           str[0] = current_string[anIndex++];
272           str[1] = current_string[anIndex++];
273           aMonth =  atoi(str);
274           str[0] = current_string[anIndex++];
275           str[1] = current_string[anIndex++];
276           str[2] = current_string[anIndex++];
277           str[3] = current_string[anIndex++];
278           str[4] = 0;
279           aYear = atoi(str);
280           aProp->SetModificationDate(aMinute,aHour,aDay,aMonth,aYear);
281
282           int aNameSize;
283           for(aNameSize = 0; current_string[anIndex+aNameSize]!=1; aNameSize++);
284           char *aName = new char[aNameSize+1];
285           strncpy(aName, &(current_string[anIndex]), aNameSize);
286           aName[aNameSize] = 0;
287           aProp->SetUserName(TCollection_ExtendedString(aName));
288           delete(aName);
289           anIndex += aNameSize + 1;
290           if (current_string[1] == 'l') {
291             aProp->SetLocked(Standard_True);
292             aProp->IsLockChanged(true);
293           }
294           aProp->SetModified(0);
295         }
296       }
297       else if (!strcmp(hdf_dataset->GetName(),"AttributePythonObject")) {
298         MESSAGE("Create an  Attribute :     AttributePythonObject");       
299         Handle(SALOMEDS_PythonObjectAttribute) anObj = SALOMEDS_PythonObjectAttribute::Set(Lab);
300         Standard_Boolean aScript = (current_string[0] == 's')?Standard_True:Standard_False;
301         anObj->SetObject((char *)(current_string+1), aScript);
302       }
303       else {
304         MESSAGE(hdf_dataset->GetName());
305         MESSAGE("LoadAttributes: unknown types");
306       }
307     }
308   }
309   if (hdf_dataset->GetType() == HDF_FLOAT64) {
310     if (!strcmp(hdf_dataset->GetName(),"AttributeSequenceOfReal")) {
311       MESSAGE("Create a Attribute :     AttributeSequenceOfReal");
312       int size = hdf_dataset->GetSize();
313       hdf_float64* val = new hdf_float64[size];
314       hdf_dataset->ReadFromDisk(val);
315       Handle(TColStd_HSequenceOfReal) SeqReal = new TColStd_HSequenceOfReal;
316       for (Standard_Integer i = 0; i < size; i++) {
317         SeqReal->Append(val[i]);
318 //          MESSAGE( val[i] << " restored"   );
319       }
320       SALOMEDS_SequenceOfRealAttribute::Set (Lab);
321       Handle(SALOMEDS_SequenceOfRealAttribute) Attr;
322       Handle(TDF_Attribute) Att;
323       Lab.FindAttribute(SALOMEDS_SequenceOfRealAttribute::GetID(),Att);
324       Attr = Handle(SALOMEDS_SequenceOfRealAttribute)::DownCast(Att);
325       Attr->Assign(SeqReal);
326     } else
327     if (!strcmp(hdf_dataset->GetName(),"AttributeTextColor")) {
328       MESSAGE("Create a Attribute :     AttributeTextColor");
329       hdf_float64 val[3];
330       hdf_dataset->ReadFromDisk(val);
331       Handle(SALOMEDS_TextColorAttribute) TC = new SALOMEDS_TextColorAttribute;
332       Lab.AddAttribute(TC); 
333       TC->SetValue(1, val[0]);
334       TC->SetValue(2, val[1]);
335       TC->SetValue(3, val[2]);
336     } else
337     if (!strcmp(hdf_dataset->GetName(),"AttributeTextHighlightColor")) {
338       MESSAGE("Create a Attribute :     AttributeTextHighlightColor");
339       hdf_float64 val[3];
340       hdf_dataset->ReadFromDisk(val);
341       Handle(SALOMEDS_TextHighlightColorAttribute) TC = new SALOMEDS_TextHighlightColorAttribute;
342       Lab.AddAttribute(TC); 
343       TC->SetValue(1, val[0]);
344       TC->SetValue(2, val[1]);
345       TC->SetValue(3, val[2]);
346     }else {
347       MESSAGE(hdf_dataset->GetName());
348       MESSAGE("LoadAttributes: unknown types");
349     }
350   }
351   if (hdf_dataset->GetType() == HDF_INT32) {
352     if (!strcmp(hdf_dataset->GetName(),"AttributeSequenceOfInteger")) {
353       MESSAGE("Create a OCAF Attribute :     AttributeSequenceOfInteger");
354       int size = hdf_dataset->GetSize();
355       hdf_int32* val = new hdf_int32[size];
356       hdf_dataset->ReadFromDisk(val);
357       Handle(TColStd_HSequenceOfInteger) SeqInt = new TColStd_HSequenceOfInteger;
358       for (Standard_Integer i = 0; i < size; i++) {
359         SeqInt->Append(val[i]);
360 //          MESSAGE( val[i] << " restored"   );
361       }
362       SALOMEDS_SequenceOfIntegerAttribute::Set (Lab);
363       Handle(SALOMEDS_SequenceOfIntegerAttribute) Attr;
364       Handle(TDF_Attribute) Att;
365       Lab.FindAttribute(SALOMEDS_SequenceOfIntegerAttribute::GetID(),Att);
366       Attr = Handle(SALOMEDS_SequenceOfIntegerAttribute)::DownCast(Att);
367       Attr->Assign(SeqInt);
368     } 
369     else {
370       MESSAGE(hdf_dataset->GetName());
371       MESSAGE("LoadAttributes: unknown types");
372     }
373   }
374   hdf_dataset->CloseOnDisk();
375 }
376
377 //============================================================================
378 //Function : Translate_IOR_to_persistentID
379 //============================================================================
380 static void Translate_IOR_to_persistentID (SALOMEDS::Study_ptr        study,
381                                            SALOMEDS::StudyBuilder_ptr SB,
382                                            SALOMEDS::SObject_ptr      so,
383                                            SALOMEDS::Driver_ptr       engine,
384                                            CORBA::Boolean             isMultiFile,
385                                            CORBA::Boolean             isASCII)
386 {
387   MESSAGE("In Translate_IOR_to_persistentID");
388   SALOMEDS::ChildIterator_var itchild = study->NewChildIterator(so);
389   CORBA::String_var ior_string;
390   char* persistent_string = 0;
391   char *curid=0;
392
393   for (; itchild->More(); itchild->Next()) {
394     SALOMEDS::SObject_var current = itchild->Value();
395     SCRUTE(current->GetID());
396     SALOMEDS::GenericAttribute_var SObj;
397     if (current->FindAttribute(SObj, "AttributeIOR")) {
398       SALOMEDS::AttributeIOR_var IOR = SALOMEDS::AttributeIOR::_narrow(SObj);
399       ior_string = IOR->Value();
400       SCRUTE(ior_string);
401       
402       persistent_string = engine->IORToLocalPersistentID (current,ior_string,isMultiFile, isASCII);
403       
404 //       SB->AddAttribute (current, SALOMEDS::PersistentRef,persistent_string);
405       SALOMEDS::AttributePersistentRef_var Pers = SALOMEDS::AttributePersistentRef::_narrow(SB->FindOrCreateAttribute (current, "AttributePersistentRef"));
406       Pers->SetValue(persistent_string);
407       SCRUTE(persistent_string);
408       curid = current->GetID();
409       MESSAGE("Translate " << curid <<
410               " to Persistent string "<<persistent_string);
411       persistent_string = 0;
412       curid = 0;
413     }
414     Translate_IOR_to_persistentID (study,SB,current,engine,isMultiFile, isASCII);
415   }
416   CORBA::string_free(persistent_string);
417   CORBA::string_free(curid);
418 }
419
420 //============================================================================
421 //Function : BuildlTree
422 //============================================================================
423 static void BuildTree  (Handle(TDF_Data)& DF,HDFgroup* hdf_current_group)
424 {
425   hdf_current_group->OpenOnDisk();
426   
427   TDF_Label Lab;
428   Standard_CString Entry = hdf_current_group->GetName();
429   if (strcmp(Entry,"STUDY_STRUCTURE") == 0) {
430     MESSAGE("find the root of the document");
431     Lab =  DF->Root().FindChild(1,Standard_True);
432   }
433   else {
434     TDF_Tool::Label  (DF,Entry,Lab,1);
435     MESSAGE("BuildTree : Create a new label"<<Entry);
436   }
437   char name[HDF_NAME_MAX_LEN+1];
438   Standard_Integer nbsons = hdf_current_group->nInternalObjects(); 
439   
440   for (Standard_Integer i=0; i<nbsons; i++) {
441     hdf_current_group->InternalObjectIndentify(i,name);
442     if (strncmp(name, "INTERNAL_COMPLEX",16) == 0) continue;
443     hdf_object_type type = hdf_current_group->InternalObjectType(name);
444
445     if  (type == HDF_DATASET) {
446       MESSAGE("--> Dataset: Internal Object Name : " << name);
447       HDFdataset* new_dataset = new HDFdataset(name,hdf_current_group);
448       ReadAttributes   (DF,Lab,new_dataset);      
449       new_dataset = 0; // will be deleted by father destructor
450
451     }
452     else if (type == HDF_GROUP)   {
453       MESSAGE( "--> Group: Internal Object Name : " << name);
454       HDFgroup* new_group = new HDFgroup(name,hdf_current_group);
455       BuildTree (DF,new_group);
456       new_group = 0; // will be deleted by father destructor
457     }
458   }
459   hdf_current_group->CloseOnDisk();
460 }
461
462
463 //============================================================================
464 /*! Function : SALOMEDS_StudyManager_i
465  *  Purpose  : SALOMEDS_StudyManager_i constructor 
466  */
467 //============================================================================
468 SALOMEDS_StudyManager_i::SALOMEDS_StudyManager_i(CORBA::ORB_ptr orb) 
469
470   _orb = CORBA::ORB::_duplicate(orb);
471   _OCAFApp = new SALOMEDS_OCAFApplication();  
472   _name_service = new SALOME_NamingService(_orb);
473   // Study directory creation in the naming service : to register all
474   // open studies in the session
475   _name_service->Create_Directory("/Study");
476   _IDcounter = 0;
477 }
478
479 //============================================================================
480 /*! Function : ~SALOMEDS_StudyManager_i
481  *  Purpose  : SALOMEDS_StudyManager_i destructor
482  */
483 //============================================================================
484 SALOMEDS_StudyManager_i::~SALOMEDS_StudyManager_i()
485 {
486   // Destroy directory to register open studies
487   _name_service->Destroy_Directory("/Study");
488   // Destroy OCAF document
489   delete &_OCAFApp;
490 }
491
492 //============================================================================
493 /*! Function : register_name
494  *  Purpose  : Register the study Manager in the naming service under the  
495  *             context name
496  */
497 //============================================================================
498 void SALOMEDS_StudyManager_i::register_name(char * name) {
499   SALOMEDS::StudyManager_ptr g = SALOMEDS::StudyManager::_narrow(_this());
500   _name_service->Register(g, name);
501 }
502
503
504 //============================================================================
505 /*! Function : NewStudy
506  *  Purpose  : Create a New Study of name study_name
507  */
508 //============================================================================
509 SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::NewStudy(const char* study_name) 
510 {
511   Handle(TDocStd_Document) Doc;
512   _OCAFApp->NewDocument("SALOME_STUDY",Doc); 
513
514   MESSAGE("NewStudy : Creating the CORBA servant holding it... ");
515   SALOMEDS_Study_i *Study_servant = new SALOMEDS_Study_i(Doc,_orb,study_name); 
516   SALOMEDS::Study_var Study = SALOMEDS::Study::_narrow(Study_servant->_this());
517
518   //Study->StudyId( _OCAFApp->NbDocuments() ); 
519   _IDcounter++;
520   Study->StudyId( _IDcounter );
521
522   // Register study in the naming service
523   // Path to acces the study
524   if(!_name_service->Change_Directory("/Study")) 
525       MESSAGE( "Unable to access the study directory" )
526   else
527       _name_service->Register(Study, study_name);
528
529   // Assign the value of the IOR in the study->root
530   const char*  IORStudy = _orb->object_to_string(Study);
531   SALOMEDS_IORAttribute::Set(Doc->Main().Root(),TCollection_ExtendedString(strdup(IORStudy)),_orb);
532
533   // set Study properties
534   SALOMEDS::AttributeStudyProperties_ptr aProp = Study->GetProperties();
535   OSD_Process aProcess;
536   Quantity_Date aDate = aProcess.SystemDate();
537   aProp->SetCreationDate(CORBA::Long(aDate.Minute()), CORBA::Long(aDate.Hour()), CORBA::Long(aDate.Day()),
538                          CORBA::Long(aDate.Month()), CORBA::Long(aDate.Year()));
539   aProp->SetCreationMode("from scratch");
540   aProp->SetUserName(aProcess.UserName().ToCString());
541
542   return Study;
543 }
544
545 //============================================================================
546 /*! Function : Open
547  *  Purpose  : Open a Study from it's persistent reference
548  */
549 //============================================================================
550 SALOMEDS::Study_ptr  SALOMEDS_StudyManager_i::Open(const char* aUrl)
551      throw(SALOME::SALOME_Exception)
552 {
553   MESSAGE("Begin of SALOMEDS_StudyManager_i::Open");
554   // open the HDFFile 
555   HDFfile *hdf_file =0;         
556   HDFgroup *hdf_group_study_structure =0;
557
558   char* aHDFUrl;
559   bool isASCII = false;
560   if (HDFascii::isASCII(aUrl)) {
561     isASCII = true;
562     char* aResultPath = HDFascii::ConvertFromASCIIToHDF(aUrl);
563     aHDFUrl = new char[strlen(aResultPath) + 19];
564     sprintf(aHDFUrl, "%shdf_from_ascii.hdf", aResultPath);
565     delete(aResultPath);
566   } else {
567     aHDFUrl = strdup(aUrl);
568   }
569
570   hdf_file = new HDFfile(aHDFUrl);
571   try {
572     hdf_file->OpenOnDisk(HDF_RDONLY);// mpv: was RDWR, but opened file can be write-protected too
573   }
574   catch (HDFexception)
575     {
576 //        MESSAGE( "HDFexception ! " );
577 //        cerr << "HDFexception ! " << endl;
578       delete aHDFUrl;
579       char eStr[strlen(aUrl)+17];
580 //      char *eStr = new char[strlen(aUrl)+17+1];
581       sprintf(eStr,"Can't open file %s",aUrl);
582       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(eStr),SALOME::BAD_PARAM);
583     } 
584   MESSAGE("Open : Creating the CORBA servant holding it... ");
585
586   // Temporary aStudyUrl in place of study name
587   Handle(TDocStd_Document) Doc;
588   _OCAFApp->NewDocument("SALOME_STUDY",Doc); 
589
590   SALOMEDS_Study_i * Study_servant = new SALOMEDS_Study_i(Doc, _orb, aUrl);  
591   SALOMEDS::Study_var Study = SALOMEDS::Study::_narrow(Study_servant->_this()); 
592
593   //  Study->StudyId( _OCAFApp->NbDocuments() ); 
594   _IDcounter++;
595   Study->StudyId( _IDcounter );
596
597   // Assign the value of the URL in the study object
598   Study->URL (aUrl);
599   SCRUTE(aUrl);
600
601   // Assign the value of the IOR in the study->root
602   CORBA::String_var IORStudy = _orb->object_to_string(Study);
603   SALOMEDS_IORAttribute::Set(Doc->Main().Root(),
604                              TCollection_ExtendedString(CORBA::string_dup(IORStudy)),_orb);
605
606   SALOMEDS_PersRefAttribute::Set(Doc->Main(),strdup(aUrl)); 
607
608   if (!hdf_file->ExistInternalObject("STUDY_STRUCTURE")) {
609     delete aHDFUrl;
610     MESSAGE("SALOMEDS_StudyManager::Open : the study is empty");
611     return Study;
612   }
613
614   //Create  the Structure of the OCAF Document
615   hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
616
617   Handle(TDF_Data) DF = Doc->GetData();
618
619   try {
620     BuildTree (DF,hdf_group_study_structure);
621   }
622   catch (HDFexception)
623     {
624 //        MESSAGE( "HDFexception ! " );
625 //        cerr << "HDFexception ! " << endl;
626       delete aHDFUrl;
627       char eStr[strlen(aUrl)+17];
628 //      char *eStr = new char[strlen(aUrl)+17+1];
629       sprintf(eStr,"Can't open file %s",aUrl);
630       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(eStr),SALOME::BAD_PARAM);
631     } 
632   
633   hdf_file->CloseOnDisk();
634
635   // Register study in the naming service
636   // Path to acces the study
637   if(!_name_service->Change_Directory("/Study")) MESSAGE( "Unable to access the study directory" )
638   else _name_service->Register(Study, CORBA::string_dup(Study->Name()));
639
640
641   if (isASCII) {
642     SALOMEDS::ListOfFileNames_var aFilesToRemove = new SALOMEDS::ListOfFileNames;
643     aFilesToRemove->length(1);
644     aFilesToRemove[0] = strdup(&(aHDFUrl[strlen(SALOMEDS_Tool::GetDirFromPath(aHDFUrl))]));
645     SALOMEDS_Tool::RemoveTemporaryFiles(SALOMEDS_Tool::GetDirFromPath(aHDFUrl), aFilesToRemove, true);
646   }
647   delete aHDFUrl;
648   delete hdf_file; // all related hdf objects will be deleted
649   return Study;
650 }
651
652
653
654 //============================================================================
655 /*! Function : Close
656  *  Purpose  : Close a study.
657  *             If the study hasn't been saved, ask the user to confirm the
658  *             close action without saving 
659  */
660 //============================================================================
661 void  SALOMEDS_StudyManager_i::Close(SALOMEDS::Study_ptr aStudy)
662 {
663   if(aStudy->_is_nil()) return;
664   
665   aStudy->RemovePostponed(-1);
666   
667   // Destroy study name in the naming service
668   if(_name_service->Change_Directory("/Study")) 
669     _name_service->Destroy_Name(aStudy->Name());
670   
671   aStudy->Close();
672 }
673
674 //============================================================================
675 /*! Function : Save
676  *  Purpose  : Save a Study to it's persistent reference
677  */
678 //============================================================================
679 void SALOMEDS_StudyManager_i::Save(SALOMEDS::Study_ptr aStudy, CORBA::Boolean theMultiFile)
680 {
681   CORBA::String_var url = aStudy->URL();
682   if (url==NULL)
683     MESSAGE( "No path specified to save the study. Nothing done")
684   else
685     {
686       _SaveAs(url,aStudy, theMultiFile, false);
687     }
688 }
689
690 void SALOMEDS_StudyManager_i::SaveASCII(SALOMEDS::Study_ptr aStudy, CORBA::Boolean theMultiFile)
691 {
692   CORBA::String_var url = aStudy->URL();
693   if (url==NULL)
694     MESSAGE( "No path specified to save the study. Nothing done")
695   else
696     {
697       _SaveAs(url,aStudy, theMultiFile, true);
698     }
699 }
700
701 //=============================================================================
702 /*! Function : SaveAs
703  *  Purpose  : Save a study to the persistent reference aUrl
704  */
705 //============================================================================
706 void SALOMEDS_StudyManager_i::SaveAs(const char* aUrl, SALOMEDS::Study_ptr aStudy, CORBA::Boolean theMultiFile)
707 {
708   _SaveAs(aUrl,aStudy,theMultiFile, false);
709
710 }
711
712 void SALOMEDS_StudyManager_i::SaveAsASCII(const char* aUrl, SALOMEDS::Study_ptr aStudy, CORBA::Boolean theMultiFile)
713 {
714   _SaveAs(aUrl,aStudy,theMultiFile, true);
715 }
716
717 //============================================================================
718 /*! Function : GetOpenStudies
719  *  Purpose  : Get name list of open studies in the session
720  */
721 //============================================================================
722 SALOMEDS::ListOfOpenStudies*  SALOMEDS_StudyManager_i::GetOpenStudies()
723 {
724   // MESSAGE("Begin of GetOpenStudies");
725   SALOMEDS::ListOfOpenStudies_var _list_open_studies = new SALOMEDS::ListOfOpenStudies;
726   _list_open_studies->length(0);
727   vector<string> _list ;
728
729   if(!_name_service->Change_Directory("/Study"))
730     {
731       MESSAGE("No active study in this session");
732     }
733   else
734     {
735       _list = _name_service->list_directory();
736       _list_open_studies->length(_list.size());
737       for (unsigned int ind=0; ind < _list.size();ind++)
738         {
739           _list_open_studies[ind]=CORBA::string_dup(_list[ind].c_str());
740           SCRUTE(_list_open_studies[ind]) ;
741         }
742     }
743   return _list_open_studies._retn();
744 }
745
746 //============================================================================
747 /*! Function : GetStudyByName
748  *  Purpose  : Get a study from its name
749  */
750 //============================================================================
751 SALOMEDS::Study_ptr  
752 SALOMEDS_StudyManager_i::GetStudyByName(const char* aStudyName) 
753 {
754   SALOMEDS::Study_var Study;
755
756   // Go to study directory and look for aStudyName
757   if(!_name_service->Change_Directory("/Study"))
758     {
759       MESSAGE("No active study in this session");
760       ASSERT(false); // Stop here...
761     }
762   
763 //   const char *theStudyName = this->_SubstituteSlash(aStudyName);
764   const char* theStudyName = CORBA::string_dup(aStudyName);
765
766   if(_name_service->Find(theStudyName)>0)
767     {
768     // Study found
769     CORBA::Object_ptr obj= _name_service->Resolve(theStudyName) ;
770     Study = SALOMEDS::Study::_narrow(obj);
771     MESSAGE("Study " << theStudyName << " found in the naming service");
772     }
773   else  
774     {
775       Study = SALOMEDS::Study::_narrow( CORBA::Object::_nil()); 
776       MESSAGE("Study " << theStudyName << " not found in the naming service");
777     }
778   return Study;
779 }
780
781 //============================================================================
782 /*! Function : GetStudyByID
783  *  Purpose  : Get a study from its ID
784  */
785 //============================================================================
786 SALOMEDS::Study_ptr  
787 SALOMEDS_StudyManager_i::GetStudyByID(CORBA::Short aStudyID) 
788 {
789   SALOMEDS::Study_var Study;
790   vector<string> _list ;
791
792   if(!_name_service->Change_Directory("/Study"))
793     {
794       MESSAGE("No active study in this session");
795     }
796   else
797     {
798       _list = _name_service->list_directory();
799       for (unsigned int ind=0; ind < _list.size();ind++)
800         {
801           const char* theStudyName = CORBA::string_dup(_list[ind].c_str());
802           MESSAGE ( "GetStudyByID = " << theStudyName )
803
804           if(_name_service->Find(theStudyName)>0) {
805             CORBA::Object_ptr obj= _name_service->Resolve(theStudyName) ;
806             Study = SALOMEDS::Study::_narrow(obj);
807
808             MESSAGE ( " aStudyID : " << aStudyID << "-" << Study->StudyId() )
809
810             if ( aStudyID == Study->StudyId() ) {
811               MESSAGE("Study with studyID = " << aStudyID << " found in the naming service");
812               return Study;
813             }
814           } else {
815             Study = SALOMEDS::Study::_narrow( CORBA::Object::_nil()); 
816             MESSAGE("Study " << theStudyName << " not found in the naming service");
817           }
818         }
819       Study = SALOMEDS::Study::_narrow( CORBA::Object::_nil()); 
820     }
821   return Study;
822 }
823 //============================================================================
824 /*! Function : SaveAttributes
825  *  Purpose  : Save attributes for object
826  */
827 //============================================================================
828 static void SaveAttributes(SALOMEDS::SObject_ptr SO, HDFgroup *hdf_group_sobject) {
829   HDFdataset *hdf_dataset = 0;
830   hdf_size size[1];
831   hdf_int32 name_len = 0;
832   SALOMEDS::GenericAttribute_var SObj;
833   if(SO->FindAttribute(SObj, "AttributeComment"))
834     {
835       SALOMEDS::AttributeComment_var Comment = SALOMEDS::AttributeComment::_narrow(SObj);
836         CORBA::String_var Val = Comment->Value();
837         name_len = (hdf_int32) strlen(Val);
838         size[0] = name_len +1 ; 
839         hdf_dataset = new HDFdataset("AttributeComment",hdf_group_sobject,HDF_STRING,size,1);
840         hdf_dataset->CreateOnDisk();
841         hdf_dataset->WriteOnDisk(Val);
842         MESSAGE("attribute comment " <<  Val << " wrote on file");
843         hdf_dataset->CloseOnDisk();
844         hdf_dataset=0; //will be deleted by hdf_sco_group destructor
845       }
846   // Attribute  SALOMEDS::PersistentRef
847   if(SO->FindAttribute(SObj, "AttributePersistentRef"))
848     {
849       SALOMEDS::AttributePersistentRef_var PersRef = SALOMEDS::AttributePersistentRef::_narrow(SObj);
850         CORBA::String_var Val = PersRef->Value();
851         name_len = (hdf_int32) strlen(Val);
852         size[0] = name_len +1 ; 
853         hdf_dataset = new HDFdataset("AttributePersistentRef",hdf_group_sobject,HDF_STRING,size,1);
854         hdf_dataset->CreateOnDisk();
855         hdf_dataset->WriteOnDisk(Val);
856         MESSAGE("attribute persistentref " <<  Val << " wrote on file");
857         hdf_dataset->CloseOnDisk();
858         hdf_dataset=0; //will be deleted by hdf_sco_group destructor
859       }
860   // Attribute  SALOMEDS::Name
861   if(SO->FindAttribute(SObj, "AttributeName"))
862     {
863       SALOMEDS::AttributeName_var NameRef = SALOMEDS::AttributeName::_narrow(SObj);
864         CORBA::String_var Val = NameRef->Value();
865         name_len = (hdf_int32) strlen(Val);
866         size[0] = name_len +1 ; 
867         hdf_dataset = new HDFdataset("AttributeName",hdf_group_sobject,HDF_STRING,size,1);
868         hdf_dataset->CreateOnDisk();
869         hdf_dataset->WriteOnDisk(Val);
870         MESSAGE("attribute name " <<  Val << " wrote on file");
871         hdf_dataset->CloseOnDisk();
872         hdf_dataset=0; //will be deleted by hdf_sco_group destructor
873       }
874   if(SO->FindAttribute(SObj, "AttributeReal"))
875     {
876       char RealVal[25];
877       SALOMEDS::AttributeReal_var RealRef = SALOMEDS::AttributeReal::_narrow(SObj);
878       sprintf(RealVal, "%f", RealRef->Value());
879       name_len = (hdf_int32) strlen(RealVal);
880       size[0] = name_len +1 ; 
881       hdf_dataset = new HDFdataset("AttributeReal",hdf_group_sobject,HDF_STRING,size,1);
882       hdf_dataset->CreateOnDisk();
883       hdf_dataset->WriteOnDisk(RealVal);
884       MESSAGE("attribute Real " <<  RealVal << " wrote on file");
885       hdf_dataset->CloseOnDisk();
886       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
887     }
888   if(SO->FindAttribute(SObj, "AttributeInteger"))
889     {
890       char IntVal[25];
891       SALOMEDS::AttributeInteger_var IntRef = SALOMEDS::AttributeInteger::_narrow(SObj);
892       sprintf(IntVal, "%d", IntRef->Value());
893       name_len = (hdf_int32) strlen(IntVal);
894       size[0] = name_len +1 ; 
895       hdf_dataset = new HDFdataset("AttributeInteger",hdf_group_sobject,HDF_STRING,size,1);
896       hdf_dataset->CreateOnDisk();
897       hdf_dataset->WriteOnDisk(IntVal);
898       MESSAGE("attribute Real " <<  IntVal << " wrote on file");
899       hdf_dataset->CloseOnDisk();
900       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
901     }     
902   
903   if(SO->FindAttribute(SObj, "AttributeSequenceOfReal"))
904     {
905       SALOMEDS::AttributeSequenceOfReal_var RealSeq = SALOMEDS::AttributeSequenceOfReal::_narrow(SObj);
906         size[0] = RealSeq->Length();
907         SALOMEDS::DoubleSeq_var DS = RealSeq->CorbaSequence();
908         hdf_dataset = new HDFdataset("AttributeSequenceOfReal",hdf_group_sobject,HDF_FLOAT64,size,1);
909         hdf_dataset->CreateOnDisk();
910         hdf_float64 *data = new hdf_float64[RealSeq->Length()];
911         for (Standard_Integer i = 0; i < RealSeq->Length(); i++) {
912           MESSAGE("Value =  " << i << " = " << DS[i]  << " wrote on file");
913           data[i] = DS[i];
914         }
915         hdf_dataset->WriteOnDisk(data);
916         //               delete data;
917         hdf_dataset->CloseOnDisk();
918         hdf_dataset=0; //will be deleted by hdf_sco_group destructor
919       }
920   if(SO->FindAttribute(SObj, "AttributeSequenceOfInteger"))
921     {
922       SALOMEDS::AttributeSequenceOfInteger_var IntSeq = SALOMEDS::AttributeSequenceOfInteger::_narrow(SObj);
923         size[0] = IntSeq->Length();
924         SALOMEDS::LongSeq_var LS = IntSeq->CorbaSequence();
925         hdf_dataset = new HDFdataset("AttributeSequenceOfInteger",hdf_group_sobject,HDF_INT32,size,1);
926         hdf_dataset->CreateOnDisk();
927         hdf_int32 *data = new hdf_int32[IntSeq->Length()];
928         for (Standard_Integer i = 0; i < IntSeq->Length(); i++) {
929           MESSAGE("Value =  " << i << " = " << LS[i]  << " wrote on file");
930           data[i] = LS[i];
931         }
932         hdf_dataset->WriteOnDisk(data);
933         hdf_dataset->CloseOnDisk();
934         //               delete data;
935         hdf_dataset=0; //will be deleted by hdf_sco_group destructor
936       }
937     if(SO->FindAttribute(SObj, "AttributeDrawable"))
938     {
939       char IntVal[25];
940       SALOMEDS::AttributeDrawable_var DrRef = SALOMEDS::AttributeDrawable::_narrow(SObj);
941       sprintf(IntVal, "%d", DrRef->IsDrawable());
942       name_len = (hdf_int32) strlen(IntVal);
943       size[0] = name_len +1 ; 
944       hdf_dataset = new HDFdataset("AttributeDrawable",hdf_group_sobject,HDF_STRING,size,1);
945       hdf_dataset->CreateOnDisk();
946       hdf_dataset->WriteOnDisk(IntVal);
947       MESSAGE("attribute Drawable " <<  IntVal << " wrote on file");
948       hdf_dataset->CloseOnDisk();
949       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
950     }     
951   if(SO->FindAttribute(SObj, "AttributeSelectable"))
952     {
953       char IntVal[25];
954       SALOMEDS::AttributeSelectable_var SelRef = SALOMEDS::AttributeSelectable::_narrow(SObj);
955       sprintf(IntVal, "%d", SelRef->IsSelectable());
956       name_len = (hdf_int32) strlen(IntVal);
957       size[0] = name_len +1 ; 
958       hdf_dataset = new HDFdataset("AttributeSelectable",hdf_group_sobject,HDF_STRING,size,1);
959       hdf_dataset->CreateOnDisk();
960       hdf_dataset->WriteOnDisk(IntVal);
961       MESSAGE("attribute Selectable " <<  IntVal << " wrote on file");
962       hdf_dataset->CloseOnDisk();
963       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
964     }     
965   if(SO->FindAttribute(SObj, "AttributeExpandable"))
966     {
967       char IntVal[25];
968       SALOMEDS::AttributeExpandable_var ExRef = SALOMEDS::AttributeExpandable::_narrow(SObj);
969       sprintf(IntVal, "%d", ExRef->IsExpandable());
970       name_len = (hdf_int32) strlen(IntVal);
971       size[0] = name_len +1 ; 
972       hdf_dataset = new HDFdataset("AttributeExpandable",hdf_group_sobject,HDF_STRING,size,1);
973       hdf_dataset->CreateOnDisk();
974       hdf_dataset->WriteOnDisk(IntVal);
975       MESSAGE("attribute Expandable " <<  IntVal << " wrote on file");
976       hdf_dataset->CloseOnDisk();
977       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
978     }     
979   if(SO->FindAttribute(SObj, "AttributeOpened"))
980     {
981       char IntVal[25];
982       SALOMEDS::AttributeOpened_var OpRef = SALOMEDS::AttributeOpened::_narrow(SObj);
983       sprintf(IntVal, "%d", OpRef->IsOpened());
984       name_len = (hdf_int32) strlen(IntVal);
985       size[0] = name_len +1 ; 
986       hdf_dataset = new HDFdataset("AttributeOpened",hdf_group_sobject,HDF_STRING,size,1);
987       hdf_dataset->CreateOnDisk();
988       hdf_dataset->WriteOnDisk(IntVal);
989       MESSAGE("attribute Opened " <<  IntVal << " wrote on file");
990       hdf_dataset->CloseOnDisk();
991       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
992     }     
993   if(SO->FindAttribute(SObj, "AttributeTextColor"))
994     {
995       SALOMEDS::AttributeTextColor_var TextRef = SALOMEDS::AttributeTextColor::_narrow(SObj);
996       size[0] = 3;
997       hdf_float64 data[3];
998       SALOMEDS::Color C = TextRef->TextColor();
999       data[0] = C.R;
1000       data[1] = C.G;
1001       data[2] = C.B;
1002       hdf_dataset = new HDFdataset("AttributeTextColor",hdf_group_sobject,HDF_FLOAT64,size,1);
1003       hdf_dataset->CreateOnDisk();
1004       hdf_dataset->WriteOnDisk(data);
1005       MESSAGE("attribute  AttributeTextColor wrote on file");
1006       hdf_dataset->CloseOnDisk();
1007       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1008     }     
1009     if(SO->FindAttribute(SObj, "AttributeTextHighlightColor"))
1010     {
1011       SALOMEDS::AttributeTextHighlightColor_var TextRef = SALOMEDS::AttributeTextHighlightColor::_narrow(SObj);
1012       size[0] = 3;
1013       hdf_float64 data[3];
1014       SALOMEDS::Color C = TextRef->TextHighlightColor();
1015       data[0] = C.R;
1016       data[1] = C.G;
1017       data[2] = C.B;
1018       hdf_dataset = new HDFdataset("AttributeTextHighlightColor",hdf_group_sobject,HDF_FLOAT64,size,1);
1019       hdf_dataset->CreateOnDisk();
1020       hdf_dataset->WriteOnDisk(data);
1021       MESSAGE("attribute  AttributeTextHighlightColor wrote on file");
1022       hdf_dataset->CloseOnDisk();
1023       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1024     }     
1025   if(SO->FindAttribute(SObj, "AttributePixMap"))
1026     {
1027       SALOMEDS::AttributePixMap_var PMRef = SALOMEDS::AttributePixMap::_narrow(SObj);
1028       if (PMRef->HasPixMap()) {
1029         CORBA::String_var Val = PMRef->GetPixMap();
1030         name_len = (hdf_int32) strlen(Val);
1031         size[0] = name_len +1 ; 
1032         hdf_dataset = new HDFdataset("AttributePixMap",hdf_group_sobject,HDF_STRING,size,1);
1033         hdf_dataset->CreateOnDisk();
1034         hdf_dataset->WriteOnDisk(Val);
1035           MESSAGE("attribute PixMap " <<  Val << " wrote on file");
1036         hdf_dataset->CloseOnDisk();
1037         hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1038       }
1039     }
1040   if(SO->FindAttribute(SObj, "AttributeLocalID"))
1041     {
1042       char IntVal[25];
1043       SALOMEDS::AttributeLocalID_var LIDRef = SALOMEDS::AttributeLocalID::_narrow(SObj);
1044       sprintf(IntVal, "%d", LIDRef->Value());
1045       name_len = (hdf_int32) strlen(IntVal);
1046       size[0] = name_len +1 ; 
1047       hdf_dataset = new HDFdataset("AttributeLocalID",hdf_group_sobject,HDF_STRING,size,1);
1048       hdf_dataset->CreateOnDisk();
1049       hdf_dataset->WriteOnDisk(IntVal);
1050       hdf_dataset->CloseOnDisk();
1051       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1052       MESSAGE("attribute  AttributeLocalID wrote on file");
1053     }     
1054   if(SO->FindAttribute(SObj, "AttributeTableOfInteger"))
1055     {
1056       SALOMEDS::AttributeTableOfInteger_var IntTab = SALOMEDS::AttributeTableOfInteger::_narrow(SObj);
1057       SALOMEDS::TMPFile_var aStream = IntTab->SaveToFile();
1058       
1059       hdf_size aHDFSize[1];
1060       aHDFSize[0] = aStream->length();
1061       
1062       HDFdataset *hdf_dataset = new HDFdataset("AttributeTableOfInteger",hdf_group_sobject, HDF_STRING, aHDFSize, 1);
1063       hdf_dataset->CreateOnDisk();
1064       hdf_dataset->WriteOnDisk((unsigned char*) &aStream[0]);  //Save the stream in the HDF file
1065       hdf_dataset->CloseOnDisk();
1066       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1067       
1068       MESSAGE("attribute  AttributeTableOfInteger wrote on file");
1069     }
1070   if(SO->FindAttribute(SObj, "AttributeTableOfReal"))
1071     {
1072       SALOMEDS::AttributeTableOfReal_var RealTab = SALOMEDS::AttributeTableOfReal::_narrow(SObj);
1073       SALOMEDS::TMPFile_var aStream = RealTab->SaveToFile();
1074       
1075       hdf_size aHDFSize[1];
1076       aHDFSize[0] = aStream->length();
1077       
1078       HDFdataset *hdf_dataset = new HDFdataset("AttributeTableOfReal",hdf_group_sobject, HDF_STRING, aHDFSize, 1);
1079       hdf_dataset->CreateOnDisk();
1080       hdf_dataset->WriteOnDisk((unsigned char*) &aStream[0]);  //Save the stream in the HDF file
1081       hdf_dataset->CloseOnDisk();
1082       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1083
1084       MESSAGE("attribute  AttributeTableOfReal wrote on file")
1085     }
1086   if(SO->FindAttribute(SObj, "AttributeTableOfString"))
1087     {
1088       SALOMEDS::AttributeTableOfString_var StrTab = SALOMEDS::AttributeTableOfString::_narrow(SObj);
1089       SALOMEDS::TMPFile_var aStream = StrTab->SaveToFile();
1090       
1091       hdf_size aHDFSize[1];
1092       aHDFSize[0] = aStream->length();
1093       
1094       HDFdataset *hdf_dataset = new HDFdataset("AttributeTableOfString",hdf_group_sobject, HDF_STRING, aHDFSize, 1);
1095       hdf_dataset->CreateOnDisk();
1096       hdf_dataset->WriteOnDisk((unsigned char*) &aStream[0]);  //Save the stream in the HDF file
1097       hdf_dataset->CloseOnDisk();
1098       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1099
1100       MESSAGE("attribute  AttributeTableOfString wrote on file")
1101     }
1102   if(SO->FindAttribute(SObj, "AttributePythonObject"))
1103     {
1104       SALOMEDS::AttributePythonObject_var anObj = SALOMEDS::AttributePythonObject::_narrow(SObj);
1105       char* aSeq = CORBA::string_dup(anObj->GetObject());
1106       int aLen = strlen(aSeq);
1107       char* aString = new char[aLen+2];
1108       aString[0] = anObj->IsScript()?'s':'n';
1109       for(int i = 0; i < aLen; i++) aString[i+1] = aSeq[i];
1110       aString[aLen+1] = 0;
1111       size[0] = aLen+2 ; 
1112       hdf_dataset = new HDFdataset("AttributePythonObject",hdf_group_sobject,HDF_STRING,size,1);
1113       hdf_dataset->CreateOnDisk();
1114       hdf_dataset->WriteOnDisk(aString);
1115       hdf_dataset->CloseOnDisk();
1116       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1117       MESSAGE("attribute  AttributePythonObject wrote on file");
1118     }     
1119
1120 // Reference
1121   SALOMEDS::SObject_var RefSO;
1122   if(SO->ReferencedObject(RefSO))
1123     {
1124       CORBA::String_var attribute_reference = strdup(RefSO->GetID());
1125       name_len = (hdf_int32) strlen(attribute_reference);
1126       size[0] = name_len +1 ; 
1127       hdf_dataset = new HDFdataset("Reference",hdf_group_sobject,HDF_STRING,size,1);
1128       hdf_dataset->CreateOnDisk();
1129       hdf_dataset->WriteOnDisk(attribute_reference);
1130       MESSAGE("attribute reference " <<  attribute_reference << " wrote on file");
1131       hdf_dataset->CloseOnDisk();
1132       hdf_dataset =0; // will be deleted by father hdf object destructor
1133     }
1134
1135 // TreeNodeAttributes with not constant GUID
1136   SALOMEDS::ListOfAttributes_var anAttrList = SO->GetAllAttributes();
1137   int anIndex, aLength = anAttrList->length();
1138   for(anIndex = 0; anIndex<aLength; anIndex++) {
1139     SALOMEDS::AttributeUserID_var UAttr = SALOMEDS::AttributeUserID::_narrow(anAttrList[anIndex]);
1140     if (!UAttr->_is_nil()) {
1141       char* Val = UAttr->Value();
1142       name_len = (hdf_int32) strlen(Val);
1143       size[0] = name_len + 1;
1144       char* aDataSetName = new char[60];
1145       sprintf(aDataSetName, "AttributeUserID_%s",Val);
1146       hdf_dataset = new HDFdataset(aDataSetName,hdf_group_sobject,HDF_STRING,size,1);
1147       hdf_dataset->CreateOnDisk();
1148       hdf_dataset->WriteOnDisk(Val);
1149       MESSAGE("attribute UesrID " <<  Val << " wrote on file");
1150       hdf_dataset->CloseOnDisk();
1151       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1152       delete(aDataSetName);
1153       continue;
1154     }
1155
1156     SALOMEDS::AttributeTreeNode_var TNRef = SALOMEDS::AttributeTreeNode::_narrow(anAttrList[anIndex]);
1157     if (!TNRef->_is_nil()) {
1158       hdf_size TNsize[2];
1159       int maxSize,index;
1160       CORBA::String_var Val[5];
1161       
1162       if (TNRef->HasFather()) Val[0] = TNRef->GetFather()->Label(); else Val[0] = "\0";
1163       maxSize = strlen(Val[0]);
1164       if (TNRef->HasPrevious()) Val[1] = TNRef->GetPrevious()->Label(); else Val[1] = "\0";
1165       maxSize = Max(maxSize,strlen(Val[1]));
1166       if (TNRef->HasNext()) Val[2] = TNRef->GetNext()->Label(); else Val[2] = "\0";
1167       maxSize = Max(maxSize,strlen(Val[2]));
1168       if (TNRef->HasFirst()) Val[3] = TNRef->GetFirst()->Label(); else Val[3] = "\0";
1169       maxSize = Max(maxSize,strlen(Val[3]));
1170       Val[4] = TNRef->GetTreeID();
1171       maxSize = Max(maxSize,strlen(Val[4]));
1172       
1173       TNsize[0]=5;
1174       TNsize[1]=maxSize+1;
1175       char Data[5][maxSize+1];
1176       for(index=0;index<5;index++) {
1177         strcpy(Data[index],Val[index]);
1178         for(int a = strlen(Data[index]) + 1; a < maxSize; a++) Data[index][a] = ' '; // mpv: for ASCII format
1179       }
1180       
1181       char* aDataSetName = new char[60];
1182       sprintf(aDataSetName, "AttributeTreeNodeGUID%s",TNRef->GetTreeID());
1183       hdf_dataset = new HDFdataset(aDataSetName,hdf_group_sobject,HDF_STRING,TNsize,2);
1184       hdf_dataset->CreateOnDisk();
1185       hdf_dataset->WriteOnDisk(Data);
1186       hdf_dataset->CloseOnDisk();
1187       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1188       MESSAGE("attribute AttributeTreeNode with various GUID wrote on file:");
1189       MESSAGE(aDataSetName);
1190       delete(aDataSetName);
1191 //       for(int i=0;i<5;i++)
1192 //      delete[] Data[i];
1193 //       delete[] Data;
1194     }
1195   }
1196 }
1197
1198 //=============================================================================
1199 /*! Function : _SaveProperties
1200  *  Purpose  : save the study properties in HDF file
1201  */
1202 //============================================================================
1203 void SALOMEDS_StudyManager_i::_SaveProperties(SALOMEDS::Study_ptr aStudy, HDFgroup *hdf_group) {
1204   HDFdataset *hdf_dataset = 0;
1205   hdf_size size[1];
1206   hdf_int32 name_len;
1207
1208   // add modifications list (user and date of save)
1209   SALOMEDS::AttributeStudyProperties_ptr aProp = aStudy->GetProperties();
1210   SALOMEDS::StudyBuilder_var SB= aStudy->NewBuilder();
1211 //    SB->NewCommand();
1212   int aLocked = aProp->IsLocked();
1213   if (aLocked) aProp->SetLocked(Standard_False);
1214   OSD_Process aProcess;
1215   Quantity_Date aDate = aProcess.SystemDate();
1216   aProp->SetModification(aProcess.UserName().ToCString(),
1217                          CORBA::Long(aDate.Minute()), CORBA::Long(aDate.Hour()), CORBA::Long(aDate.Day()),
1218                          CORBA::Long(aDate.Month()), CORBA::Long(aDate.Year()));
1219   if (aLocked) aProp->SetLocked(Standard_True);
1220 //    SB->CommitCommand();
1221   
1222
1223   SALOMEDS::StringSeq_var aNames;
1224   SALOMEDS::LongSeq_var aMinutes, aHours, aDays, aMonths, aYears;
1225   aProp->GetModificationsList(aNames , aMinutes ,aHours, aDays, aMonths, aYears, true);
1226   int aLength, anIndex;
1227   for(aLength = 0, anIndex = aNames->length() - 1; anIndex >= 0; anIndex--) aLength += strlen(aNames[anIndex]) + 1;
1228
1229   // string length: 1 byte = locked flag, 1 byte = modified flag, (12 + name length + 1) for each name and date, "zero" byte
1230   char* aProperty = new char[3 + aLength + 12 * aNames->length()];
1231
1232   sprintf(aProperty,"%c%c",
1233           (strlen(aProp->GetCreationMode()) != 0)?aProp->GetCreationMode()[0]:'0',
1234           (aProp->IsLocked())?'l':'u');
1235
1236   aLength = aNames->length();
1237   int a = 2;
1238   for(anIndex = 0; anIndex  < aLength; anIndex++) {
1239     sprintf(&(aProperty[a]),"%2d%2d%2d%2d%4d%s",
1240             (int)(aMinutes[anIndex]),
1241             (int)(aHours[anIndex]),
1242             (int)(aDays[anIndex]),
1243             (int)(aMonths[anIndex]),
1244             (int)(aYears[anIndex]),
1245             (char*)aNames[anIndex]);
1246     a = strlen(aProperty);
1247     aProperty[a++] = 1;
1248   }
1249   aProperty[a] = 0;
1250
1251   name_len = (hdf_int32) a;
1252 //    MESSAGE("*** Property: "<<aProperty);
1253   size[0] = name_len + 1 ; 
1254   hdf_dataset = new HDFdataset("AttributeStudyProperties",hdf_group,HDF_STRING,size,1);
1255   hdf_dataset->CreateOnDisk();
1256   hdf_dataset->WriteOnDisk(aProperty);
1257   MESSAGE("attribute StudyProperties " <<  aProperty << " wrote on file");
1258   hdf_dataset->CloseOnDisk();
1259   hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1260   delete(aProperty);
1261   aProp->SetModified(0);
1262 }
1263
1264 //=============================================================================
1265 /*! Function : _SaveAs
1266  *  Purpose  : save the study in HDF file
1267  */
1268 //============================================================================
1269 void SALOMEDS_StudyManager_i::_SaveAs(const char* aUrl, 
1270                                       SALOMEDS::Study_ptr aStudy,
1271                                       CORBA::Boolean theMultiFile,
1272                                       CORBA::Boolean theASCII)
1273 {
1274   // HDF File will be composed of differents part :
1275   // * For each ComponentDataType, all data created by the component
1276   //   Informations in data group hdf_group_datacomponent
1277   // * Study Structure -> Exactly what is contained in OCAF document
1278   //   Informations in data group hdf_group_study_structure
1279
1280   HDFfile *hdf_file=0;         
1281   HDFgroup *hdf_group_study_structure =0;
1282   HDFgroup *hdf_sco_group =0;
1283   HDFgroup *hdf_sco_group2 =0;
1284
1285   HDFgroup *hdf_group_datacomponent =0;
1286   HDFdataset *hdf_dataset =0;
1287   HDFattribute *hdf_attribute=0;
1288   hdf_size size[1];
1289   hdf_int32 name_len = 0;
1290   char *component_name = 0;
1291   char *attribute_name = 0;
1292   char *attribute_comment = 0;
1293   char *attribute_persistentref = 0;
1294
1295   int aLocked = aStudy->GetProperties()->IsLocked();
1296   if (aLocked) aStudy->GetProperties()->SetLocked(false);
1297
1298   SALOMEDS::StudyBuilder_var SB= aStudy->NewBuilder();
1299
1300   ASSERT(!CORBA::is_nil(aStudy));
1301   try
1302     {
1303       // mpv 15.12.2003: for saving components we have to load all data from all modules
1304
1305       SALOMEDS::SComponentIterator_var itcomponent1 = aStudy->NewComponentIterator();
1306       for (; itcomponent1->More(); itcomponent1->Next())
1307         {
1308           SALOMEDS::SComponent_var sco = itcomponent1->Value();
1309           // if there is an associated Engine call its method for saving
1310           CORBA::String_var IOREngine;
1311           try {
1312             
1313             if (!sco->ComponentIOR(IOREngine)) {
1314               SALOMEDS::GenericAttribute_var aGeneric;
1315               SALOMEDS::AttributeName_var aName;
1316               if(sco->FindAttribute(aGeneric, "AttributeName"))
1317                 aName = SALOMEDS::AttributeName::_narrow(aGeneric);
1318
1319               if (!aName->_is_nil()) {
1320                 
1321                 CORBA::String_var aCompType = aName->Value();
1322
1323                 
1324                 CORBA::String_var aFactoryType;
1325                 if (strcmp(aCompType, "SUPERV") == 0) aFactoryType = "SuperVisionContainer";
1326                 else aFactoryType = "FactoryServer";
1327                 
1328                 Engines::Component_var aComp =
1329                   SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component(aFactoryType, aCompType);
1330                 
1331                 if (aComp->_is_nil()) {
1332                   Engines::Component_var aComp =
1333                     SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component("FactoryServerPy", aCompType);
1334                 }
1335                 
1336                 if (!aComp->_is_nil()) {
1337                   SALOMEDS::Driver_var aDriver = SALOMEDS::Driver::_narrow(aComp);
1338                   if (!CORBA::is_nil(aDriver)) {
1339                     SB->LoadWith(sco, aDriver);
1340                   }
1341                 }
1342               }
1343             }
1344           } catch(...) {
1345             MESSAGE("Can not restore information to resave it");
1346             return;
1347           }
1348         }
1349
1350
1351
1352       CORBA::String_var anOldName = aStudy->Name();
1353       aStudy->URL(aUrl);
1354
1355       // To change for Save 
1356       // Do not have to do a new file but just a Open??? Rewrite all informations after erasing evrything??
1357       hdf_file = new HDFfile((char *)aUrl);
1358       hdf_file->CreateOnDisk();
1359       MESSAGE("File " << aUrl << " created");
1360
1361       //-----------------------------------------------------------------------
1362       // 1 - Create a groupe for each SComponent and Update the PersistanceRef
1363       //-----------------------------------------------------------------------
1364       hdf_group_datacomponent = new HDFgroup("DATACOMPONENT",hdf_file);
1365       hdf_group_datacomponent->CreateOnDisk();
1366
1367       SALOMEDS::SComponentIterator_var itcomponent = aStudy->NewComponentIterator();
1368       
1369       //SRN: Added 17 Nov, 2003
1370       SALOMEDS::SObject_var anAutoSaveSO = aStudy->FindObjectID(AUTO_SAVE_TAG);
1371       //SRN: End
1372
1373       for (; itcomponent->More(); itcomponent->Next())
1374         {
1375           SALOMEDS::SComponent_var sco = itcomponent->Value();
1376           
1377           CORBA::String_var scoid = sco->GetID();
1378           hdf_sco_group = new HDFgroup(scoid,hdf_group_datacomponent);
1379           hdf_sco_group->CreateOnDisk();
1380
1381           CORBA::String_var componentDataType = sco->ComponentDataType();
1382           MESSAGE ( "Look for  an engine for data type :"<< componentDataType);
1383
1384           //SRN: Added 17 Nov 2003: If there is a specified attribute, the component peforms a special save       
1385           if(!CORBA::is_nil(anAutoSaveSO) && SB->IsGUID(sco, AUTO_SAVE_GUID)) {     
1386        
1387             SALOMEDS::GenericAttribute_var aGeneric;
1388             SALOMEDS::AttributeTableOfString_var aTable;
1389             if(anAutoSaveSO->FindAttribute(aGeneric, "AttributeTableOfString")) {
1390               aTable = SALOMEDS::AttributeTableOfString::_narrow(aGeneric);
1391               Standard_Integer nbRows = aTable->GetNbRows(), k, aTimeOut = 0;
1392               if(nbRows > 0 && aTable->GetNbColumns() > 1) {    
1393
1394                 SALOMEDS::StringSeq_var aRow;
1395                 for(k=1; k<=nbRows; k++) {
1396                   aRow = aTable->GetRow(k);
1397                   if (strcmp(aRow[0], componentDataType) == 0) {
1398                     CORBA::String_var anEntry = CORBA::string_dup(aRow[1]);
1399                     SALOMEDS::SObject_var aCompSpecificSO = aStudy->FindObjectID(anEntry);
1400                     if(!CORBA::is_nil(aCompSpecificSO)) {
1401                       SALOMEDS::AttributeInteger_var anInteger;
1402                       if(aCompSpecificSO->FindAttribute(aGeneric, "AttributeInteger")) {
1403                         anInteger = SALOMEDS::AttributeInteger::_narrow(aGeneric);
1404                         anInteger->SetValue(-1);
1405                         while(anInteger->Value() < 0) { sleep(2); if(++aTimeOut > AUTO_SAVE_TIME_OUT_IN_SECONDS) break; }
1406                       }  // if(aCompSpecificSO->FindAttribute(anInteger, "AttributeInteger"))
1407                     }  // if(!CORBA::is_nil(aCompSpecificSO)) 
1408                   }  // if (strcmp(aRow[0], componentDataType) == 0)
1409                 }  // for
1410
1411               }  // if(nbRows > 0 && aTable->GetNbColumns() > 1)
1412
1413             }  // if(anAutoSaveSO->FindAttribute(aTable, "AttributeTableOfString")
1414
1415           }  // if(SB->IsGUID(AUTO_SAVE_GUID)
1416
1417           //SRN: End
1418
1419           CORBA::String_var IOREngine;
1420           if (sco->ComponentIOR(IOREngine))
1421             {
1422               // we have found the associated engine to write the data 
1423               MESSAGE ( "We have found an engine for data type :"<< componentDataType);
1424               CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1425               SALOMEDS::Driver_var Engine = SALOMEDS::Driver::_narrow(obj) ;
1426               
1427               if (!CORBA::is_nil(Engine))
1428                 {
1429                   MESSAGE ( "Save the data of type:"<< componentDataType);
1430                   MESSAGE("Engine :"<<Engine->ComponentDataType());
1431
1432                   SALOMEDS::TMPFile_var aStream;
1433
1434                   if (theASCII) aStream = Engine->SaveASCII(sco,SALOMEDS_Tool::GetDirFromPath(aUrl),theMultiFile);
1435                   else aStream = Engine->Save(sco,SALOMEDS_Tool::GetDirFromPath(aUrl),theMultiFile);
1436
1437                   HDFdataset *hdf_dataset;
1438                   hdf_size aHDFSize[1];
1439                   if(aStream->length() > 0) {  //The component saved some auxiliary files, then put them into HDF file 
1440
1441                     aHDFSize[0] = aStream->length();
1442                       
1443                     HDFdataset *hdf_dataset = new HDFdataset("FILE_STREAM", hdf_sco_group, HDF_STRING, aHDFSize, 1);
1444                     hdf_dataset->CreateOnDisk();
1445                     hdf_dataset->WriteOnDisk((unsigned char*) &aStream[0]);  //Save the stream in the HDF file
1446                     hdf_dataset->CloseOnDisk();
1447                   }
1448                   // store multifile state
1449                   aHDFSize[0] = 2;
1450                   hdf_dataset = new HDFdataset("MULTIFILE_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
1451                   hdf_dataset->CreateOnDisk();
1452                   hdf_dataset->WriteOnDisk((void*)(theMultiFile?"M":"S")); // save: multi or single
1453                   hdf_dataset->CloseOnDisk();
1454                   hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor                
1455
1456                   // store ASCII state
1457                   aHDFSize[0] = 2;
1458                   hdf_dataset = new HDFdataset("ASCII_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
1459                   hdf_dataset->CreateOnDisk();
1460                   hdf_dataset->WriteOnDisk((void*)(theASCII?"A":"B")); // save: ASCII or BINARY
1461                   hdf_dataset->CloseOnDisk();
1462                   hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor                
1463
1464                   Translate_IOR_to_persistentID (aStudy,SB,sco,Engine,theMultiFile, theASCII);
1465                   MESSAGE("After Translate_IOR_to_persistentID");
1466                   
1467                   // Creation of the persistance reference  attribute
1468                 }
1469             }
1470           hdf_sco_group->CloseOnDisk();
1471           hdf_sco_group=0; // will be deleted by hdf_group_datacomponent destructor
1472         }
1473       hdf_group_datacomponent->CloseOnDisk();
1474       hdf_group_datacomponent =0;  // will be deleted by hdf_file destructor
1475
1476
1477       //-----------------------------------------------------------------------
1478       //3 - Write the Study Structure
1479       //-----------------------------------------------------------------------
1480       hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
1481       hdf_group_study_structure->CreateOnDisk();
1482
1483       // save component attributes
1484       SALOMEDS::SComponentIterator_var itcomp = aStudy->NewComponentIterator();
1485       for (; itcomp->More(); itcomp->Next()) 
1486         {
1487           SALOMEDS::SComponent_var SC = itcomp->Value();
1488           
1489           CORBA::String_var scid = SC->GetID();
1490           hdf_sco_group2 = new HDFgroup(scid,hdf_group_study_structure);
1491           hdf_sco_group2->CreateOnDisk();
1492           SaveAttributes(SC, hdf_sco_group2);
1493           // ComponentDataType treatment
1494           component_name = SC->ComponentDataType();
1495           MESSAGE("Component data type " << component_name << " treated");
1496           
1497           name_len = (hdf_int32) strlen(component_name);
1498           size[0] = name_len +1 ; 
1499           hdf_dataset = new HDFdataset("COMPONENTDATATYPE",hdf_sco_group2,HDF_STRING,size,1);
1500           hdf_dataset->CreateOnDisk();
1501           hdf_dataset->WriteOnDisk(component_name);
1502           MESSAGE("component name " <<  component_name << " wrote on file");
1503           hdf_dataset->CloseOnDisk();
1504           hdf_dataset=0; //will be deleted by hdf_sco_group destructor
1505           _SaveObject(aStudy, SC, hdf_sco_group2);
1506           hdf_sco_group2->CloseOnDisk();
1507           hdf_sco_group2=0; // will be deleted by hdf_group_study_structure destructor
1508           CORBA::string_free(component_name);       
1509         }
1510       //-----------------------------------------------------------------------
1511       //4 - Write the Study UseCases Structure
1512       //-----------------------------------------------------------------------
1513       SALOMEDS::SObject_var aSO = aStudy->FindObjectID(USE_CASE_LABEL_ID);
1514       if (!aSO->_is_nil()) {
1515         HDFgroup *hdf_soo_group = new HDFgroup(USE_CASE_LABEL_ID,hdf_group_study_structure);
1516         hdf_soo_group->CreateOnDisk();
1517         SaveAttributes(aSO, hdf_soo_group);
1518         _SaveObject(aStudy, aSO, hdf_soo_group);
1519         MESSAGE("Use cases data structure writed");
1520         hdf_soo_group->CloseOnDisk();
1521         hdf_soo_group=0; // will be deleted by hdf_group_study_structure destructor
1522       }
1523
1524       if (aLocked) aStudy->GetProperties()->SetLocked(true);
1525       //-----------------------------------------------------------------------
1526       //5 - Write the Study Properties
1527       //-----------------------------------------------------------------------
1528       name_len = (hdf_int32) strlen(aStudy->Name());
1529       size[0] = name_len +1 ; 
1530       hdf_dataset = new HDFdataset("STUDY_NAME",hdf_group_study_structure,HDF_STRING,size,1);
1531       hdf_dataset->CreateOnDisk();
1532       CORBA::String_var studid = aStudy->Name();
1533       hdf_dataset->WriteOnDisk(studid);
1534       MESSAGE("study name " << studid << " wrote on file");
1535       hdf_dataset->CloseOnDisk();
1536       hdf_dataset=0; // will be deleted by hdf_group_study_structure destructor
1537
1538       _SaveProperties(aStudy, hdf_group_study_structure);
1539
1540       hdf_group_study_structure->CloseOnDisk();
1541       hdf_file->CloseOnDisk();
1542
1543       _name_service->Change_Directory("/Study");
1544       _name_service->Destroy_Name(anOldName);
1545       _name_service->Register(aStudy, aStudy->Name());
1546
1547       aStudy->IsSaved(true);
1548       hdf_group_study_structure =0; // will be deleted by hdf_file destructor
1549       delete hdf_file; // recursively deletes all hdf objects...
1550     }
1551   catch (HDFexception)
1552     {
1553       MESSAGE( "HDFexception ! " )
1554     }
1555   if (theASCII) { // save file in ASCII format
1556     HDFascii::ConvertFromHDFToASCII(aUrl, true);
1557   }
1558 }
1559
1560 //============================================================================
1561 /*! Function : _SaveObject
1562  *  Purpose  :
1563  */
1564 //============================================================================
1565 void SALOMEDS_StudyManager_i::_SaveObject(SALOMEDS::Study_ptr aStudy, 
1566                                           SALOMEDS::SObject_ptr SC, 
1567                                           HDFgroup *hdf_group_datatype)
1568 {
1569   // Write in group hdf_group_datatype all informations of SObject SC
1570   // Iterative function to parse all SObjects under a SComponent
1571   SALOMEDS::SObject_var RefSO;
1572   HDFgroup *hdf_group_sobject = 0;
1573   HDFdataset *hdf_dataset = 0;
1574   hdf_size size[1];
1575   hdf_int32 name_len = 0;
1576
1577   SALOMEDS::ChildIterator_var itchild = aStudy->NewChildIterator(SC);
1578   for (; itchild->More(); itchild->Next()) 
1579     {
1580       SALOMEDS::SObject_var SO = itchild->Value();
1581
1582       // mpv: don't save empty labels
1583       if (SO->GetAllAttributes()->length() == 0) {
1584         SALOMEDS::ChildIterator_var subchild = aStudy->NewChildIterator(SC);
1585         if (!subchild->More()) {
1586           continue;
1587         }
1588         subchild->InitEx(true);
1589         bool anEmpty = true;
1590         for (; subchild->More() && anEmpty; subchild->Next()) 
1591           if (subchild->Value()->GetAllAttributes()->length() != 0) anEmpty = false;
1592         if (anEmpty) {
1593           continue;
1594         }
1595       }
1596
1597       CORBA::String_var scoid = strdup(SO->GetID());
1598       hdf_group_sobject = new HDFgroup(scoid,hdf_group_datatype);
1599       hdf_group_sobject->CreateOnDisk();
1600       SaveAttributes(SO, hdf_group_sobject);
1601       _SaveObject(aStudy,SO, hdf_group_sobject);
1602       hdf_group_sobject->CloseOnDisk();
1603       hdf_group_sobject =0; // will be deleted by father hdf object destructor
1604
1605     }
1606 }
1607
1608 //============================================================================
1609 /*! Function : _SubstituteSlash
1610  *  Purpose  :
1611  */
1612 //============================================================================
1613
1614 const char *SALOMEDS_StudyManager_i::_SubstituteSlash(const char *aUrl)
1615 {
1616   ASSERT(1==0);
1617   TCollection_ExtendedString theUrl(CORBA::string_dup(aUrl));
1618   Standard_ExtCharacter val1 = ToExtCharacter('/');
1619   Standard_ExtCharacter val2 = ToExtCharacter(':');
1620   theUrl.ChangeAll(val1,val2);
1621   TCollection_AsciiString ch(theUrl);
1622   return strdup(ch.ToCString());
1623 }
1624
1625 //============================================================================
1626 /*! Function : CanCopy
1627  *  Purpose  : 
1628  */
1629 //============================================================================
1630 CORBA::Boolean SALOMEDS_StudyManager_i::CanCopy(SALOMEDS::SObject_ptr theObject) {
1631   SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1632   if (aComponent->_is_nil()) return false;
1633   if (aComponent == theObject) return false;
1634
1635   CORBA::String_var IOREngine;
1636   if (!aComponent->ComponentIOR(IOREngine)) return false;
1637
1638   CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1639   SALOMEDS::Driver_var Engine = SALOMEDS::Driver::_narrow(obj) ;
1640   if (CORBA::is_nil(Engine)) return false;
1641   Standard_Boolean a = Engine->CanCopy(theObject);
1642   return a;
1643 }
1644
1645 //============================================================================
1646 /*! Function : GetDocumentOfStudy
1647  *  Purpose  : 
1648  */
1649 //============================================================================
1650 Handle(TDocStd_Document) SALOMEDS_StudyManager_i::GetDocumentOfStudy(SALOMEDS::Study_ptr theStudy) {
1651   int a;
1652   int aNbDocs = _OCAFApp->NbDocuments(); 
1653   Handle(TDocStd_Document) aDocument;  
1654   for(a = 1; a <= aNbDocs ; a++) {
1655     _OCAFApp->GetDocument(a, aDocument);
1656     if (!aDocument.IsNull()) {
1657       SALOMEDS_SObject_i *  aSOServant = new SALOMEDS_SObject_i (aDocument->Main(),_orb);
1658       SALOMEDS::SObject_var aSO = SALOMEDS::SObject::_narrow(aSOServant->_this()); 
1659       SALOMEDS::Study_var aStudy = aSO->GetStudy();
1660       if(CORBA::is_nil(aStudy)) continue;  //The clipboard document ( hopefully :) )
1661       if (aStudy->StudyId() == theStudy->StudyId()) break;
1662       aDocument.Nullify();
1663     }
1664   }
1665
1666   return aDocument;
1667 }
1668
1669 //============================================================================
1670 /*! Function : CopyLabel
1671  *  Purpose  : 
1672  */
1673 //============================================================================
1674 void SALOMEDS_StudyManager_i::CopyLabel(const SALOMEDS::Study_ptr theSourceStudy,
1675                                         const SALOMEDS::Driver_ptr theEngine,
1676                                         const Standard_Integer theSourceStartDepth,
1677                                         const TDF_Label& theSource,
1678                                         const TDF_Label& theDestinationMain) {
1679   int a;
1680   TDF_Label aTargetLabel = theDestinationMain;
1681   TDF_Label aAuxTargetLabel = theDestinationMain.Father().FindChild(2);
1682   for(a = theSource.Depth() - theSourceStartDepth; a > 0 ; a--) {
1683     TDF_Label aSourceLabel = theSource;
1684     for(int aNbFather = 1; aNbFather < a; aNbFather++) aSourceLabel = aSourceLabel.Father();
1685     aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
1686     aAuxTargetLabel = aAuxTargetLabel.FindChild(aSourceLabel.Tag());
1687   }
1688   // iterate attributes
1689   TDF_AttributeIterator anAttrIterator(theSource);
1690   Handle(TDF_RelocationTable) aRT = new TDF_RelocationTable();
1691   for(; anAttrIterator.More(); anAttrIterator.Next()) {
1692     Handle(TDF_Attribute) anAttr = anAttrIterator.Value();
1693     if (!Handle(TDataStd_TreeNode)::DownCast(anAttr).IsNull()) continue; // never copy tree node attribute
1694     if (!Handle(SALOMEDS_TargetAttribute)::DownCast(anAttr).IsNull()) continue; // and target attribute
1695     
1696     if (!Handle(TDF_Reference)::DownCast(anAttr).IsNull()) { // reference copied as Comment in auxiliary tree
1697       TDF_Label aReferenced = Handle(TDF_Reference)::DownCast(anAttr)->Get();
1698       TCollection_AsciiString anEntry;
1699       TDF_Tool::Entry(aReferenced, anEntry);
1700       // store the value of name attribute of referenced label
1701       Handle(TDataStd_Name) aNameAttribute;
1702       if (aReferenced.FindAttribute(TDataStd_Name::GetID(), aNameAttribute)) {
1703         anEntry += " ";
1704         anEntry += aNameAttribute->Get();
1705       }
1706       TDataStd_Comment::Set(aAuxTargetLabel, TCollection_ExtendedString(anEntry));
1707       continue;
1708     }
1709     
1710     if (!Handle(SALOMEDS_IORAttribute)::DownCast(anAttr).IsNull()) { // IOR => ID and TMPFile of Engine
1711       TCollection_AsciiString anEntry;
1712       TDF_Tool::Entry(theSource, anEntry);
1713       SALOMEDS::SObject_var aSO = theSourceStudy->FindObjectID(strdup(anEntry.ToCString()));
1714 //        if (theEngine->CanCopy(aSO)) {
1715         CORBA::Long anObjID;
1716 //      TCollection_ExtendedString aResStr(strdup((char*)(theEngine->CopyFrom(aSO, anObjID))));
1717           SALOMEDS::TMPFile_var aStream = theEngine->CopyFrom(aSO, anObjID);
1718           int aLen = aStream->length();
1719           TCollection_ExtendedString aResStr("");
1720           for(a = 0; a < aLen; a++) {
1721             aResStr += TCollection_ExtendedString(ToExtCharacter((Standard_Character)aStream[a]));
1722           }
1723           TDataStd_Integer::Set(aAuxTargetLabel, anObjID);
1724           TDataStd_Name::Set(aAuxTargetLabel, aResStr);
1725 //        }
1726       continue;
1727     }
1728     Handle(TDF_Attribute) aNewAttribute = anAttr->NewEmpty();
1729     aTargetLabel.AddAttribute(aNewAttribute);
1730     anAttr->Paste(aNewAttribute, aRT);
1731 //      aRT->SetRelocation(anAttr, aNewAttribute);
1732   }
1733 }
1734
1735 //============================================================================
1736 /*! Function : Copy
1737  *  Purpose  :
1738  */
1739 //============================================================================
1740 CORBA::Boolean SALOMEDS_StudyManager_i::Copy(SALOMEDS::SObject_ptr theObject) {
1741   // adoptation for alliances datamodel copy: without IOR attributes !!!
1742   bool aStructureOnly; // copy only SObjects and attributes without component help
1743   SALOMEDS::GenericAttribute_var anAttribute;
1744   aStructureOnly = !theObject->FindAttribute(anAttribute, "AttributeIOR");
1745
1746   // get component-engine
1747   SALOMEDS::Study_var aStudy = theObject->GetStudy();
1748
1749   SALOMEDS::Driver_var Engine;
1750   if (!aStructureOnly) {
1751     SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1752     CORBA::String_var IOREngine;
1753     if (!aComponent->ComponentIOR(IOREngine)) return false;
1754
1755     CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1756     Engine = SALOMEDS::Driver::_narrow(obj) ;
1757   }
1758   // CAF document of current study usage
1759   Handle(TDocStd_Document) aDocument = GetDocumentOfStudy(aStudy);
1760   if (aDocument.IsNull()) return false;
1761   // create new document for clipboard
1762   Handle(TDocStd_Document) aTargetDocument;
1763   _OCAFApp->NewDocument("SALOME_STUDY", aTargetDocument);
1764   // set component data type to the name attribute of root label
1765   if (!aStructureOnly) {
1766     TDataStd_Comment::Set(aTargetDocument->Main().Root(),
1767                           TCollection_ExtendedString(strdup(Engine->ComponentDataType())));
1768   }
1769   // set to the Root label integer attribute: study id
1770   TDataStd_Integer::Set(aTargetDocument->Main().Root(), aStudy->StudyId());
1771   // iterate all theObject's label children
1772   TDF_Label aStartLabel;
1773   char* aStartID = strdup(theObject->GetID());
1774   TDF_Tool::Label(aDocument->GetData(), aStartID, aStartLabel);
1775   Standard_Integer aSourceStartDepth = aStartLabel.Depth();
1776   
1777   // copy main source label
1778   CopyLabel(aStudy, Engine, aSourceStartDepth, aStartLabel, aTargetDocument->Main());
1779
1780   // copy all subchildren of the main source label (all levels)
1781   TDF_ChildIterator anIterator(aStartLabel, Standard_True);
1782   for(; anIterator.More(); anIterator.Next()) {
1783     CopyLabel(aStudy, Engine, aSourceStartDepth, anIterator.Value(), aTargetDocument->Main());
1784   }
1785   // done: free old clipboard document and 
1786   if (!_clipboard.IsNull()) {
1787 //      Handle(TDocStd_Owner) anOwner;
1788 //      if (_clipboard->Main().Root().FindAttribute(TDocStd_Owner::GetID(), anOwner)) {
1789 //        Handle(TDocStd_Document) anEmptyDoc;
1790 //        anOwner->SetDocument(anEmptyDoc);
1791 //      }
1792     _OCAFApp->Close(_clipboard);
1793   }
1794   _clipboard = aTargetDocument;
1795
1796   return true;
1797 }
1798 //============================================================================
1799 /*! Function : CanPaste
1800  *  Purpose  :
1801  */
1802 //============================================================================
1803 CORBA::Boolean SALOMEDS_StudyManager_i::CanPaste(SALOMEDS::SObject_ptr theObject) {
1804   if (_clipboard.IsNull()) return false;
1805
1806   Handle(TDataStd_Comment) aCompName;
1807   if (!_clipboard->Main().Root().FindAttribute(TDataStd_Comment::GetID(), aCompName)) return false;
1808   Handle(TDataStd_Integer) anObjID;
1809   if (!_clipboard->Main().Father().FindChild(2).FindAttribute(TDataStd_Integer::GetID(), anObjID))
1810     return false;
1811
1812   SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1813   if (aComponent->_is_nil()) return false;
1814   
1815   CORBA::String_var IOREngine;
1816   if (!aComponent->ComponentIOR(IOREngine)) return false;
1817   
1818   CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1819   SALOMEDS::Driver_var Engine = SALOMEDS::Driver::_narrow(obj) ;
1820   if (CORBA::is_nil(Engine)) return false;
1821   return Engine->CanPaste(strdup(TCollection_AsciiString(aCompName->Get()).ToCString()), anObjID->Get());
1822 }
1823 //============================================================================
1824 /*! Function : PasteLabel
1825  *  Purpose  :
1826  */
1827 //============================================================================
1828 TDF_Label SALOMEDS_StudyManager_i::PasteLabel(const SALOMEDS::Study_ptr theDestinationStudy,
1829                                               const SALOMEDS::Driver_ptr theEngine,
1830                                               const TDF_Label& theSource,
1831                                               const TDF_Label& theDestinationStart,
1832                                               const int theCopiedStudyID,
1833                                               const bool isFirstElement) {
1834
1835   // get corresponding source, target and auxiliary labels
1836   TDF_Label aTargetLabel = theDestinationStart;
1837   TDF_Label aAuxSourceLabel = theSource.Root().FindChild(2);
1838   int a;
1839   if (!isFirstElement) {
1840     for(a = theSource.Depth() - 1; a > 0 ; a--) {
1841       TDF_Label aSourceLabel = theSource;
1842       for(int aNbFather = 1; aNbFather < a; aNbFather++) aSourceLabel = aSourceLabel.Father();
1843       aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
1844       aAuxSourceLabel = aAuxSourceLabel.FindChild(aSourceLabel.Tag());
1845     }
1846   }
1847
1848   // check auxiliary label for TMPFile => IOR
1849   Handle(TDataStd_Name) aNameAttribute;
1850   if (aAuxSourceLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute)) {
1851     Handle(TDataStd_Integer) anObjID;
1852
1853     aAuxSourceLabel.FindAttribute(TDataStd_Integer::GetID(), anObjID);
1854     Handle(TDataStd_Comment) aComponentName;
1855     theSource.Root().FindAttribute(TDataStd_Comment::GetID(), aComponentName);
1856     CORBA::String_var aCompName = strdup(TCollection_AsciiString(aComponentName->Get()).ToCString());
1857
1858     if (theEngine->CanPaste(aCompName, anObjID->Get())) {
1859       SALOMEDS::TMPFile_var aTMPFil = new SALOMEDS::TMPFile();
1860       TCollection_ExtendedString aTMPStr = aNameAttribute->Get();
1861       int aLen = aTMPStr.Length();
1862       aTMPFil->length(aLen);
1863       for(a = 0; a < aLen; a++) {
1864         aTMPFil[a] = ToCharacter(aTMPStr.Value(a+1));
1865       }
1866 //        char* aTMPStr = strdup(TCollection_AsciiString(aNameAttribute->Get()).ToCString());
1867 //        int aLen = strlen(aTMPStr);
1868 //        SALOMEDS::TMPFile aTMPFil(aLen, aLen, (CORBA::Octet*)aTMPStr, 1);
1869       
1870       TCollection_AsciiString anEntry;
1871       TDF_Tool::Entry(aTargetLabel, anEntry);
1872       SALOMEDS::SObject_var aPastedSO = theDestinationStudy->FindObjectID(strdup(anEntry.ToCString()));
1873       if (isFirstElement) {
1874         SALOMEDS::SObject_var aDestSO =
1875           theEngine->PasteInto(aTMPFil.in(),
1876                                anObjID->Get(),
1877                                aPastedSO->GetFatherComponent());
1878         TDF_Tool::Label(theDestinationStart.Data(), aDestSO->GetID(), aTargetLabel);
1879       } else theEngine->PasteInto(aTMPFil.in(),anObjID->Get(),aPastedSO);
1880     }
1881   }
1882
1883   // iterate attributes
1884   TDF_AttributeIterator anAttrIterator(theSource);
1885   Handle(TDF_RelocationTable) aRT = new TDF_RelocationTable();
1886   for(; anAttrIterator.More(); anAttrIterator.Next()) {
1887     Handle(TDF_Attribute) anAttr = anAttrIterator.Value();
1888     if (aTargetLabel.FindAttribute(anAttr->ID(), anAttr)) {
1889       aTargetLabel.ForgetAttribute(anAttr->ID());
1890       anAttr = anAttrIterator.Value();
1891     }
1892     Handle(TDF_Attribute) aNewAttribute = anAttr->NewEmpty();
1893     aTargetLabel.AddAttribute(aNewAttribute);
1894     anAttr->Paste(aNewAttribute, aRT);
1895 //      aRT->SetRelocation(anAttr, aNewAttribute);
1896   }
1897   // check auxiliary label for Comment => reference or name attribute of the referenced object
1898   Handle(TDataStd_Comment) aCommentAttribute;
1899   if (aAuxSourceLabel.FindAttribute(TDataStd_Comment::GetID(), aCommentAttribute)) {
1900     char * anEntry = new char[aCommentAttribute->Get().Length() + 1];
1901     strcpy(anEntry, TCollection_AsciiString(aCommentAttribute->Get()).ToCString());
1902     char* aNameStart = strchr(anEntry, ' ');
1903     if (aNameStart) {
1904       *aNameStart = '\0';
1905       aNameStart++;
1906     }
1907     if (theCopiedStudyID == theDestinationStudy->StudyId()) { // if copy to the same study, reanimate reference
1908       TDF_Label aRefLabel;
1909       TDF_Tool::Label(aTargetLabel.Data(), anEntry, aRefLabel);
1910       TDF_Reference::Set(aTargetLabel, aRefLabel);
1911       SALOMEDS_TargetAttribute::Set(aRefLabel)->Append(aTargetLabel); // target attributes structure support
1912     } else {
1913       if (aNameStart) TDataStd_Name::Set(aTargetLabel, aNameStart);
1914       else TDataStd_Name::Set(aTargetLabel, TCollection_ExtendedString("Reference to:")+anEntry);
1915     }
1916     delete(anEntry);
1917   }
1918
1919   return aTargetLabel;
1920 }
1921 //============================================================================
1922 /*! Function : Paste
1923  *  Purpose  :
1924  */
1925 //============================================================================
1926 SALOMEDS::SObject_ptr SALOMEDS_StudyManager_i::Paste(SALOMEDS::SObject_ptr theObject)
1927      throw(SALOMEDS::StudyBuilder::LockProtection)
1928 {
1929   SALOMEDS::Study_var aStudy = theObject->GetStudy();
1930
1931   // if study is locked, then paste can't be done
1932   if (aStudy->GetProperties()->IsLocked())
1933     throw SALOMEDS::StudyBuilder::LockProtection();
1934
1935   // if there is no component name, then paste only SObjects and attributes: without component help
1936   Handle(TDataStd_Comment) aComponentName;
1937   bool aStructureOnly = !_clipboard->Main().Root().FindAttribute(TDataStd_Comment::GetID(), aComponentName);
1938
1939   // get copied study ID
1940   Handle(TDataStd_Integer) aStudyIDAttribute;
1941   if (!_clipboard->Main().Root().FindAttribute(TDataStd_Integer::GetID(), aStudyIDAttribute))
1942     return SALOMEDS::SObject::_nil();
1943   int aCStudyID = aStudyIDAttribute->Get();
1944
1945   // get component-engine
1946   SALOMEDS::Driver_var Engine;
1947   SALOMEDS::SComponent_var aComponent;
1948   if (!aStructureOnly) {
1949     aComponent = theObject->GetFatherComponent();
1950     CORBA::String_var IOREngine;
1951     if (!aComponent->ComponentIOR(IOREngine)) return SALOMEDS::SObject::_nil();
1952     CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1953     Engine = SALOMEDS::Driver::_narrow(obj) ;
1954   }
1955
1956   // CAF document of current study usage
1957   Handle(TDocStd_Document) aDocument = GetDocumentOfStudy(aStudy);
1958   if (aDocument.IsNull()) return SALOMEDS::SObject::_nil();
1959   // fill root inserted SObject
1960   TDF_Label aStartLabel;
1961   if (aStructureOnly) {
1962     TDF_Label anObjectLabel;
1963     TDF_Tool::Label(aDocument->GetData(), theObject->GetID(), anObjectLabel);
1964     aStartLabel = PasteLabel(aStudy, Engine, _clipboard->Main(), anObjectLabel, aCStudyID, false);
1965   } else {
1966     TDF_Label aComponentLabel;
1967     TDF_Tool::Label(aDocument->GetData(), aComponent->GetID(), aComponentLabel);
1968     aStartLabel = PasteLabel(aStudy, Engine, _clipboard->Main(), aComponentLabel, aCStudyID, true);
1969   }
1970
1971   // paste all sublebels
1972   TDF_ChildIterator anIterator(_clipboard->Main(), Standard_True);
1973   for(; anIterator.More(); anIterator.Next()) {
1974     PasteLabel(aStudy, Engine, anIterator.Value(), aStartLabel, aCStudyID, false);
1975   }
1976
1977   SALOMEDS_SObject_i *  so_servant = new SALOMEDS_SObject_i (aStartLabel, _orb);
1978   SALOMEDS::SObject_var so = SALOMEDS::SObject::_narrow(so_servant->_this()); 
1979
1980   return so._retn();
1981 }