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