Salome HOME
71033bb231804b2a6c4455836c63f34c0c313449
[modules/kernel.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
78 #include "SALOME_GenericObj_i.hh"
79
80 #include "Utils_ExceptHandlers.hxx"
81 using namespace std;
82
83 UNEXPECT_CATCH(SalomeException,SALOME::SALOME_Exception);
84 UNEXPECT_CATCH(LockProtection, SALOMEDS::StudyBuilder::LockProtection);
85
86 #define USE_CASE_LABEL_ID             "0:2"
87 #define AUTO_SAVE_GUID                "128268A3-71C9-4036-89B1-F81BD6A4FCF2"
88 #define AUTO_SAVE_TAG                 "0:8"
89 #define AUTO_SAVE_TIME_OUT_IN_SECONDS 1200
90 //===========================================================================
91 //Function : LoadAttributes
92 //===========================================================================
93 static void ReadAttributes(SALOMEDS::Study_ptr theStudy,
94                            SALOMEDS::SObject_ptr aSO,
95                            HDFdataset* hdf_dataset)
96 {
97   hdf_dataset->OpenOnDisk();
98
99   SALOMEDS::GenericAttribute_var anAttr;
100
101   char* current_string = new char[hdf_dataset->GetSize()];
102   hdf_dataset->ReadFromDisk(current_string);
103
104   if (!strcmp(hdf_dataset->GetName(),"COMPONENTDATATYPE")) {
105     anAttr = theStudy->NewBuilder()->FindOrCreateAttribute(aSO, "AttributeComment");
106   } else if (!strcmp(hdf_dataset->GetName(),"Reference")) {
107     theStudy->NewBuilder()->Addreference(aSO, theStudy->CreateObjectID(current_string));
108     delete(current_string);
109     hdf_dataset->CloseOnDisk();
110     return;
111   } else {
112     MESSAGE("Read attribute "<<hdf_dataset->GetName())
113     anAttr = theStudy->NewBuilder()->FindOrCreateAttribute(aSO, hdf_dataset->GetName());
114   }
115
116   if (!CORBA::is_nil(anAttr)) {
117     anAttr->Restore(current_string);
118     MESSAGE("Restoring attribute "<<hdf_dataset->GetName()<<" by string '"<<current_string<<"' done")
119   } else {
120     MESSAGE(hdf_dataset->GetName());
121     MESSAGE("LoadAttributes: unknown types");
122   }
123   delete(current_string);
124   hdf_dataset->CloseOnDisk();
125 }
126
127 //============================================================================
128 //Function : Translate_IOR_to_persistentID
129 //============================================================================
130 static void Translate_IOR_to_persistentID (SALOMEDS::Study_ptr        study,
131                                            SALOMEDS::StudyBuilder_ptr SB,
132                                            SALOMEDS::SObject_ptr      so,
133                                            SALOMEDS::Driver_ptr       engine,
134                                            CORBA::Boolean             isMultiFile,
135                                            CORBA::Boolean             isASCII)
136 {
137   MESSAGE("In Translate_IOR_to_persistentID");
138   SALOMEDS::ChildIterator_var itchild = study->NewChildIterator(so);
139   CORBA::String_var ior_string;
140   char* persistent_string = 0;
141   char *curid=0;
142
143   for (; itchild->More(); itchild->Next()) {
144     SALOMEDS::SObject_var current = itchild->Value();
145     SCRUTE(current->GetID());
146     SALOMEDS::GenericAttribute_var SObj;
147     if (current->FindAttribute(SObj, "AttributeIOR")) {
148       SALOMEDS::AttributeIOR_var IOR = SALOMEDS::AttributeIOR::_narrow(SObj);
149       ior_string = IOR->Value();
150       SCRUTE(ior_string);
151       
152       persistent_string = engine->IORToLocalPersistentID (current,ior_string,isMultiFile, isASCII);
153       
154 //       SB->AddAttribute (current, SALOMEDS::PersistentRef,persistent_string);
155       SALOMEDS::AttributePersistentRef_var Pers = SALOMEDS::AttributePersistentRef::_narrow(SB->FindOrCreateAttribute (current, "AttributePersistentRef"));
156       Pers->SetValue(persistent_string);
157       SCRUTE(persistent_string);
158       curid = current->GetID();
159       MESSAGE("Translate " << curid <<
160               " to Persistent string "<<persistent_string);
161       persistent_string = 0;
162       curid = 0;
163     }
164     Translate_IOR_to_persistentID (study,SB,current,engine,isMultiFile, isASCII);
165   }
166   CORBA::string_free(persistent_string);
167   CORBA::string_free(curid);
168 }
169
170 //============================================================================
171 //Function : BuildlTree
172 //============================================================================
173 static void BuildTree (SALOMEDS::Study_ptr theStudy,HDFgroup* hdf_current_group)
174 {
175   hdf_current_group->OpenOnDisk();
176   
177   SALOMEDS::SObject_var aSO;
178   char* Entry = hdf_current_group->GetName();
179   if (strcmp(Entry,"STUDY_STRUCTURE") == 0) {
180     MESSAGE("find the root of the document");
181     aSO = theStudy->CreateObjectID("0:1");
182   }
183   else {
184     aSO = theStudy->CreateObjectID(Entry);
185     MESSAGE("BuildTree : Create a new label"<<Entry);
186   }
187   char name[HDF_NAME_MAX_LEN+1];
188   Standard_Integer nbsons = hdf_current_group->nInternalObjects(); 
189   
190   for (Standard_Integer i=0; i<nbsons; i++) {
191     hdf_current_group->InternalObjectIndentify(i,name);
192     if (strncmp(name, "INTERNAL_COMPLEX",16) == 0) continue;
193     hdf_object_type type = hdf_current_group->InternalObjectType(name);
194
195     if  (type == HDF_DATASET) {
196       MESSAGE("--> Dataset: Internal Object Name : " << name);
197       HDFdataset* new_dataset = new HDFdataset(name,hdf_current_group);
198       ReadAttributes(theStudy,aSO,new_dataset);      
199       new_dataset = 0; // will be deleted by father destructor
200
201     }
202     else if (type == HDF_GROUP)   {
203       MESSAGE( "--> Group: Internal Object Name : " << name);
204       HDFgroup* new_group = new HDFgroup(name,hdf_current_group);
205       BuildTree (theStudy, new_group);
206       new_group = 0; // will be deleted by father destructor
207     }
208   }
209   hdf_current_group->CloseOnDisk();
210 }
211
212
213 //============================================================================
214 /*! Function : SALOMEDS_StudyManager_i
215  *  Purpose  : SALOMEDS_StudyManager_i constructor 
216  */
217 //============================================================================
218 SALOMEDS_StudyManager_i::SALOMEDS_StudyManager_i(CORBA::ORB_ptr orb) 
219
220   _orb = CORBA::ORB::_duplicate(orb);
221   _OCAFApp = new SALOMEDS_OCAFApplication();  
222   _name_service = new SALOME_NamingService(_orb);
223   // Study directory creation in the naming service : to register all
224   // open studies in the session
225   _name_service->Create_Directory("/Study");
226   _IDcounter = 0;
227 }
228
229 //============================================================================
230 /*! Function : ~SALOMEDS_StudyManager_i
231  *  Purpose  : SALOMEDS_StudyManager_i destructor
232  */
233 //============================================================================
234 SALOMEDS_StudyManager_i::~SALOMEDS_StudyManager_i()
235 {
236   // Destroy directory to register open studies
237   _name_service->Destroy_Directory("/Study");
238   // Destroy OCAF document
239   delete &_OCAFApp;
240 }
241
242 //============================================================================
243 /*! Function : register_name
244  *  Purpose  : Register the study Manager in the naming service under the  
245  *             context name
246  */
247 //============================================================================
248 void SALOMEDS_StudyManager_i::register_name(char * name) {
249   SALOMEDS::StudyManager_ptr g = SALOMEDS::StudyManager::_narrow(_this());
250   _name_service->Register(g, name);
251 }
252
253
254 //============================================================================
255 /*! Function : NewStudy
256  *  Purpose  : Create a New Study of name study_name
257  */
258 //============================================================================
259 SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::NewStudy(const char* study_name) 
260 {
261   Handle(TDocStd_Document) Doc;
262   _OCAFApp->NewDocument("SALOME_STUDY",Doc); 
263
264   MESSAGE("NewStudy : Creating the CORBA servant holding it... ");
265   SALOMEDS_Study_i *Study_servant = new SALOMEDS_Study_i(Doc,_orb,study_name); 
266   SALOMEDS::Study_var Study = SALOMEDS::Study::_narrow(Study_servant->_this());
267
268   //Study->StudyId( _OCAFApp->NbDocuments() ); 
269   _IDcounter++;
270   Study->StudyId( _IDcounter );
271
272   // Register study in the naming service
273   // Path to acces the study
274   if(!_name_service->Change_Directory("/Study")) 
275       MESSAGE( "Unable to access the study directory" )
276   else
277       _name_service->Register(Study, study_name);
278
279   // Assign the value of the IOR in the study->root
280   const char*  IORStudy = _orb->object_to_string(Study);
281   SALOMEDS_IORAttribute::Set(Doc->Main().Root(),TCollection_ExtendedString((char*)IORStudy),_orb);
282
283   // set Study properties
284   SALOMEDS::AttributeStudyProperties_ptr aProp = Study->GetProperties();
285   OSD_Process aProcess;
286   Quantity_Date aDate = aProcess.SystemDate();
287   aProp->SetCreationDate(CORBA::Long(aDate.Minute()), CORBA::Long(aDate.Hour()), CORBA::Long(aDate.Day()),
288                          CORBA::Long(aDate.Month()), CORBA::Long(aDate.Year()));
289   aProp->SetCreationMode("from scratch");
290   aProp->SetUserName(aProcess.UserName().ToCString());
291
292   return Study;
293 }
294
295 //============================================================================
296 /*! Function : Open
297  *  Purpose  : Open a Study from it's persistent reference
298  */
299 //============================================================================
300 SALOMEDS::Study_ptr  SALOMEDS_StudyManager_i::Open(const char* aUrl)
301      throw(SALOME::SALOME_Exception)
302 {
303   Unexpect aCatch(SalomeException);
304   MESSAGE("Begin of SALOMEDS_StudyManager_i::Open");
305   // open the HDFFile 
306   HDFfile *hdf_file =0;         
307   HDFgroup *hdf_group_study_structure =0;
308
309   char* aHDFUrl;
310   bool isASCII = false;
311   if (HDFascii::isASCII(aUrl)) {
312     isASCII = true;
313     char* aResultPath = HDFascii::ConvertFromASCIIToHDF(aUrl);
314     aHDFUrl = new char[strlen(aResultPath) + 19];
315     sprintf(aHDFUrl, "%shdf_from_ascii.hdf", aResultPath);
316     delete(aResultPath);
317   } else {
318     aHDFUrl = CORBA::string_dup(aUrl);
319   }
320
321   hdf_file = new HDFfile(aHDFUrl);
322   try {
323     hdf_file->OpenOnDisk(HDF_RDONLY);// mpv: was RDWR, but opened file can be write-protected too
324   }
325   catch (HDFexception)
326     {
327 //        MESSAGE( "HDFexception ! " );
328 //        cerr << "HDFexception ! " << endl;
329       delete aHDFUrl;
330       char eStr[strlen(aUrl)+17];
331       sprintf(eStr,"Can't open file %s",aUrl);
332       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(eStr),SALOME::BAD_PARAM);
333       
334     } 
335   MESSAGE("Open : Creating the CORBA servant holding it... ");
336
337   // Temporary aStudyUrl in place of study name
338   Handle(TDocStd_Document) Doc;
339   _OCAFApp->NewDocument("SALOME_STUDY",Doc); 
340
341   SALOMEDS_Study_i * Study_servant = new SALOMEDS_Study_i(Doc, _orb, aUrl);  
342   SALOMEDS::Study_var Study = SALOMEDS::Study::_narrow(Study_servant->_this()); 
343
344   //  Study->StudyId( _OCAFApp->NbDocuments() ); 
345   _IDcounter++;
346   Study->StudyId( _IDcounter );
347
348   // Assign the value of the URL in the study object
349   Study->URL (aUrl);
350   SCRUTE(aUrl);
351
352   // Assign the value of the IOR in the study->root
353   CORBA::String_var IORStudy = _orb->object_to_string(Study);
354   SALOMEDS_IORAttribute::Set(Doc->Main().Root(),
355                              TCollection_ExtendedString(CORBA::string_dup(IORStudy)),_orb);
356
357   SALOMEDS_PersRefAttribute::Set(Doc->Main(),(char*)aUrl); 
358
359   if (!hdf_file->ExistInternalObject("STUDY_STRUCTURE")) {
360     delete aHDFUrl;
361     MESSAGE("SALOMEDS_StudyManager::Open : the study is empty");
362     return Study;
363   }
364
365   //Create  the Structure of the OCAF Document
366   hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
367
368   Handle(TDF_Data) DF = Doc->GetData();
369
370   try {
371     BuildTree (Study,hdf_group_study_structure);
372   }
373   catch (HDFexception)
374     {
375 //        MESSAGE( "HDFexception ! " );
376 //        cerr << "HDFexception ! " << endl;
377       delete aHDFUrl;
378       char eStr[strlen(aUrl)+17];
379       sprintf(eStr,"Can't open file %s",aUrl);
380       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(eStr),SALOME::BAD_PARAM);
381     } 
382   
383   hdf_file->CloseOnDisk();
384
385   // Register study in the naming service
386   // Path to acces the study
387   if(!_name_service->Change_Directory("/Study")) MESSAGE( "Unable to access the study directory" )
388   else _name_service->Register(Study, CORBA::string_dup(Study->Name()));
389
390
391   if (isASCII) {
392     SALOMEDS::ListOfFileNames_var aFilesToRemove = new SALOMEDS::ListOfFileNames;
393     aFilesToRemove->length(1);
394     aFilesToRemove[0] = CORBA::string_dup(&(aHDFUrl[strlen(SALOMEDS_Tool::GetDirFromPath(aHDFUrl).c_str())]));
395     SALOMEDS_Tool::RemoveTemporaryFiles(SALOMEDS_Tool::GetDirFromPath(aHDFUrl).c_str(), aFilesToRemove, true);
396   }
397   delete aHDFUrl;
398   delete hdf_file; // all related hdf objects will be deleted
399   return Study;
400 }
401
402
403
404 //============================================================================
405 /*! Function : Close
406  *  Purpose  : Close a study.
407  *             If the study hasn't been saved, ask the user to confirm the
408  *             close action without saving 
409  */
410 //============================================================================
411 void  SALOMEDS_StudyManager_i::Close(SALOMEDS::Study_ptr aStudy)
412 {
413   if(aStudy->_is_nil()) return;
414   
415   aStudy->RemovePostponed(-1);
416   
417   // Destroy study name in the naming service
418   if(_name_service->Change_Directory("/Study")) 
419     _name_service->Destroy_Name(aStudy->Name());
420   
421   aStudy->Close();
422 }
423
424 //============================================================================
425 /*! Function : Save
426  *  Purpose  : Save a Study to it's persistent reference
427  */
428 //============================================================================
429 void SALOMEDS_StudyManager_i::Save(SALOMEDS::Study_ptr aStudy, CORBA::Boolean theMultiFile)
430 {
431   CORBA::String_var url = aStudy->URL();
432   if (url==NULL)
433     MESSAGE( "No path specified to save the study. Nothing done")
434   else
435     {
436       _SaveAs(url,aStudy, theMultiFile, false);
437     }
438 }
439
440 void SALOMEDS_StudyManager_i::SaveASCII(SALOMEDS::Study_ptr aStudy, CORBA::Boolean theMultiFile)
441 {
442   CORBA::String_var url = aStudy->URL();
443   if (url==NULL)
444     MESSAGE( "No path specified to save the study. Nothing done")
445   else
446     {
447       _SaveAs(url,aStudy, theMultiFile, true);
448     }
449 }
450
451 //=============================================================================
452 /*! Function : SaveAs
453  *  Purpose  : Save a study to the persistent reference aUrl
454  */
455 //============================================================================
456 void SALOMEDS_StudyManager_i::SaveAs(const char* aUrl, SALOMEDS::Study_ptr aStudy, CORBA::Boolean theMultiFile)
457 {
458   _SaveAs(aUrl,aStudy,theMultiFile, false);
459
460 }
461
462 void SALOMEDS_StudyManager_i::SaveAsASCII(const char* aUrl, SALOMEDS::Study_ptr aStudy, CORBA::Boolean theMultiFile)
463 {
464   _SaveAs(aUrl,aStudy,theMultiFile, true);
465 }
466
467 //============================================================================
468 /*! Function : GetOpenStudies
469  *  Purpose  : Get name list of open studies in the session
470  */
471 //============================================================================
472 SALOMEDS::ListOfOpenStudies*  SALOMEDS_StudyManager_i::GetOpenStudies()
473 {
474   // MESSAGE("Begin of GetOpenStudies");
475   SALOMEDS::ListOfOpenStudies_var _list_open_studies = new SALOMEDS::ListOfOpenStudies;
476   _list_open_studies->length(0);
477   vector<string> _list ;
478
479   if(!_name_service->Change_Directory("/Study"))
480     {
481       MESSAGE("No active study in this session");
482     }
483   else
484     {
485       _list = _name_service->list_directory();
486       _list_open_studies->length(_list.size());
487       for (unsigned int ind=0; ind < _list.size();ind++)
488         {
489           _list_open_studies[ind]=CORBA::string_dup(_list[ind].c_str());
490           SCRUTE(_list_open_studies[ind]) ;
491         }
492     }
493   return _list_open_studies._retn();
494 }
495
496 //============================================================================
497 /*! Function : GetStudyByName
498  *  Purpose  : Get a study from its name
499  */
500 //============================================================================
501 SALOMEDS::Study_ptr  
502 SALOMEDS_StudyManager_i::GetStudyByName(const char* aStudyName) 
503 {
504   SALOMEDS::Study_var Study;
505
506   // Go to study directory and look for aStudyName
507   if(!_name_service->Change_Directory("/Study"))
508     {
509       MESSAGE("No active study in this session");
510       ASSERT(false); // Stop here...
511     }
512   
513 //   const char *theStudyName = this->_SubstituteSlash(aStudyName);
514   const char* theStudyName = CORBA::string_dup(aStudyName);
515
516   if(_name_service->Find(theStudyName)>0)
517     {
518     // Study found
519     CORBA::Object_ptr obj= _name_service->Resolve(theStudyName) ;
520     Study = SALOMEDS::Study::_narrow(obj);
521     MESSAGE("Study " << theStudyName << " found in the naming service");
522     }
523   else  
524     {
525       Study = SALOMEDS::Study::_narrow( CORBA::Object::_nil()); 
526       MESSAGE("Study " << theStudyName << " not found in the naming service");
527     }
528   return Study;
529 }
530
531 //============================================================================
532 /*! Function : GetStudyByID
533  *  Purpose  : Get a study from its ID
534  */
535 //============================================================================
536 SALOMEDS::Study_ptr  
537 SALOMEDS_StudyManager_i::GetStudyByID(CORBA::Short aStudyID) 
538 {
539   SALOMEDS::Study_var Study;
540   vector<string> _list ;
541
542   if(!_name_service->Change_Directory("/Study"))
543     {
544       MESSAGE("No active study in this session");
545     }
546   else
547     {
548       _list = _name_service->list_directory();
549       for (unsigned int ind=0; ind < _list.size();ind++)
550         {
551           const char* theStudyName = CORBA::string_dup(_list[ind].c_str());
552           MESSAGE ( "GetStudyByID = " << theStudyName )
553
554           if(_name_service->Find(theStudyName)>0) {
555             CORBA::Object_ptr obj= _name_service->Resolve(theStudyName) ;
556             Study = SALOMEDS::Study::_narrow(obj);
557
558             MESSAGE ( " aStudyID : " << aStudyID << "-" << Study->StudyId() )
559
560             if ( aStudyID == Study->StudyId() ) {
561               MESSAGE("Study with studyID = " << aStudyID << " found in the naming service");
562               return Study;
563             }
564           } else {
565             Study = SALOMEDS::Study::_narrow( CORBA::Object::_nil()); 
566             MESSAGE("Study " << theStudyName << " not found in the naming service");
567           }
568         }
569       Study = SALOMEDS::Study::_narrow( CORBA::Object::_nil()); 
570     }
571   return Study;
572 }
573 //============================================================================
574 /*! Function : SaveAttributes
575  *  Purpose  : Save attributes for object
576  */
577 //============================================================================
578 static void SaveAttributes(SALOMEDS::SObject_ptr SO, HDFgroup *hdf_group_sobject) {
579   int a;
580   hdf_size size[1];
581   SALOMEDS::ListOfAttributes_var anAttrList = SO->GetAllAttributes();
582   for(a = anAttrList->length() - 1; a >= 0; a--) {
583     if (strcmp(anAttrList[a]->Type(), "AttributeIOR") == 0) continue; // never write AttributeIOR to file
584     if (strcmp(anAttrList[a]->Type(), "AttributeExternalFileDef") == 0) continue; // never write ExternalFileDef to file
585     if (strcmp(anAttrList[a]->Type(), "AttributeFileType") == 0) continue; // never write FileType to file
586     CORBA::String_var aSaveStr = CORBA::string_dup(anAttrList[a]->Store());
587     size[0] = (hdf_int32) strlen(aSaveStr) + 1;
588     HDFdataset *hdf_dataset = new HDFdataset(anAttrList[a]->Type(),hdf_group_sobject,HDF_STRING,size,1);
589     hdf_dataset->CreateOnDisk();
590     hdf_dataset->WriteOnDisk(aSaveStr);
591     hdf_dataset->CloseOnDisk();
592     //MESSAGE("********** Write Attribute "<<anAttrList[a]->Type()<<" : "<<aSaveStr<<" done");
593     hdf_dataset=0; //will be deleted by hdf_sco_group destructor
594   }
595
596   // Reference attribute has no CORBA attribute representation, so, GetAllAttributes can not return this attribute
597   SALOMEDS::SObject_var RefSO;
598   if(SO->ReferencedObject(RefSO)) {
599     CORBA::String_var attribute_reference = CORBA::string_dup(RefSO->GetID());
600     size[0] = strlen(attribute_reference) + 1 ; 
601     HDFdataset *hdf_dataset = new HDFdataset("Reference",hdf_group_sobject,HDF_STRING,size,1);
602     hdf_dataset->CreateOnDisk();
603     hdf_dataset->WriteOnDisk(attribute_reference);
604     hdf_dataset->CloseOnDisk();
605     hdf_dataset =0; // will be deleted by father hdf object destructor
606   }
607 }
608
609 //=============================================================================
610 /*! Function : _SaveProperties
611  *  Purpose  : save the study properties in HDF file
612  */
613 //============================================================================
614 void SALOMEDS_StudyManager_i::_SaveProperties(SALOMEDS::Study_ptr aStudy, HDFgroup *hdf_group) {
615   HDFdataset *hdf_dataset = 0;
616   hdf_size size[1];
617   hdf_int32 name_len;
618
619   // add modifications list (user and date of save)
620   SALOMEDS::AttributeStudyProperties_ptr aProp = aStudy->GetProperties();
621   SALOMEDS::StudyBuilder_var SB= aStudy->NewBuilder();
622 //    SB->NewCommand();
623   int aLocked = aProp->IsLocked();
624   if (aLocked) aProp->SetLocked(Standard_False);
625   OSD_Process aProcess;
626   Quantity_Date aDate = aProcess.SystemDate();
627   aProp->SetModification(aProcess.UserName().ToCString(),
628                          CORBA::Long(aDate.Minute()), CORBA::Long(aDate.Hour()), CORBA::Long(aDate.Day()),
629                          CORBA::Long(aDate.Month()), CORBA::Long(aDate.Year()));
630   if (aLocked) aProp->SetLocked(Standard_True);
631 //    SB->CommitCommand();
632   
633
634   SALOMEDS::StringSeq_var aNames;
635   SALOMEDS::LongSeq_var aMinutes, aHours, aDays, aMonths, aYears;
636   aProp->GetModificationsList(aNames , aMinutes ,aHours, aDays, aMonths, aYears, true);
637   int aLength, anIndex;
638   for(aLength = 0, anIndex = aNames->length() - 1; anIndex >= 0; anIndex--) aLength += strlen(aNames[anIndex]) + 1;
639
640   // string length: 1 byte = locked flag, 1 byte = modified flag, (12 + name length + 1) for each name and date, "zero" byte
641   char* aProperty = new char[3 + aLength + 12 * aNames->length()];
642
643   sprintf(aProperty,"%c%c",
644           (strlen(aProp->GetCreationMode()) != 0)?aProp->GetCreationMode()[0]:'0',
645           (aProp->IsLocked())?'l':'u');
646
647   aLength = aNames->length();
648   int a = 2;
649   for(anIndex = 0; anIndex  < aLength; anIndex++) {
650     sprintf(&(aProperty[a]),"%2d%2d%2d%2d%4d%s",
651             (int)(aMinutes[anIndex]),
652             (int)(aHours[anIndex]),
653             (int)(aDays[anIndex]),
654             (int)(aMonths[anIndex]),
655             (int)(aYears[anIndex]),
656             (char*)aNames[anIndex]);
657     a = strlen(aProperty);
658     aProperty[a++] = 1;
659   }
660   aProperty[a] = 0;
661
662   name_len = (hdf_int32) a;
663 //    MESSAGE("*** Property: "<<aProperty);
664   size[0] = name_len + 1 ; 
665   hdf_dataset = new HDFdataset("AttributeStudyProperties",hdf_group,HDF_STRING,size,1);
666   hdf_dataset->CreateOnDisk();
667   hdf_dataset->WriteOnDisk(aProperty);
668   MESSAGE("attribute StudyProperties " <<  aProperty << " wrote on file");
669   hdf_dataset->CloseOnDisk();
670   hdf_dataset=0; //will be deleted by hdf_sco_group destructor
671   //delete(aProperty); 
672   delete [] aProperty;
673   aProp->SetModified(0);
674 }
675
676 //=============================================================================
677 /*! Function : _SaveAs
678  *  Purpose  : save the study in HDF file
679  */
680 //============================================================================
681 void SALOMEDS_StudyManager_i::_SaveAs(const char* aUrl, 
682                                       SALOMEDS::Study_ptr aStudy,
683                                       CORBA::Boolean theMultiFile,
684                                       CORBA::Boolean theASCII)
685 {
686   // HDF File will be composed of differents part :
687   // * For each ComponentDataType, all data created by the component
688   //   Informations in data group hdf_group_datacomponent
689   // * Study Structure -> Exactly what is contained in OCAF document
690   //   Informations in data group hdf_group_study_structure
691
692   HDFfile *hdf_file=0;         
693   HDFgroup *hdf_group_study_structure =0;
694   HDFgroup *hdf_sco_group =0;
695   HDFgroup *hdf_sco_group2 =0;
696
697   HDFgroup *hdf_group_datacomponent =0;
698   HDFdataset *hdf_dataset =0;
699   HDFattribute *hdf_attribute=0;
700   hdf_size size[1];
701   hdf_int32 name_len = 0;
702   char *component_name = 0;
703   char *attribute_name = 0;
704   char *attribute_comment = 0;
705   char *attribute_persistentref = 0;
706
707   int aLocked = aStudy->GetProperties()->IsLocked();
708   if (aLocked) aStudy->GetProperties()->SetLocked(false);
709
710   SALOMEDS::StudyBuilder_var SB= aStudy->NewBuilder();
711
712   ASSERT(!CORBA::is_nil(aStudy));
713   try
714     {
715       // mpv 15.12.2003: for saving components we have to load all data from all modules
716
717       SALOMEDS::SComponentIterator_var itcomponent1 = aStudy->NewComponentIterator();
718       for (; itcomponent1->More(); itcomponent1->Next())
719         {
720           SALOMEDS::SComponent_var sco = itcomponent1->Value();
721
722           // if there is an associated Engine call its method for saving
723           CORBA::String_var IOREngine;
724           try {
725             if (!sco->ComponentIOR(IOREngine)) {
726               SALOMEDS::GenericAttribute_var aGeneric;
727               SALOMEDS::AttributeComment_var aName;
728               if(sco->FindAttribute(aGeneric, "AttributeComment"))
729                 aName = SALOMEDS::AttributeComment::_narrow(aGeneric);
730             
731               if (!aName->_is_nil()) {
732                 
733                 CORBA::String_var aCompType = aName->Value();
734
735                 CORBA::String_var aFactoryType;
736                 if (strcmp(aCompType, "SUPERV") == 0) aFactoryType = "SuperVisionContainer";
737                 else aFactoryType = "FactoryServer";
738                 
739                 Engines::Component_var aComp =
740                   SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component(aFactoryType, aCompType);
741                 if (aComp->_is_nil()) {
742                   Engines::Component_var aComp =
743                     SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component("FactoryServerPy", aCompType);
744                 }
745                 
746                 if (!aComp->_is_nil()) {
747                   SALOMEDS::Driver_var aDriver = SALOMEDS::Driver::_narrow(aComp);
748                   if (!CORBA::is_nil(aDriver)) {
749                     SB->LoadWith(sco, aDriver);
750                   }
751                 }
752               }
753             }
754           } catch(...) {
755             MESSAGE("Can not restore information to resave it");
756             return;
757           }
758         }
759
760
761
762       CORBA::String_var anOldName = aStudy->Name();
763       aStudy->URL(aUrl);
764
765       // To change for Save 
766       // Do not have to do a new file but just a Open??? Rewrite all informations after erasing evrything??
767       hdf_file = new HDFfile((char *)aUrl);
768       hdf_file->CreateOnDisk();
769       MESSAGE("File " << aUrl << " created");
770
771       //-----------------------------------------------------------------------
772       // 1 - Create a groupe for each SComponent and Update the PersistanceRef
773       //-----------------------------------------------------------------------
774       hdf_group_datacomponent = new HDFgroup("DATACOMPONENT",hdf_file);
775       hdf_group_datacomponent->CreateOnDisk();
776
777       SALOMEDS::SComponentIterator_var itcomponent = aStudy->NewComponentIterator();
778       
779       //SRN: Added 17 Nov, 2003
780       SALOMEDS::SObject_var anAutoSaveSO = aStudy->FindObjectID(AUTO_SAVE_TAG);
781       //SRN: End
782
783       for (; itcomponent->More(); itcomponent->Next())
784         {
785           SALOMEDS::SComponent_var sco = itcomponent->Value();
786           
787           CORBA::String_var scoid = sco->GetID();
788           hdf_sco_group = new HDFgroup(scoid,hdf_group_datacomponent);
789           hdf_sco_group->CreateOnDisk();
790
791           CORBA::String_var componentDataType = sco->ComponentDataType();
792           MESSAGE ( "Look for  an engine for data type :"<< componentDataType);
793
794           //SRN: Added 17 Nov 2003: If there is a specified attribute, the component peforms a special save       
795           if(!CORBA::is_nil(anAutoSaveSO) && SB->IsGUID(sco, AUTO_SAVE_GUID)) {     
796        
797             SALOMEDS::GenericAttribute_var aGeneric;
798             SALOMEDS::AttributeTableOfString_var aTable;
799             if(anAutoSaveSO->FindAttribute(aGeneric, "AttributeTableOfString")) {
800               aTable = SALOMEDS::AttributeTableOfString::_narrow(aGeneric);
801               Standard_Integer nbRows = aTable->GetNbRows(), k, aTimeOut = 0;
802               if(nbRows > 0 && aTable->GetNbColumns() > 1) {    
803
804                 SALOMEDS::StringSeq_var aRow;
805                 for(k=1; k<=nbRows; k++) {
806                   aRow = aTable->GetRow(k);
807                   if (strcmp(aRow[0], componentDataType) == 0) {
808                     CORBA::String_var anEntry = CORBA::string_dup(aRow[1]);
809                     SALOMEDS::SObject_var aCompSpecificSO = aStudy->FindObjectID(anEntry);
810                     if(!CORBA::is_nil(aCompSpecificSO)) {
811                       SALOMEDS::AttributeInteger_var anInteger;
812                       if(aCompSpecificSO->FindAttribute(aGeneric, "AttributeInteger")) {
813                         anInteger = SALOMEDS::AttributeInteger::_narrow(aGeneric);
814                         anInteger->SetValue(-1);
815                         while(anInteger->Value() < 0) { sleep(2); if(++aTimeOut > AUTO_SAVE_TIME_OUT_IN_SECONDS) break; }
816                       }  // if(aCompSpecificSO->FindAttribute(anInteger, "AttributeInteger"))
817                     }  // if(!CORBA::is_nil(aCompSpecificSO)) 
818                   }  // if (strcmp(aRow[0], componentDataType) == 0)
819                 }  // for
820
821               }  // if(nbRows > 0 && aTable->GetNbColumns() > 1)
822
823             }  // if(anAutoSaveSO->FindAttribute(aTable, "AttributeTableOfString")
824
825           }  // if(SB->IsGUID(AUTO_SAVE_GUID)
826
827           //SRN: End
828
829           CORBA::String_var IOREngine;
830           if (sco->ComponentIOR(IOREngine))
831             {
832               // we have found the associated engine to write the data 
833               MESSAGE ( "We have found an engine for data type :"<< componentDataType);
834               CORBA::Object_var obj = _orb->string_to_object(IOREngine);
835               SALOMEDS::Driver_var Engine = SALOMEDS::Driver::_narrow(obj) ;
836               
837               if (!CORBA::is_nil(Engine))
838                 {
839                   MESSAGE ( "Save the data of type:"<< componentDataType);
840                   MESSAGE("Engine :"<<Engine->ComponentDataType());
841
842                   SALOMEDS::TMPFile_var aStream;
843
844                   if (theASCII) aStream = Engine->SaveASCII(sco,SALOMEDS_Tool::GetDirFromPath(aUrl).c_str(),theMultiFile);
845                   else aStream = Engine->Save(sco,SALOMEDS_Tool::GetDirFromPath(aUrl).c_str(),theMultiFile);
846
847                   HDFdataset *hdf_dataset;
848                   hdf_size aHDFSize[1];
849                   if(aStream->length() > 0) {  //The component saved some auxiliary files, then put them into HDF file 
850
851                     aHDFSize[0] = aStream->length();
852                       
853                     HDFdataset *hdf_dataset = new HDFdataset("FILE_STREAM", hdf_sco_group, HDF_STRING, aHDFSize, 1);
854                     hdf_dataset->CreateOnDisk();
855                     hdf_dataset->WriteOnDisk((unsigned char*) &aStream[0]);  //Save the stream in the HDF file
856                     hdf_dataset->CloseOnDisk();
857                   }
858                   // store multifile state
859                   aHDFSize[0] = 2;
860                   hdf_dataset = new HDFdataset("MULTIFILE_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
861                   hdf_dataset->CreateOnDisk();
862                   hdf_dataset->WriteOnDisk((void*)(theMultiFile?"M":"S")); // save: multi or single
863                   hdf_dataset->CloseOnDisk();
864                   hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor                
865
866                   // store ASCII state
867                   aHDFSize[0] = 2;
868                   hdf_dataset = new HDFdataset("ASCII_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
869                   hdf_dataset->CreateOnDisk();
870                   hdf_dataset->WriteOnDisk((void*)(theASCII?"A":"B")); // save: ASCII or BINARY
871                   hdf_dataset->CloseOnDisk();
872                   hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor                
873
874                   Translate_IOR_to_persistentID (aStudy,SB,sco,Engine,theMultiFile, theASCII);
875                   MESSAGE("After Translate_IOR_to_persistentID");
876                   
877                   // Creation of the persistance reference  attribute
878                 }
879             }
880           hdf_sco_group->CloseOnDisk();
881           hdf_sco_group=0; // will be deleted by hdf_group_datacomponent destructor
882         }
883       hdf_group_datacomponent->CloseOnDisk();
884       hdf_group_datacomponent =0;  // will be deleted by hdf_file destructor
885
886
887       //-----------------------------------------------------------------------
888       //3 - Write the Study Structure
889       //-----------------------------------------------------------------------
890       hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
891       hdf_group_study_structure->CreateOnDisk();
892
893       // save component attributes
894       SALOMEDS::SComponentIterator_var itcomp = aStudy->NewComponentIterator();
895       for (; itcomp->More(); itcomp->Next()) 
896         {
897           SALOMEDS::SComponent_var SC = itcomp->Value();
898           
899           CORBA::String_var scid = SC->GetID();
900           hdf_sco_group2 = new HDFgroup(scid,hdf_group_study_structure);
901           hdf_sco_group2->CreateOnDisk();
902           SaveAttributes(SC, hdf_sco_group2);
903           // ComponentDataType treatment
904           component_name = SC->ComponentDataType();
905           MESSAGE("Component data type " << component_name << " treated");
906           
907           name_len = (hdf_int32) strlen(component_name);
908           size[0] = name_len +1 ; 
909           hdf_dataset = new HDFdataset("COMPONENTDATATYPE",hdf_sco_group2,HDF_STRING,size,1);
910           hdf_dataset->CreateOnDisk();
911           hdf_dataset->WriteOnDisk(component_name);
912           MESSAGE("component name " <<  component_name << " wrote on file");
913           hdf_dataset->CloseOnDisk();
914           hdf_dataset=0; //will be deleted by hdf_sco_group destructor
915           _SaveObject(aStudy, SC, hdf_sco_group2);
916           hdf_sco_group2->CloseOnDisk();
917           hdf_sco_group2=0; // will be deleted by hdf_group_study_structure destructor
918           CORBA::string_free(component_name);       
919         }
920       //-----------------------------------------------------------------------
921       //4 - Write the Study UseCases Structure
922       //-----------------------------------------------------------------------
923       SALOMEDS::SObject_var aSO = aStudy->FindObjectID(USE_CASE_LABEL_ID);
924       if (!aSO->_is_nil()) {
925         HDFgroup *hdf_soo_group = new HDFgroup(USE_CASE_LABEL_ID,hdf_group_study_structure);
926         hdf_soo_group->CreateOnDisk();
927         SaveAttributes(aSO, hdf_soo_group);
928         _SaveObject(aStudy, aSO, hdf_soo_group);
929         MESSAGE("Use cases data structure writed");
930         hdf_soo_group->CloseOnDisk();
931         hdf_soo_group=0; // will be deleted by hdf_group_study_structure destructor
932       }
933
934       if (aLocked) aStudy->GetProperties()->SetLocked(true);
935       //-----------------------------------------------------------------------
936       //5 - Write the Study Properties
937       //-----------------------------------------------------------------------
938       name_len = (hdf_int32) strlen(aStudy->Name());
939       size[0] = name_len +1 ; 
940       hdf_dataset = new HDFdataset("STUDY_NAME",hdf_group_study_structure,HDF_STRING,size,1);
941       hdf_dataset->CreateOnDisk();
942       CORBA::String_var studid = aStudy->Name();
943       hdf_dataset->WriteOnDisk(studid);
944       MESSAGE("study name " << studid << " wrote on file");
945       hdf_dataset->CloseOnDisk();
946       hdf_dataset=0; // will be deleted by hdf_group_study_structure destructor
947
948       _SaveProperties(aStudy, hdf_group_study_structure);
949
950       hdf_group_study_structure->CloseOnDisk();
951       hdf_file->CloseOnDisk();
952
953       _name_service->Change_Directory("/Study");
954       _name_service->Destroy_Name(anOldName);
955       _name_service->Register(aStudy, aStudy->Name());
956
957       aStudy->IsSaved(true);
958       hdf_group_study_structure =0; // will be deleted by hdf_file destructor
959       delete hdf_file; // recursively deletes all hdf objects...
960     }
961   catch (HDFexception)
962     {
963       MESSAGE( "HDFexception ! " )
964     }
965   if (theASCII) { // save file in ASCII format
966     HDFascii::ConvertFromHDFToASCII(aUrl, true);
967   }
968 }
969
970 //============================================================================
971 /*! Function : _SaveObject
972  *  Purpose  :
973  */
974 //============================================================================
975 void SALOMEDS_StudyManager_i::_SaveObject(SALOMEDS::Study_ptr aStudy, 
976                                           SALOMEDS::SObject_ptr SC, 
977                                           HDFgroup *hdf_group_datatype)
978 {
979   // Write in group hdf_group_datatype all informations of SObject SC
980   // Iterative function to parse all SObjects under a SComponent
981   SALOMEDS::SObject_var RefSO;
982   HDFgroup *hdf_group_sobject = 0;
983   HDFdataset *hdf_dataset = 0;
984   hdf_size size[1];
985   hdf_int32 name_len = 0;
986
987   SALOMEDS::ChildIterator_var itchild = aStudy->NewChildIterator(SC);
988   for (; itchild->More(); itchild->Next()) 
989     {
990       SALOMEDS::SObject_var SO = itchild->Value();
991
992       // mpv: don't save empty labels
993       if (SO->GetAllAttributes()->length() == 0 && !SO->ReferencedObject(RefSO)) {
994         SALOMEDS::ChildIterator_var subchild = aStudy->NewChildIterator(SC);
995         if (!subchild->More()) {
996           continue;
997         }
998         subchild->InitEx(true);
999         bool anEmpty = true;
1000         for (; subchild->More() && anEmpty; subchild->Next()) 
1001           if (subchild->Value()->GetAllAttributes()->length() != 0 ||
1002               subchild->Value()->ReferencedObject(RefSO)) anEmpty = false;
1003         if (anEmpty) {
1004           continue;
1005         }
1006       }
1007
1008       CORBA::String_var scoid = CORBA::string_dup(SO->GetID());
1009       hdf_group_sobject = new HDFgroup(scoid,hdf_group_datatype);
1010       hdf_group_sobject->CreateOnDisk();
1011       SaveAttributes(SO, hdf_group_sobject);
1012       _SaveObject(aStudy,SO, hdf_group_sobject);
1013       hdf_group_sobject->CloseOnDisk();
1014       hdf_group_sobject =0; // will be deleted by father hdf object destructor
1015
1016     }
1017 }
1018
1019 //============================================================================
1020 /*! Function : _SubstituteSlash
1021  *  Purpose  :
1022  */
1023 //============================================================================
1024
1025 const char *SALOMEDS_StudyManager_i::_SubstituteSlash(const char *aUrl)
1026 {
1027   ASSERT(1==0);
1028   TCollection_ExtendedString theUrl(CORBA::string_dup(aUrl));
1029   Standard_ExtCharacter val1 = ToExtCharacter('/');
1030   Standard_ExtCharacter val2 = ToExtCharacter(':');
1031   theUrl.ChangeAll(val1,val2);
1032   TCollection_AsciiString ch(theUrl);
1033   return CORBA::string_dup(ch.ToCString());
1034 }
1035
1036 //============================================================================
1037 /*! Function : CanCopy
1038  *  Purpose  : 
1039  */
1040 //============================================================================
1041 CORBA::Boolean SALOMEDS_StudyManager_i::CanCopy(SALOMEDS::SObject_ptr theObject) {
1042   SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1043   if (aComponent->_is_nil()) return false;
1044   if (aComponent == theObject) return false;
1045
1046   CORBA::String_var IOREngine;
1047   if (!aComponent->ComponentIOR(IOREngine)) return false;
1048
1049   CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1050   SALOMEDS::Driver_var Engine = SALOMEDS::Driver::_narrow(obj) ;
1051   if (CORBA::is_nil(Engine)) return false;
1052   Standard_Boolean a = Engine->CanCopy(theObject);
1053   return a;
1054 }
1055
1056 //============================================================================
1057 /*! Function : GetDocumentOfStudy
1058  *  Purpose  : 
1059  */
1060 //============================================================================
1061 Handle(TDocStd_Document) SALOMEDS_StudyManager_i::GetDocumentOfStudy(SALOMEDS::Study_ptr theStudy) {
1062   int a;
1063   int aNbDocs = _OCAFApp->NbDocuments(); 
1064   Handle(TDocStd_Document) aDocument;  
1065   for(a = 1; a <= aNbDocs ; a++) {
1066     _OCAFApp->GetDocument(a, aDocument);
1067     if (!aDocument.IsNull()) {
1068       SALOMEDS_SObject_i *  aSOServant = new SALOMEDS_SObject_i (aDocument->Main(),_orb);
1069       SALOMEDS::SObject_var aSO = SALOMEDS::SObject::_narrow(aSOServant->_this()); 
1070       SALOMEDS::Study_var aStudy = aSO->GetStudy();
1071       if(CORBA::is_nil(aStudy)) continue;  //The clipboard document ( hopefully :) )
1072       if (aStudy->StudyId() == theStudy->StudyId()) break;
1073       aDocument.Nullify();
1074     }
1075   }
1076
1077   return aDocument;
1078 }
1079
1080 //============================================================================
1081 /*! Function : CopyLabel
1082  *  Purpose  : 
1083  */
1084 //============================================================================
1085 void SALOMEDS_StudyManager_i::CopyLabel(const SALOMEDS::Study_ptr theSourceStudy,
1086                                         const SALOMEDS::Driver_ptr theEngine,
1087                                         const Standard_Integer theSourceStartDepth,
1088                                         const TDF_Label& theSource,
1089                                         const TDF_Label& theDestinationMain) {
1090   int a;
1091   TDF_Label aTargetLabel = theDestinationMain;
1092   TDF_Label aAuxTargetLabel = theDestinationMain.Father().FindChild(2);
1093   for(a = theSource.Depth() - theSourceStartDepth; a > 0 ; a--) {
1094     TDF_Label aSourceLabel = theSource;
1095     for(int aNbFather = 1; aNbFather < a; aNbFather++) aSourceLabel = aSourceLabel.Father();
1096     aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
1097     aAuxTargetLabel = aAuxTargetLabel.FindChild(aSourceLabel.Tag());
1098   }
1099   // iterate attributes
1100   TDF_AttributeIterator anAttrIterator(theSource);
1101   Handle(TDF_RelocationTable) aRT = new TDF_RelocationTable();
1102   for(; anAttrIterator.More(); anAttrIterator.Next()) {
1103     Handle(TDF_Attribute) anAttr = anAttrIterator.Value();
1104     if (!Handle(TDataStd_TreeNode)::DownCast(anAttr).IsNull()) continue; // never copy tree node attribute
1105     if (!Handle(SALOMEDS_TargetAttribute)::DownCast(anAttr).IsNull()) continue; // and target attribute
1106     
1107     if (!Handle(TDF_Reference)::DownCast(anAttr).IsNull()) { // reference copied as Comment in auxiliary tree
1108       TDF_Label aReferenced = Handle(TDF_Reference)::DownCast(anAttr)->Get();
1109       TCollection_AsciiString anEntry;
1110       TDF_Tool::Entry(aReferenced, anEntry);
1111       // store the value of name attribute of referenced label
1112       Handle(TDataStd_Name) aNameAttribute;
1113       if (aReferenced.FindAttribute(TDataStd_Name::GetID(), aNameAttribute)) {
1114         anEntry += " ";
1115         anEntry += aNameAttribute->Get();
1116       }
1117       TDataStd_Comment::Set(aAuxTargetLabel, TCollection_ExtendedString(anEntry));
1118       continue;
1119     }
1120     
1121     if (!Handle(SALOMEDS_IORAttribute)::DownCast(anAttr).IsNull()) { // IOR => ID and TMPFile of Engine
1122       TCollection_AsciiString anEntry;
1123       TDF_Tool::Entry(theSource, anEntry);
1124       SALOMEDS::SObject_var aSO = theSourceStudy->FindObjectID(anEntry.ToCString());
1125 //        if (theEngine->CanCopy(aSO)) {
1126         CORBA::Long anObjID;
1127 //      TCollection_ExtendedString aResStr(strdup((char*)(theEngine->CopyFrom(aSO, anObjID))));
1128           SALOMEDS::TMPFile_var aStream = theEngine->CopyFrom(aSO, anObjID);
1129           int aLen = aStream->length();
1130           TCollection_ExtendedString aResStr("");
1131           for(a = 0; a < aLen; a++) {
1132             aResStr += TCollection_ExtendedString(ToExtCharacter((Standard_Character)aStream[a]));
1133           }
1134           TDataStd_Integer::Set(aAuxTargetLabel, anObjID);
1135           TDataStd_Name::Set(aAuxTargetLabel, aResStr);
1136 //        }
1137       continue;
1138     }
1139     Handle(TDF_Attribute) aNewAttribute = anAttr->NewEmpty();
1140     aTargetLabel.AddAttribute(aNewAttribute);
1141     anAttr->Paste(aNewAttribute, aRT);
1142 //      aRT->SetRelocation(anAttr, aNewAttribute);
1143   }
1144 }
1145
1146 //============================================================================
1147 /*! Function : Copy
1148  *  Purpose  :
1149  */
1150 //============================================================================
1151 CORBA::Boolean SALOMEDS_StudyManager_i::Copy(SALOMEDS::SObject_ptr theObject) {
1152   // adoptation for alliances datamodel copy: without IOR attributes !!!
1153   bool aStructureOnly; // copy only SObjects and attributes without component help
1154   SALOMEDS::GenericAttribute_var anAttribute;
1155   aStructureOnly = !theObject->FindAttribute(anAttribute, "AttributeIOR");
1156
1157   // get component-engine
1158   SALOMEDS::Study_var aStudy = theObject->GetStudy();
1159
1160   SALOMEDS::Driver_var Engine;
1161   if (!aStructureOnly) {
1162     SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1163     CORBA::String_var IOREngine;
1164     if (!aComponent->ComponentIOR(IOREngine)) return false;
1165
1166     CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1167     Engine = SALOMEDS::Driver::_narrow(obj) ;
1168   }
1169   // CAF document of current study usage
1170   Handle(TDocStd_Document) aDocument = GetDocumentOfStudy(aStudy);
1171   if (aDocument.IsNull()) return false;
1172   // create new document for clipboard
1173   Handle(TDocStd_Document) aTargetDocument;
1174   _OCAFApp->NewDocument("SALOME_STUDY", aTargetDocument);
1175   // set component data type to the name attribute of root label
1176   if (!aStructureOnly) {
1177     TDataStd_Comment::Set(aTargetDocument->Main().Root(),
1178                           TCollection_ExtendedString(Engine->ComponentDataType()));
1179   }
1180   // set to the Root label integer attribute: study id
1181   TDataStd_Integer::Set(aTargetDocument->Main().Root(), aStudy->StudyId());
1182   // iterate all theObject's label children
1183   TDF_Label aStartLabel;
1184   char* aStartID = CORBA::string_dup(theObject->GetID());
1185   TDF_Tool::Label(aDocument->GetData(), aStartID, aStartLabel);
1186   delete(aStartID);
1187   Standard_Integer aSourceStartDepth = aStartLabel.Depth();
1188   
1189   // copy main source label
1190   CopyLabel(aStudy, Engine, aSourceStartDepth, aStartLabel, aTargetDocument->Main());
1191
1192   // copy all subchildren of the main source label (all levels)
1193   TDF_ChildIterator anIterator(aStartLabel, Standard_True);
1194   for(; anIterator.More(); anIterator.Next()) {
1195     CopyLabel(aStudy, Engine, aSourceStartDepth, anIterator.Value(), aTargetDocument->Main());
1196   }
1197   // done: free old clipboard document and 
1198   if (!_clipboard.IsNull()) {
1199 //      Handle(TDocStd_Owner) anOwner;
1200 //      if (_clipboard->Main().Root().FindAttribute(TDocStd_Owner::GetID(), anOwner)) {
1201 //        Handle(TDocStd_Document) anEmptyDoc;
1202 //        anOwner->SetDocument(anEmptyDoc);
1203 //      }
1204     _OCAFApp->Close(_clipboard);
1205   }
1206   _clipboard = aTargetDocument;
1207
1208   return true;
1209 }
1210 //============================================================================
1211 /*! Function : CanPaste
1212  *  Purpose  :
1213  */
1214 //============================================================================
1215 CORBA::Boolean SALOMEDS_StudyManager_i::CanPaste(SALOMEDS::SObject_ptr theObject) {
1216   if (_clipboard.IsNull()) return false;
1217
1218   Handle(TDataStd_Comment) aCompName;
1219   if (!_clipboard->Main().Root().FindAttribute(TDataStd_Comment::GetID(), aCompName)) return false;
1220   Handle(TDataStd_Integer) anObjID;
1221   if (!_clipboard->Main().Father().FindChild(2).FindAttribute(TDataStd_Integer::GetID(), anObjID))
1222     return false;
1223
1224   SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1225   if (aComponent->_is_nil()) return false;
1226   
1227   CORBA::String_var IOREngine;
1228   if (!aComponent->ComponentIOR(IOREngine)) return false;
1229   
1230   CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1231   SALOMEDS::Driver_var Engine = SALOMEDS::Driver::_narrow(obj) ;
1232   if (CORBA::is_nil(Engine)) return false;
1233   return Engine->CanPaste(TCollection_AsciiString(aCompName->Get()).ToCString(), anObjID->Get());
1234 }
1235 //============================================================================
1236 /*! Function : PasteLabel
1237  *  Purpose  :
1238  */
1239 //============================================================================
1240 TDF_Label SALOMEDS_StudyManager_i::PasteLabel(const SALOMEDS::Study_ptr theDestinationStudy,
1241                                               const SALOMEDS::Driver_ptr theEngine,
1242                                               const TDF_Label& theSource,
1243                                               const TDF_Label& theDestinationStart,
1244                                               const int theCopiedStudyID,
1245                                               const bool isFirstElement) {
1246
1247   // get corresponding source, target and auxiliary labels
1248   TDF_Label aTargetLabel = theDestinationStart;
1249   TDF_Label aAuxSourceLabel = theSource.Root().FindChild(2);
1250   int a;
1251   if (!isFirstElement) {
1252     for(a = theSource.Depth() - 1; a > 0 ; a--) {
1253       TDF_Label aSourceLabel = theSource;
1254       for(int aNbFather = 1; aNbFather < a; aNbFather++) aSourceLabel = aSourceLabel.Father();
1255       aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
1256       aAuxSourceLabel = aAuxSourceLabel.FindChild(aSourceLabel.Tag());
1257     }
1258   }
1259
1260   // check auxiliary label for TMPFile => IOR
1261   Handle(TDataStd_Name) aNameAttribute;
1262   if (aAuxSourceLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute)) {
1263     Handle(TDataStd_Integer) anObjID;
1264
1265     aAuxSourceLabel.FindAttribute(TDataStd_Integer::GetID(), anObjID);
1266     Handle(TDataStd_Comment) aComponentName;
1267     theSource.Root().FindAttribute(TDataStd_Comment::GetID(), aComponentName);
1268     CORBA::String_var aCompName = CORBA::string_dup(TCollection_AsciiString(aComponentName->Get()).ToCString());
1269
1270     if (theEngine->CanPaste(aCompName, anObjID->Get())) {
1271       SALOMEDS::TMPFile_var aTMPFil = new SALOMEDS::TMPFile();
1272       TCollection_ExtendedString aTMPStr = aNameAttribute->Get();
1273       int aLen = aTMPStr.Length();
1274       aTMPFil->length(aLen);
1275       for(a = 0; a < aLen; a++) {
1276         aTMPFil[a] = ToCharacter(aTMPStr.Value(a+1));
1277       }
1278 //        char* aTMPStr = strdup(TCollection_AsciiString(aNameAttribute->Get()).ToCString());
1279 //        int aLen = strlen(aTMPStr);
1280 //        SALOMEDS::TMPFile aTMPFil(aLen, aLen, (CORBA::Octet*)aTMPStr, 1);
1281       
1282       TCollection_AsciiString anEntry;
1283       TDF_Tool::Entry(aTargetLabel, anEntry);
1284       SALOMEDS::SObject_var aPastedSO = theDestinationStudy->FindObjectID(anEntry.ToCString());
1285       if (isFirstElement) {
1286         SALOMEDS::SObject_var aDestSO =
1287           theEngine->PasteInto(aTMPFil.in(),
1288                                anObjID->Get(),
1289                                aPastedSO->GetFatherComponent());
1290         TDF_Tool::Label(theDestinationStart.Data(), aDestSO->GetID(), aTargetLabel);
1291       } else theEngine->PasteInto(aTMPFil.in(),anObjID->Get(),aPastedSO);
1292     }
1293   }
1294
1295   // iterate attributes
1296   TDF_AttributeIterator anAttrIterator(theSource);
1297   Handle(TDF_RelocationTable) aRT = new TDF_RelocationTable();
1298   for(; anAttrIterator.More(); anAttrIterator.Next()) {
1299     Handle(TDF_Attribute) anAttr = anAttrIterator.Value();
1300     if (aTargetLabel.FindAttribute(anAttr->ID(), anAttr)) {
1301       aTargetLabel.ForgetAttribute(anAttr->ID());
1302       anAttr = anAttrIterator.Value();
1303     }
1304     Handle(TDF_Attribute) aNewAttribute = anAttr->NewEmpty();
1305     aTargetLabel.AddAttribute(aNewAttribute);
1306     anAttr->Paste(aNewAttribute, aRT);
1307 //      aRT->SetRelocation(anAttr, aNewAttribute);
1308   }
1309   // check auxiliary label for Comment => reference or name attribute of the referenced object
1310   Handle(TDataStd_Comment) aCommentAttribute;
1311   if (aAuxSourceLabel.FindAttribute(TDataStd_Comment::GetID(), aCommentAttribute)) {
1312     char * anEntry = new char[aCommentAttribute->Get().Length() + 1];
1313     strcpy(anEntry, TCollection_AsciiString(aCommentAttribute->Get()).ToCString());
1314     char* aNameStart = strchr(anEntry, ' ');
1315     if (aNameStart) {
1316       *aNameStart = '\0';
1317       aNameStart++;
1318     }
1319     if (theCopiedStudyID == theDestinationStudy->StudyId()) { // if copy to the same study, reanimate reference
1320       TDF_Label aRefLabel;
1321       TDF_Tool::Label(aTargetLabel.Data(), anEntry, aRefLabel);
1322       TDF_Reference::Set(aTargetLabel, aRefLabel);
1323       SALOMEDS_TargetAttribute::Set(aRefLabel)->Append(aTargetLabel); // target attributes structure support
1324     } else {
1325       if (aNameStart) TDataStd_Name::Set(aTargetLabel, aNameStart);
1326       else TDataStd_Name::Set(aTargetLabel, TCollection_ExtendedString("Reference to:")+anEntry);
1327     }
1328     delete [] anEntry;
1329   }
1330
1331   return aTargetLabel;
1332 }
1333 //============================================================================
1334 /*! Function : Paste
1335  *  Purpose  :
1336  */
1337 //============================================================================
1338 SALOMEDS::SObject_ptr SALOMEDS_StudyManager_i::Paste(SALOMEDS::SObject_ptr theObject)
1339      throw(SALOMEDS::StudyBuilder::LockProtection)
1340 {
1341   Unexpect aCatch(LockProtection);
1342   SALOMEDS::Study_var aStudy = theObject->GetStudy();
1343
1344   // if study is locked, then paste can't be done
1345   if (aStudy->GetProperties()->IsLocked())
1346     throw SALOMEDS::StudyBuilder::LockProtection();
1347
1348   // if there is no component name, then paste only SObjects and attributes: without component help
1349   Handle(TDataStd_Comment) aComponentName;
1350   bool aStructureOnly = !_clipboard->Main().Root().FindAttribute(TDataStd_Comment::GetID(), aComponentName);
1351
1352   // get copied study ID
1353   Handle(TDataStd_Integer) aStudyIDAttribute;
1354   if (!_clipboard->Main().Root().FindAttribute(TDataStd_Integer::GetID(), aStudyIDAttribute))
1355     return SALOMEDS::SObject::_nil();
1356   int aCStudyID = aStudyIDAttribute->Get();
1357
1358   // get component-engine
1359   SALOMEDS::Driver_var Engine;
1360   SALOMEDS::SComponent_var aComponent;
1361   if (!aStructureOnly) {
1362     aComponent = theObject->GetFatherComponent();
1363     CORBA::String_var IOREngine;
1364     if (!aComponent->ComponentIOR(IOREngine)) return SALOMEDS::SObject::_nil();
1365     CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1366     Engine = SALOMEDS::Driver::_narrow(obj) ;
1367   }
1368
1369   // CAF document of current study usage
1370   Handle(TDocStd_Document) aDocument = GetDocumentOfStudy(aStudy);
1371   if (aDocument.IsNull()) return SALOMEDS::SObject::_nil();
1372   // fill root inserted SObject
1373   TDF_Label aStartLabel;
1374   if (aStructureOnly) {
1375     TDF_Label anObjectLabel;
1376     TDF_Tool::Label(aDocument->GetData(), theObject->GetID(), anObjectLabel);
1377     aStartLabel = PasteLabel(aStudy, Engine, _clipboard->Main(), anObjectLabel, aCStudyID, false);
1378   } else {
1379     TDF_Label aComponentLabel;
1380     TDF_Tool::Label(aDocument->GetData(), aComponent->GetID(), aComponentLabel);
1381     aStartLabel = PasteLabel(aStudy, Engine, _clipboard->Main(), aComponentLabel, aCStudyID, true);
1382   }
1383
1384   // paste all sublebels
1385   TDF_ChildIterator anIterator(_clipboard->Main(), Standard_True);
1386   for(; anIterator.More(); anIterator.Next()) {
1387     PasteLabel(aStudy, Engine, anIterator.Value(), aStartLabel, aCStudyID, false);
1388   }
1389
1390   SALOMEDS_SObject_i *  so_servant = new SALOMEDS_SObject_i (aStartLabel, _orb);
1391   SALOMEDS::SObject_var so = SALOMEDS::SObject::_narrow(so_servant->_this()); 
1392
1393   return so._retn();
1394 }