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