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