1 // SALOME SALOMEDS : data structure of SALOME and sources of Salome data server
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : SALOMEDS_StudyManager_i.cxx
25 // Author : Yves FRICAUD
32 #include <OSD_Process.hxx>
33 #include <Quantity_Date.hxx>
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>
50 #include "SALOMEDS_StudyManager_i.hxx"
51 #include "SALOME_LifeCycleCORBA.hxx"
52 #include "SALOMEDS_SObject_i.hxx"
53 #include "SALOMEDS_Study_i.hxx"
55 #include "SALOMEDS_IORAttribute.hxx"
56 #include "SALOMEDS_PersRefAttribute.hxx"
57 #include "SALOMEDS_TargetAttribute.hxx"
59 #include "SALOMEDS_Tool.hxx"
60 #include "HDFexplorer.hxx"
63 #include <SALOMEconfig.h>
64 #include CORBA_SERVER_HEADER(SALOMEDS_Attributes)
66 #include "SALOME_GenericObj_i.hh"
67 #include "Utils_CorbaException.hxx"
68 #include "Utils_ExceptHandlers.hxx"
70 UNEXPECT_CATCH(SalomeException,SALOME::SALOME_Exception);
71 UNEXPECT_CATCH(LockProtection, SALOMEDS::StudyBuilder::LockProtection);
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
78 #include "utilities.h"
82 //===========================================================================
86 GetObject(const TDF_Label& theLabel, CORBA::ORB_ptr theORB)
89 Handle(SALOMEDS_IORAttribute) anAttr;
90 if(theLabel.FindAttribute(SALOMEDS_IORAttribute::GetID(),anAttr))
91 return theORB->string_to_object(TCollection_AsciiString(anAttr->Get()).ToCString());
94 return CORBA::Object::_nil();
98 PortableServer::ServantBase_var
99 GetServant(CORBA::Object_ptr theObject, PortableServer::POA_ptr thePOA)
101 if(CORBA::is_nil(theObject))
104 return thePOA->reference_to_servant(theObject);
112 //===========================================================================
113 //Function : LoadAttributes
114 //===========================================================================
115 static void ReadAttributes(SALOMEDS::Study_ptr theStudy,
116 SALOMEDS::SObject_ptr aSO,
117 HDFdataset* hdf_dataset)
119 hdf_dataset->OpenOnDisk();
121 SALOMEDS::GenericAttribute_var anAttr;
123 char* current_string = new char[hdf_dataset->GetSize()];
124 hdf_dataset->ReadFromDisk(current_string);
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();
134 MESSAGE("Read attribute "<<hdf_dataset->GetName())
135 anAttr = theStudy->NewBuilder()->FindOrCreateAttribute(aSO, hdf_dataset->GetName());
138 if (!CORBA::is_nil(anAttr)) {
139 anAttr->Restore(current_string);
140 MESSAGE("Restoring attribute "<<hdf_dataset->GetName()<<" by string '"<<current_string<<"' done")
142 MESSAGE(hdf_dataset->GetName());
143 MESSAGE("LoadAttributes: unknown types");
145 delete(current_string);
146 hdf_dataset->CloseOnDisk();
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)
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();
174 Translate_IOR_to_persistentID(theStudy,theBuilder,aSObject,theEngine,theIsMultiFile,theIsASCII);
178 //============================================================================
179 //Function : BuildlTree
180 //============================================================================
181 static void BuildTree (SALOMEDS::Study_ptr theStudy,HDFgroup* hdf_current_group)
183 hdf_current_group->OpenOnDisk();
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");
192 aSO = theStudy->CreateObjectID(Entry);
193 MESSAGE("BuildTree : Create a new label"<<Entry);
195 char name[HDF_NAME_MAX_LEN+1];
196 Standard_Integer nbsons = hdf_current_group->nInternalObjects();
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);
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
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
217 hdf_current_group->CloseOnDisk();
221 //============================================================================
222 /*! Function : SALOMEDS_StudyManager_i
223 * Purpose : SALOMEDS_StudyManager_i constructor
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)
233 // Study directory creation in the naming service : to register all
234 // open studies in the session
235 _name_service.Create_Directory("/Study");
239 //============================================================================
240 /*! Function : ~SALOMEDS_StudyManager_i
241 * Purpose : SALOMEDS_StudyManager_i destructor
243 //============================================================================
244 SALOMEDS_StudyManager_i::~SALOMEDS_StudyManager_i()
246 // Destroy directory to register open studies
247 _name_service.Destroy_Directory("/Study");
250 //============================================================================
251 /*! Function : register_name
252 * Purpose : Register the study Manager in the naming service under the
255 //============================================================================
256 void SALOMEDS_StudyManager_i::register_name(char * theName) {
257 SALOMEDS::StudyManager_var aManager(_this());
258 _name_service.Register(aManager.in(),theName);
262 //============================================================================
263 /*! Function : NewStudy
264 * Purpose : Create a New Study of name study_name
266 //============================================================================
267 SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::NewStudy(const char* theStudyName)
269 Handle(TDocStd_Document) aDocument;
270 _OCAFApp->NewDocument("SALOME_STUDY",aDocument);
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();
276 //Study->StudyId( _OCAFApp->NbDocuments() );
278 aStudyServant->StudyId( _IDcounter );
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" );
285 _name_service.Register(aStudy, theStudyName);
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);
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());
303 return aStudy._retn();
306 //============================================================================
308 * Purpose : Open a Study from it's persistent reference
310 //============================================================================
311 SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::Open(const char* theURL)
312 throw(SALOME::SALOME_Exception)
314 Unexpect aCatch(SalomeException);
315 MESSAGE("Begin of SALOMEDS_StudyManager_i::Open");
317 bool isASCII = false;
318 std::ostringstream anURLStream;
319 if (HDFascii::isASCII(theURL)) {
321 auto_ptr<char> aResultPath(HDFascii::ConvertFromASCIIToHDF(theURL));
322 anURLStream<<aResultPath.get()<<"hdf_from_ascii.hdf";
326 std::string aHDFUrl = anURLStream.str();
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())));
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);
339 MESSAGE("Open : Creating the CORBA servant holding it... ");
341 // Temporary aStudyUrl in place of study name
342 Handle(TDocStd_Document) Doc;
343 _OCAFApp->NewDocument("SALOME_STUDY",Doc);
345 SALOMEDS_Study_i* aStudyServant = new SALOMEDS_Study_i(this,Doc,theURL);
346 SALOMEDS::Study_var aStudy = aStudyServant->_this();
348 // aStudy->StudyId( _OCAFApp->NbDocuments() );
350 aStudy->StudyId( _IDcounter );
352 // Assign the value of the URL in the study object
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);
360 SALOMEDS_PersRefAttribute::Set(Doc->Main(),const_cast<char*>(theURL));
362 if (!hdf_file->ExistInternalObject("STUDY_STRUCTURE")) {
363 MESSAGE("SALOMEDS_StudyManager::Open : the study is empty");
364 return aStudy._retn();
367 //Create the Structure of the OCAF Document
368 HDFgroup *hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file.get());
370 Handle(TDF_Data) DF = Doc->GetData();
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);
381 hdf_file->CloseOnDisk();
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" );
388 CORBA::String_var aString(aStudy->Name());
389 _name_service.Register(aStudy,aString.in());
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);
400 return aStudy._retn();
405 //============================================================================
407 * Purpose : Close a study.
408 * If the study hasn't been saved, ask the user to confirm the
409 * close action without saving
411 //============================================================================
412 void SALOMEDS_StudyManager_i::Close(SALOMEDS::Study_ptr aStudy)
414 if(aStudy->_is_nil()) return;
416 aStudy->RemovePostponed(-1);
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());
427 //============================================================================
429 * Purpose : Save a Study to it's persistent reference
431 //============================================================================
432 void SALOMEDS_StudyManager_i::Save(SALOMEDS::Study_ptr theStudy, CORBA::Boolean theMultiFile)
434 CORBA::String_var anURL = theStudy->URL();
435 if(strcmp(anURL.in(),"") == 0){
436 MESSAGE( "No path specified to save the study. Nothing done");
438 _SaveAs(anURL,theStudy,theMultiFile,false);
442 void SALOMEDS_StudyManager_i::SaveASCII(SALOMEDS::Study_ptr theStudy, CORBA::Boolean theMultiFile)
444 CORBA::String_var anURL = theStudy->URL();
445 if(strcmp(anURL.in(),"") == 0){
446 MESSAGE( "No path specified to save the study. Nothing done");
448 _SaveAs(anURL,theStudy,theMultiFile,true);
452 //=============================================================================
453 /*! Function : SaveAs
454 * Purpose : Save a study to the persistent reference aUrl
456 //============================================================================
457 void SALOMEDS_StudyManager_i::SaveAs(const char* aUrl, SALOMEDS::Study_ptr theStudy, CORBA::Boolean theMultiFile)
459 _SaveAs(aUrl,theStudy,theMultiFile, false);
463 void SALOMEDS_StudyManager_i::SaveAsASCII(const char* aUrl, SALOMEDS::Study_ptr theStudy, CORBA::Boolean theMultiFile)
465 _SaveAs(aUrl,theStudy,theMultiFile, true);
468 //============================================================================
469 /*! Function : GetOpenStudies
470 * Purpose : Get name list of open studies in the session
472 //============================================================================
473 SALOMEDS::ListOfOpenStudies* SALOMEDS_StudyManager_i::GetOpenStudies()
475 // MESSAGE("Begin of GetOpenStudies");
476 SALOMEDS::ListOfOpenStudies_var aStudyList = new SALOMEDS::ListOfOpenStudies;
478 if(!_name_service.Change_Directory("/Study")){
479 MESSAGE("No active study in this session");
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]) ;
489 return aStudyList._retn();
492 //============================================================================
493 /*! Function : GetStudyByName
494 * Purpose : Get a study from its name
496 //============================================================================
498 SALOMEDS_StudyManager_i::GetStudyByName(const char* theStudyName)
500 SALOMEDS::Study_var aStudy;
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...
508 if(_name_service.Find(theStudyName) > 0){
510 CORBA::Object_ptr anObj = _name_service.Resolve(theStudyName) ;
511 aStudy = SALOMEDS::Study::_narrow(anObj);
512 MESSAGE("Study " << theStudyName << " found in the naming service");
514 MESSAGE("Study " << theStudyName << " not found in the naming service");
516 return aStudy._retn();
519 //============================================================================
520 /*! Function : GetStudyByID
521 * Purpose : Get a study from its ID
523 //============================================================================
525 SALOMEDS_StudyManager_i::GetStudyByID(CORBA::Short aStudyID)
527 SALOMEDS::Study_var aStudy;
529 if(!_name_service.Change_Directory("/Study")){
530 MESSAGE("No active study in this session");
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();
545 MESSAGE("Study " << aStudyName << " not found in the naming service");
550 return aStudy._retn();
552 //============================================================================
553 /*! Function : SaveAttributes
554 * Purpose : Save attributes for object
556 //============================================================================
557 static void SaveAttributes(SALOMEDS::SObject_ptr SO, HDFgroup *hdf_group_sobject) {
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
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
588 //=============================================================================
589 /*! Function : _SaveProperties
590 * Purpose : save the study properties in HDF file
592 //============================================================================
593 void SALOMEDS_StudyManager_i::_SaveProperties(SALOMEDS::Study_ptr aStudy, HDFgroup *hdf_group)
595 // add modifications list (user and date of save)
596 SALOMEDS::AttributeStudyProperties_ptr aProp = aStudy->GetProperties();
597 SALOMEDS::StudyBuilder_var SB= aStudy->NewBuilder();
599 int aLocked = aProp->IsLocked();
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()));
611 aProp->SetLocked(Standard_True);
612 // SB->CommitCommand();
614 SALOMEDS::StringSeq_var aNames;
615 SALOMEDS::LongSeq_var aMinutes, aHours, aDays, aMonths, aYears;
616 aProp->GetModificationsList(aNames,aMinutes,aHours,aDays,aMonths,aYears,true);
618 std::ostringstream aPropertyList;
619 aPropertyList<<(strlen(aProp->GetCreationMode()) != 0? aProp->GetCreationMode()[0] : '0');
620 aPropertyList<<(aProp->IsLocked()? 'l': 'u');
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);
632 std::string aProperty = aPropertyList.str();
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);
644 //=============================================================================
645 /*! Function : _SaveAs
646 * Purpose : save the study in HDF file
648 //============================================================================
649 void SALOMEDS_StudyManager_i::_SaveAs(const char* aUrl,
650 SALOMEDS::Study_ptr aStudy,
651 CORBA::Boolean theMultiFile,
652 CORBA::Boolean theASCII)
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
661 HDFgroup *hdf_group_study_structure =0;
662 HDFgroup *hdf_sco_group =0;
663 HDFgroup *hdf_sco_group2 =0;
665 HDFgroup *hdf_group_datacomponent =0;
666 HDFdataset *hdf_dataset =0;
668 hdf_int32 name_len = 0;
670 int aLocked = aStudy->GetProperties()->IsLocked();
671 if (aLocked) aStudy->GetProperties()->SetLocked(false);
673 SALOMEDS::StudyBuilder_var SB= aStudy->NewBuilder();
675 ASSERT(!CORBA::is_nil(aStudy));
678 // mpv 15.12.2003: for saving components we have to load all data from all modules
680 SALOMEDS::SComponentIterator_var itcomponent1 = aStudy->NewComponentIterator();
681 for (; itcomponent1->More(); itcomponent1->Next())
683 SALOMEDS::SComponent_var sco = itcomponent1->Value();
684 // if there is an associated Engine call its method for saving
685 CORBA::String_var IOREngine;
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);
694 if (!aName->_is_nil()) {
696 CORBA::String_var aCompType = aName->Value();
699 CORBA::String_var aFactoryType;
700 if (strcmp(aCompType, "SUPERV") == 0) aFactoryType = "SuperVisionContainer";
701 else aFactoryType = "FactoryServer";
703 Engines::Component_var aComp =
704 SALOME_LifeCycleCORBA(&_name_service).FindOrLoad_Component(aFactoryType, aCompType);
706 if (aComp->_is_nil()) {
707 Engines::Component_var aComp =
708 SALOME_LifeCycleCORBA(&_name_service).FindOrLoad_Component("FactoryServerPy", aCompType);
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);
720 MESSAGE("Can not restore information to resave it");
727 CORBA::String_var anOldName = aStudy->Name();
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");
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();
742 SALOMEDS::SComponentIterator_var itcomponent = aStudy->NewComponentIterator();
744 //SRN: Added 17 Nov, 2003
745 SALOMEDS::SObject_var anAutoSaveSO = aStudy->FindObjectID(AUTO_SAVE_TAG);
748 for (; itcomponent->More(); itcomponent->Next())
750 SALOMEDS::SComponent_var sco = itcomponent->Value();
752 CORBA::String_var scoid = sco->GetID();
753 hdf_sco_group = new HDFgroup(scoid,hdf_group_datacomponent);
754 hdf_sco_group->CreateOnDisk();
756 CORBA::String_var componentDataType = sco->ComponentDataType();
757 MESSAGE ( "Look for an engine for data type :"<< componentDataType);
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)) {
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) {
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)
786 } // if(nbRows > 0 && aTable->GetNbColumns() > 1)
788 } // if(anAutoSaveSO->FindAttribute(aTable, "AttributeTableOfString")
790 } // if(SB->IsGUID(AUTO_SAVE_GUID)
794 CORBA::String_var IOREngine;
795 if (sco->ComponentIOR(IOREngine))
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) ;
802 if (!CORBA::is_nil(Engine))
804 MESSAGE ( "Save the data of type:"<< componentDataType);
805 MESSAGE("Engine :"<<Engine->ComponentDataType());
807 SALOMEDS::TMPFile_var aStream;
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);
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
816 aHDFSize[0] = aStream->length();
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();
823 // store multifile state
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
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
839 Translate_IOR_to_persistentID (aStudy,SB,sco,Engine,theMultiFile, theASCII);
840 MESSAGE("After Translate_IOR_to_persistentID");
842 // Creation of the persistance reference attribute
845 hdf_sco_group->CloseOnDisk();
846 hdf_sco_group=0; // will be deleted by hdf_group_datacomponent destructor
848 hdf_group_datacomponent->CloseOnDisk();
849 hdf_group_datacomponent =0; // will be deleted by hdf_file destructor
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();
858 // save component attributes
859 SALOMEDS::SComponentIterator_var itcomp = aStudy->NewComponentIterator();
860 for (; itcomp->More(); itcomp->Next())
862 SALOMEDS::SComponent_var SC = itcomp->Value();
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");
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
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
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
912 _SaveProperties(aStudy, hdf_group_study_structure);
914 hdf_group_study_structure->CloseOnDisk();
915 hdf_file->CloseOnDisk();
917 _name_service.Change_Directory("/Study");
918 _name_service.Destroy_Name(anOldName);
919 _name_service.Register(aStudy, aStudy->Name());
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...
927 MESSAGE( "HDFexception ! " )
929 if (theASCII) { // save file in ASCII format
930 HDFascii::ConvertFromHDFToASCII(aUrl, true);
934 //============================================================================
935 /*! Function : _SaveObject
938 //============================================================================
939 void SALOMEDS_StudyManager_i::_SaveObject(SALOMEDS::Study_ptr aStudy,
940 SALOMEDS::SObject_ptr SC,
941 HDFgroup *hdf_group_datatype)
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;
948 SALOMEDS::ChildIterator_var itchild = aStudy->NewChildIterator(SC);
949 for (; itchild->More(); itchild->Next())
951 SALOMEDS::SObject_var SO = itchild->Value();
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()) {
959 subchild->InitEx(true);
961 for (; subchild->More() && anEmpty; subchild->Next())
962 if (subchild->Value()->GetAllAttributes()->length() != 0 ||
963 subchild->Value()->ReferencedObject(RefSO)) anEmpty = false;
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
980 //============================================================================
981 /*! Function : _SubstituteSlash
984 //============================================================================
986 std::string SALOMEDS_StudyManager_i::_SubstituteSlash(const char *theUrl)
989 TCollection_ExtendedString aUrl(const_cast<char*>(theUrl));
990 aUrl.ChangeAll(ToExtCharacter('/'),ToExtCharacter(':'));
991 TCollection_AsciiString ch(aUrl);
992 return ch.ToCString();
995 //============================================================================
996 /*! Function : CanCopy
999 //============================================================================
1000 CORBA::Boolean SALOMEDS_StudyManager_i::CanCopy(SALOMEDS::SObject_ptr theObject) {
1001 SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1003 if(aComponent->_is_nil())
1006 if(aComponent == theObject)
1009 CORBA::String_var IOREngine;
1010 if(!aComponent->ComponentIOR(IOREngine))
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))
1018 return Engine->CanCopy(theObject);
1021 //============================================================================
1022 /*! Function : CopyLabel
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)
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());
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
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)) {
1057 anEntry += aNameAttribute->Get();
1059 TDataStd_Comment::Set(aAuxTargetLabel, TCollection_ExtendedString(anEntry));
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]));
1074 TDataStd_Integer::Set(aAuxTargetLabel, anObjID);
1075 TDataStd_Name::Set(aAuxTargetLabel, aResStr);
1078 Handle(TDF_Attribute) aNewAttribute = anAttr->NewEmpty();
1079 aTargetLabel.AddAttribute(aNewAttribute);
1080 anAttr->Paste(aNewAttribute, aRT);
1081 // aRT->SetRelocation(anAttr, aNewAttribute);
1085 //============================================================================
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");
1096 PortableServer::ServantBase_var aServant = GetServant(theObject,_poa);
1097 SALOMEDS_SObject_i* aSObject = dynamic_cast<SALOMEDS_SObject_i*>(aServant.in());
1098 if(aSObject == NULL)
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))
1109 CORBA::Object_var anObj = _orb->string_to_object(aString);
1110 anEngine = SALOMEDS::Driver::_narrow(anObj) ;
1113 // CAF document of current study usage
1114 Handle(TDocStd_Document) aDocument = aStudy->GetDocument();
1115 if(aDocument.IsNull())
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()));
1126 // set to the Root label integer attribute: study id
1127 TDataStd_Integer::Set(aTargetDocument->Main().Root(),aStudy->StudyId());
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();
1135 // copy main source label
1136 CopyLabel(aStudy,anEngine,aSourceStartDepth,aStartLabel,aTargetDocument->Main());
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());
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);
1151 _OCAFApp->Close(_clipboard);
1154 _clipboard = aTargetDocument;
1158 //============================================================================
1159 /*! Function : CanPaste
1162 //============================================================================
1163 CORBA::Boolean SALOMEDS_StudyManager_i::CanPaste(SALOMEDS::SObject_ptr theObject) {
1164 if (_clipboard.IsNull()) return false;
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))
1172 SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1173 if(aComponent->_is_nil())
1176 CORBA::String_var IOREngine;
1177 if(!aComponent->ComponentIOR(IOREngine))
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))
1185 return Engine->CanPaste(TCollection_AsciiString(aCompName->Get()).ToCString(),anObjID->Get());
1187 //============================================================================
1188 /*! Function : PasteLabel
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) {
1199 // get corresponding source, target and auxiliary labels
1200 TDF_Label aTargetLabel = theDestinationStart;
1201 TDF_Label aAuxSourceLabel = theSource.Root().FindChild(2);
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());
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;
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));
1229 TCollection_AsciiString anEntry;
1230 TDF_Tool::Entry(aTargetLabel, anEntry);
1231 SALOMEDS::SObject_var aPastedSO = theDestinationStudy->FindObjectID(anEntry.ToCString());
1233 SALOMEDS::SObject_var aDestSO =
1234 theEngine->PasteInto(aTMPFil.in(),
1236 aPastedSO->GetFatherComponent());
1237 TDF_Tool::Label(theDestinationStart.Data(), aDestSO->GetID(), aTargetLabel);
1239 theEngine->PasteInto(aTMPFil.in(),anObjID->Get(),aPastedSO);
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();
1252 Handle(TDF_Attribute) aNewAttribute = anAttr->NewEmpty();
1253 aTargetLabel.AddAttribute(aNewAttribute);
1254 anAttr->Paste(aNewAttribute, aRT);
1255 // aRT->SetRelocation(anAttr, aNewAttribute);
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
1268 if(aNameStart != std::string::npos)
1269 TDataStd_Name::Set(aTargetLabel, &anEntry[aNameStart+1]);
1271 TDataStd_Name::Set(aTargetLabel,
1272 TCollection_ExtendedString("Reference to:") +
1273 const_cast<char*>(anEntry.c_str()));
1277 return aTargetLabel;
1279 //============================================================================
1280 /*! Function : Paste
1283 //============================================================================
1284 SALOMEDS::SObject_ptr SALOMEDS_StudyManager_i::Paste(SALOMEDS::SObject_ptr theObject)
1285 throw(SALOMEDS::StudyBuilder::LockProtection)
1287 Unexpect aCatch(LockProtection);
1289 PortableServer::ServantBase_var aServant = GetServant(theObject,_poa);
1290 SALOMEDS_SObject_i* aSObject = dynamic_cast<SALOMEDS_SObject_i*>(aServant.in());
1291 if(aSObject == NULL)
1294 SALOMEDS_Study_i* aStudy = aSObject->GetStudyServant();
1296 // if study is locked, then paste can't be done
1297 if (aStudy->GetProperties()->IsLocked())
1298 throw SALOMEDS::StudyBuilder::LockProtection();
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);
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();
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();
1318 CORBA::Object_var anObj = _orb->string_to_object(aString);
1319 anEngine = SALOMEDS::Driver::_narrow(anObj) ;
1322 // CAF document of current study usage
1323 Handle(TDocStd_Document) aDocument = aStudy->GetDocument();
1324 if (aDocument.IsNull())
1325 return SALOMEDS::SObject::_nil();
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);
1335 TDF_Label aComponentLabel;
1336 TDF_Tool::Label(aDocument->GetData(),aComponent->GetID(),aComponentLabel);
1337 aStartLabel = PasteLabel(aStudy,anEngine,_clipboard->Main(),aComponentLabel,aCStudyID,true);
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);
1346 SALOMEDS_SObject_i* aSObjectServant = SALOMEDS_SObject_i::New(aStudy,aStartLabel);
1348 return aSObjectServant->_this();