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.hxx"
51 #include "SALOMEDS_StudyManager_i.hxx"
52 #include "SALOME_LifeCycleCORBA.hxx"
54 #include "SALOMEDS_Study_i.hxx"
55 #include "SALOMEDS_SObject_i.hxx"
56 #include "SALOMEDS_StudyBuilder_i.hxx"
58 #include "SALOMEDS_IORAttribute.hxx"
59 #include "SALOMEDS_PersRefAttribute.hxx"
60 #include "SALOMEDS_TargetAttribute.hxx"
62 #include "SALOMEDS_Tool.hxx"
63 #include "HDFexplorer.hxx"
66 #include <SALOMEconfig.h>
67 #include CORBA_SERVER_HEADER(SALOMEDS_Attributes)
69 #include "SALOME_GenericObj_i.hh"
70 #include "Utils_CorbaException.hxx"
71 #include "Utils_ExceptHandlers.hxx"
73 UNEXPECT_CATCH(SalomeException,SALOME::SALOME_Exception);
74 UNEXPECT_CATCH(LockProtection, SALOMEDS::StudyBuilder::LockProtection);
76 #define USE_CASE_LABEL_ID "0:2"
77 #define AUTO_SAVE_GUID "128268A3-71C9-4036-89B1-F81BD6A4FCF2"
78 #define AUTO_SAVE_TAG "0:8"
79 #define AUTO_SAVE_TIME_OUT_IN_SECONDS 1200
81 #include "utilities.h"
85 //===========================================================================
89 GetObject(const TDF_Label& theLabel, CORBA::ORB_ptr theORB)
92 Handle(SALOMEDS_IORAttribute) anAttr;
93 if(theLabel.FindAttribute(SALOMEDS_IORAttribute::GetID(),anAttr))
94 return theORB->string_to_object(TCollection_AsciiString(anAttr->Get()).ToCString());
97 return CORBA::Object::_nil();
101 PortableServer::ServantBase_var
102 GetServant(CORBA::Object_ptr theObject, PortableServer::POA_ptr thePOA)
104 if(CORBA::is_nil(theObject))
107 return thePOA->reference_to_servant(theObject);
115 //===========================================================================
116 //Function : LoadAttributes
117 //===========================================================================
120 ReadAttributes(SALOMEDS_Study_i* theStudy,
121 SALOMEDS::SObject_ptr aSO,
122 HDFdataset* hdf_dataset)
124 hdf_dataset->OpenOnDisk();
126 SALOMEDS::GenericAttribute_var anAttr;
128 char* current_string = new char[hdf_dataset->GetSize()];
129 hdf_dataset->ReadFromDisk(current_string);
131 if (!strcmp(hdf_dataset->GetName(),"COMPONENTDATATYPE")) {
132 anAttr = theStudy->GetBuilder()->FindOrCreateAttribute(aSO, "AttributeComment");
133 } else if (!strcmp(hdf_dataset->GetName(),"Reference")) {
134 theStudy->GetBuilder()->Addreference(aSO, theStudy->CreateObjectID(current_string));
135 delete(current_string);
136 hdf_dataset->CloseOnDisk();
139 MESSAGE("Read attribute "<<hdf_dataset->GetName())
140 anAttr = theStudy->GetBuilder()->FindOrCreateAttribute(aSO, hdf_dataset->GetName());
143 if (!CORBA::is_nil(anAttr)) {
144 anAttr->Restore(current_string);
145 MESSAGE("Restoring attribute "<<hdf_dataset->GetName()<<" by string '"<<current_string<<"' done")
147 MESSAGE(hdf_dataset->GetName());
148 MESSAGE("LoadAttributes: unknown types");
150 delete(current_string);
151 hdf_dataset->CloseOnDisk();
154 //============================================================================
155 //Function : Translate_IOR_to_persistentID
156 //============================================================================
157 static void Translate_IOR_to_persistentID(SALOMEDS_Study_i* theStudy,
158 SALOMEDS_StudyBuilder_i* theBuilder,
159 SALOMEDS::SObject_ptr theSObject,
160 SALOMEDS::Driver_ptr theEngine,
161 CORBA::Boolean theIsMultiFile,
162 CORBA::Boolean theIsASCII)
164 MESSAGE("In Translate_IOR_to_persistentID");
165 SALOMEDS_ChildIterator_i anIter = theStudy->GetChildIterator(theSObject);
166 for(; anIter.More(); anIter.Next()){
167 SALOMEDS::GenericAttribute_var anAttr;
168 SALOMEDS::SObject_var aSObject = anIter.Value();
169 if(aSObject->FindAttribute(anAttr,"AttributeIOR")){
170 SALOMEDS::AttributeIOR_var anIOR = SALOMEDS::AttributeIOR::_narrow(anAttr);
171 CORBA::String_var aString = anIOR->Value();
172 CORBA::String_var aPersistentID =
173 theEngine->IORToLocalPersistentID(aSObject,aString,theIsMultiFile,theIsASCII);
174 anAttr = theBuilder->FindOrCreateAttribute(aSObject,"AttributePersistentRef");
175 SALOMEDS::AttributePersistentRef_var aPersistentRef = SALOMEDS::AttributePersistentRef::_narrow(anAttr);
176 aPersistentRef->SetValue(aPersistentID);
177 aString = aSObject->GetID();
179 Translate_IOR_to_persistentID(theStudy,theBuilder,aSObject,theEngine,theIsMultiFile,theIsASCII);
183 //============================================================================
184 //Function : BuildlTree
185 //============================================================================
188 BuildTree(SALOMEDS_Study_i* theStudy, HDFgroup* hdf_current_group)
190 hdf_current_group->OpenOnDisk();
192 SALOMEDS::SObject_var aSO;
193 char* Entry = hdf_current_group->GetName();
194 if (strcmp(Entry,"STUDY_STRUCTURE") == 0) {
195 MESSAGE("find the root of the document");
196 aSO = theStudy->CreateObjectID("0:1");
199 aSO = theStudy->CreateObjectID(Entry);
200 MESSAGE("BuildTree : Create a new label"<<Entry);
202 char name[HDF_NAME_MAX_LEN+1];
203 Standard_Integer nbsons = hdf_current_group->nInternalObjects();
205 for (Standard_Integer i=0; i<nbsons; i++) {
206 hdf_current_group->InternalObjectIndentify(i,name);
207 if (strncmp(name, "INTERNAL_COMPLEX",16) == 0) continue;
208 hdf_object_type type = hdf_current_group->InternalObjectType(name);
210 if (type == HDF_DATASET) {
211 MESSAGE("--> Dataset: Internal Object Name : " << name);
212 HDFdataset* new_dataset = new HDFdataset(name,hdf_current_group);
213 ReadAttributes(theStudy,aSO,new_dataset);
214 new_dataset = 0; // will be deleted by father destructor
217 else if (type == HDF_GROUP) {
218 MESSAGE( "--> Group: Internal Object Name : " << name);
219 HDFgroup* new_group = new HDFgroup(name,hdf_current_group);
220 BuildTree(theStudy, new_group);
221 new_group = 0; // will be deleted by father destructor
224 hdf_current_group->CloseOnDisk();
228 //============================================================================
229 /*! Function : SALOMEDS_StudyManager_i
230 * Purpose : SALOMEDS_StudyManager_i constructor
232 //============================================================================
233 SALOMEDS_StudyManager_i::SALOMEDS_StudyManager_i(CORBA::ORB_ptr theORB,
234 PortableServer::POA_ptr thePOA):
235 _orb(CORBA::ORB::_duplicate(theORB)),
236 _poa(PortableServer::POA::_duplicate(thePOA)),
237 _OCAFApp(new SALOMEDS_OCAFApplication()),
238 _name_service(theORB)
240 // Study directory creation in the naming service : to register all
241 // open studies in the session
242 _name_service.Create_Directory("/Study");
246 //============================================================================
247 /*! Function : ~SALOMEDS_StudyManager_i
248 * Purpose : SALOMEDS_StudyManager_i destructor
250 //============================================================================
251 SALOMEDS_StudyManager_i::~SALOMEDS_StudyManager_i()
253 // Destroy directory to register open studies
254 _name_service.Destroy_Directory("/Study");
258 SALOMEDS_StudyManager_i::DownCast(SALOMEDS::Study_ptr theStudy) const
260 if(!CORBA::is_nil(theStudy)){
261 PortableServer::POA_var aPOA = GetPOA();
262 PortableServer::ServantBase_var aServant = SALOMEDS::GetServant(theStudy,aPOA);
264 return dynamic_cast<SALOMEDS_Study_i*>(aServant.in());
269 //============================================================================
270 /*! Function : register_name
271 * Purpose : Register the study Manager in the naming service under the
274 //============================================================================
275 void SALOMEDS_StudyManager_i::register_name(char * theName) {
276 SALOMEDS::StudyManager_var aManager(_this());
277 _name_service.Register(aManager.in(),theName);
281 //============================================================================
282 /*! Function : NewStudy
283 * Purpose : Create a New Study of name study_name
285 //============================================================================
286 SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::NewStudy(const char* theStudyName)
288 SALOMEDS::Locker lock;
290 Handle(TDocStd_Document) aDocument;
291 _OCAFApp->NewDocument("SALOME_STUDY",aDocument);
293 MESSAGE("NewStudy : Creating the CORBA servant holding it... ");
294 SALOMEDS_Study_i* aStudyServant = new SALOMEDS_Study_i(this,aDocument,theStudyName);
295 SALOMEDS::Study_var aStudy = aStudyServant->_this();
297 //Study->StudyId( _OCAFApp->NbDocuments() );
299 aStudyServant->StudyId( _IDcounter );
301 // Register study in the naming service
302 // Path to acces the study
303 if(!_name_service.Change_Directory("/Study")){
304 MESSAGE( "Unable to access the study directory" );
306 _name_service.Register(aStudy, theStudyName);
308 // Assign the value of the IOR in the study->root
309 CORBA::String_var anIOR = _orb->object_to_string(aStudy);
310 SALOMEDS_IORAttribute::Set(aDocument->Main().Root(),
311 const_cast<char*>(anIOR.in()),
314 // set Study properties
315 SALOMEDS::AttributeStudyProperties_var aProp = aStudyServant->GetProperties();
316 OSD_Process aProcess;
317 Quantity_Date aDate = aProcess.SystemDate();
318 aProp->SetCreationDate(CORBA::Long(aDate.Minute()),
319 CORBA::Long(aDate.Hour()),
320 CORBA::Long(aDate.Day()),
321 CORBA::Long(aDate.Month()),
322 CORBA::Long(aDate.Year()));
323 aProp->SetCreationMode("from scratch");
324 aProp->SetUserName(aProcess.UserName().ToCString());
326 return aStudy._retn();
329 //============================================================================
331 * Purpose : Open a Study from it's persistent reference
333 //============================================================================
334 SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::Open(const char* theURL)
335 throw(SALOME::SALOME_Exception)
337 SALOMEDS::Locker lock;
339 Unexpect aCatch(SalomeException);
340 MESSAGE("Begin of SALOMEDS_StudyManager_i::Open");
342 bool isASCII = false;
343 std::ostringstream anURLStream;
344 if (HDFascii::isASCII(theURL)) {
346 auto_ptr<char> aResultPath(HDFascii::ConvertFromASCIIToHDF(theURL));
347 anURLStream<<aResultPath.get()<<"hdf_from_ascii.hdf";
351 std::string aHDFUrl = anURLStream.str();
353 // open the HDFFile (all related hdf objects will be deleted )
354 auto_ptr<HDFfile> hdf_file(new HDFfile(const_cast<char*>(aHDFUrl.c_str())));
357 hdf_file->OpenOnDisk(HDF_RDONLY);// mpv: was RDWR, but opened file can be write-protected too
358 }catch(HDFexception){
359 std::ostringstream aStream;
360 aStream<<"Can't open file "<<theURL;
361 std::string eStr = aStream.str();
362 THROW_SALOME_CORBA_EXCEPTION(eStr.c_str(),SALOME::BAD_PARAM);
364 MESSAGE("Open : Creating the CORBA servant holding it... ");
366 // Temporary aStudyUrl in place of study name
367 Handle(TDocStd_Document) Doc;
368 _OCAFApp->NewDocument("SALOME_STUDY",Doc);
370 SALOMEDS_Study_i* aStudyServant = new SALOMEDS_Study_i(this,Doc,theURL);
371 SALOMEDS::Study_var aStudy = aStudyServant->_this();
373 // aStudy->StudyId( _OCAFApp->NbDocuments() );
375 aStudy->StudyId( _IDcounter );
377 // Assign the value of the URL in the study object
378 aStudyServant->URL(theURL);
381 // Assign the value of the IOR in the study->root
382 CORBA::String_var anIOR = _orb->object_to_string(aStudy);
383 SALOMEDS_IORAttribute::Set(Doc->Main().Root(),
384 const_cast<char*>(anIOR.in()),
387 SALOMEDS_PersRefAttribute::Set(Doc->Main(),const_cast<char*>(theURL));
389 if (!hdf_file->ExistInternalObject("STUDY_STRUCTURE")) {
390 MESSAGE("SALOMEDS_StudyManager::Open : the study is empty");
391 return aStudy._retn();
394 //Create the Structure of the OCAF Document
395 HDFgroup *hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file.get());
397 Handle(TDF_Data) DF = Doc->GetData();
400 BuildTree(aStudyServant,hdf_group_study_structure);
401 }catch(HDFexception){
402 std::ostringstream aStream;
403 aStream<<"Can't open file "<<theURL;
404 std::string eStr = aStream.str();
405 THROW_SALOME_CORBA_EXCEPTION(eStr.c_str(),SALOME::BAD_PARAM);
408 hdf_file->CloseOnDisk();
410 // Register study in the naming service
411 // Path to acces the study
412 if(!_name_service.Change_Directory("/Study")){
413 MESSAGE( "Unable to access the study directory" );
415 CORBA::String_var aString(aStudyServant->Name());
416 _name_service.Register(aStudy,aString.in());
420 SALOMEDS::ListOfFileNames_var aFilesToRemove = new SALOMEDS::ListOfFileNames;
421 aFilesToRemove->length(1);
422 std::string aDir = SALOMEDS_Tool::GetDirFromPath(aHDFUrl);
423 aFilesToRemove[0] = CORBA::string_dup(&aHDFUrl[strlen(aDir.c_str())]);
424 SALOMEDS_Tool::RemoveTemporaryFiles(aDir,aFilesToRemove,true);
427 return aStudy._retn();
432 //============================================================================
434 * Purpose : Close a study.
435 * If the study hasn't been saved, ask the user to confirm the
436 * close action without saving
438 //============================================================================
439 void SALOMEDS_StudyManager_i::Close(SALOMEDS::Study_ptr aStudy)
441 SALOMEDS::Locker lock;
443 if(aStudy->_is_nil()) return;
445 aStudy->RemovePostponed(-1);
447 // Destroy study name in the naming service
448 if(_name_service.Change_Directory("/Study")){
449 CORBA::String_var aString(aStudy->Name());
450 _name_service.Destroy_Name(aString.in());
456 //============================================================================
458 * Purpose : Save a Study to it's persistent reference
460 //============================================================================
461 void SALOMEDS_StudyManager_i::Save(SALOMEDS::Study_ptr theStudy, CORBA::Boolean theMultiFile)
463 SALOMEDS::Locker lock;
465 CORBA::String_var anURL = theStudy->URL();
466 if(strcmp(anURL.in(),"") == 0){
467 MESSAGE( "No path specified to save the study. Nothing done");
469 _SaveAs(anURL,theStudy,theMultiFile,false);
473 void SALOMEDS_StudyManager_i::SaveASCII(SALOMEDS::Study_ptr theStudy, CORBA::Boolean theMultiFile)
475 SALOMEDS::Locker lock;
477 CORBA::String_var anURL = theStudy->URL();
478 if(strcmp(anURL.in(),"") == 0){
479 MESSAGE( "No path specified to save the study. Nothing done");
481 _SaveAs(anURL,theStudy,theMultiFile,true);
485 //=============================================================================
486 /*! Function : SaveAs
487 * Purpose : Save a study to the persistent reference aUrl
489 //============================================================================
490 void SALOMEDS_StudyManager_i::SaveAs(const char* aUrl, SALOMEDS::Study_ptr theStudy, CORBA::Boolean theMultiFile)
492 SALOMEDS::Locker lock;
494 _SaveAs(aUrl,theStudy,theMultiFile, false);
498 void SALOMEDS_StudyManager_i::SaveAsASCII(const char* aUrl, SALOMEDS::Study_ptr theStudy, CORBA::Boolean theMultiFile)
500 SALOMEDS::Locker lock;
502 _SaveAs(aUrl,theStudy,theMultiFile, true);
505 //============================================================================
506 /*! Function : GetOpenStudies
507 * Purpose : Get name list of open studies in the session
509 //============================================================================
510 SALOMEDS::ListOfOpenStudies* SALOMEDS_StudyManager_i::GetOpenStudies()
512 // MESSAGE("Begin of GetOpenStudies");
513 SALOMEDS::ListOfOpenStudies_var aStudyList = new SALOMEDS::ListOfOpenStudies;
515 if(!_name_service.Change_Directory("/Study")){
516 MESSAGE("No active study in this session");
518 vector<string> aList = _name_service.list_directory();
519 aStudyList->length(aList.size());
520 for(unsigned int ind = 0; ind < aList.size(); ind++){
521 aStudyList[ind] = CORBA::string_dup(aList[ind].c_str());
522 SCRUTE(aStudyList[ind]) ;
526 return aStudyList._retn();
529 //============================================================================
530 /*! Function : GetStudyByName
531 * Purpose : Get a study from its name
533 //============================================================================
535 SALOMEDS_StudyManager_i::GetStudyByName(const char* theStudyName)
537 SALOMEDS::Study_var aStudy;
539 // Go to study directory and look for aStudyName
540 if(!_name_service.Change_Directory("/Study")){
541 MESSAGE("No active study in this session");
542 ASSERT(false); // Stop here...
545 if(_name_service.Find(theStudyName) > 0){
547 CORBA::Object_ptr anObj = _name_service.Resolve(theStudyName) ;
548 aStudy = SALOMEDS::Study::_narrow(anObj);
549 MESSAGE("Study " << theStudyName << " found in the naming service");
551 MESSAGE("Study " << theStudyName << " not found in the naming service");
553 return aStudy._retn();
556 //============================================================================
557 /*! Function : GetStudyByID
558 * Purpose : Get a study from its ID
560 //============================================================================
562 SALOMEDS_StudyManager_i::GetStudyByID(CORBA::Short aStudyID)
564 SALOMEDS::Study_var aStudy;
566 if(!_name_service.Change_Directory("/Study")){
567 MESSAGE("No active study in this session");
569 vector<string> aList = _name_service.list_directory();
570 for(unsigned int ind = 0; ind < aList.size(); ind++){
571 const char* aStudyName = aList[ind].c_str();
572 MESSAGE( "GetStudyByID = " << aStudyName );
573 if(_name_service.Find(aStudyName) > 0){
574 CORBA::Object_ptr anObj = _name_service.Resolve(aStudyName) ;
575 aStudy = SALOMEDS::Study::_narrow(anObj);
576 MESSAGE( " aStudyID : " << aStudyID << "-" << aStudy->StudyId() );
577 if(aStudyID == aStudy->StudyId()){
578 MESSAGE("Study with studyID = " << aStudyID << " found in the naming service");
579 return aStudy._retn();
582 MESSAGE("Study " << aStudyName << " not found in the naming service");
587 return aStudy._retn();
589 //============================================================================
590 /*! Function : SaveAttributes
591 * Purpose : Save attributes for object
593 //============================================================================
594 static void SaveAttributes(SALOMEDS::SObject_ptr SO, HDFgroup *hdf_group_sobject) {
597 SALOMEDS::ListOfAttributes_var anAttrList = SO->GetAllAttributes();
598 for(a = anAttrList->length() - 1; a >= 0; a--) {
599 if (strcmp(anAttrList[a]->Type(), "AttributeIOR") == 0) continue; // never write AttributeIOR to file
600 if (strcmp(anAttrList[a]->Type(), "AttributeExternalFileDef") == 0) continue; // never write ExternalFileDef to file
601 if (strcmp(anAttrList[a]->Type(), "AttributeFileType") == 0) continue; // never write FileType to file
602 CORBA::String_var aSaveStr(anAttrList[a]->Store());
603 size[0] = (hdf_int32) strlen(aSaveStr.in()) + 1;
604 HDFdataset *hdf_dataset = new HDFdataset(anAttrList[a]->Type(),hdf_group_sobject,HDF_STRING,size,1);
605 hdf_dataset->CreateOnDisk();
606 hdf_dataset->WriteOnDisk(aSaveStr);
607 hdf_dataset->CloseOnDisk();
608 //cout<<"********** Write Attribute "<<anAttrList[a]->Type()<<" : "<<aSaveStr<<" done"<<endl;
609 hdf_dataset = 0; //will be deleted by hdf_sco_group destructor
612 // Reference attribute has no CORBA attribute representation, so, GetAllAttributes can not return this attribute
613 SALOMEDS::SObject_var RefSO;
614 if(SO->ReferencedObject(RefSO)) {
615 CORBA::String_var attribute_reference(RefSO->GetID());
616 size[0] = strlen(attribute_reference) + 1 ;
617 HDFdataset *hdf_dataset = new HDFdataset("Reference",hdf_group_sobject,HDF_STRING,size,1);
618 hdf_dataset->CreateOnDisk();
619 hdf_dataset->WriteOnDisk(attribute_reference);
620 hdf_dataset->CloseOnDisk();
621 hdf_dataset = 0; // will be deleted by father hdf object destructor
625 //=============================================================================
626 /*! Function : _SaveProperties
627 * Purpose : save the study properties in HDF file
629 //============================================================================
630 void SALOMEDS_StudyManager_i::_SaveProperties(SALOMEDS_Study_i* theStudy, HDFgroup *hdf_group)
632 // add modifications list (user and date of save)
633 SALOMEDS::AttributeStudyProperties_ptr aProp = theStudy->GetProperties();
634 int aLocked = aProp->IsLocked();
636 aProp->SetLocked(Standard_False);
637 OSD_Process aProcess;
638 Quantity_Date aDate = aProcess.SystemDate();
639 aProp->SetModification(aProcess.UserName().ToCString(),
640 CORBA::Long(aDate.Minute()),
641 CORBA::Long(aDate.Hour()),
642 CORBA::Long(aDate.Day()),
643 CORBA::Long(aDate.Month()),
644 CORBA::Long(aDate.Year()));
646 aProp->SetLocked(Standard_True);
648 SALOMEDS::StringSeq_var aNames;
649 SALOMEDS::LongSeq_var aMinutes, aHours, aDays, aMonths, aYears;
650 aProp->GetModificationsList(aNames,aMinutes,aHours,aDays,aMonths,aYears,true);
652 std::ostringstream aPropertyList;
653 aPropertyList<<(strlen(aProp->GetCreationMode()) != 0? aProp->GetCreationMode()[0] : '0');
654 aPropertyList<<(aProp->IsLocked()? 'l': 'u');
656 int aLength = aNames->length();
657 for(int anIndex = 0; anIndex < aLength; anIndex++) {
658 aPropertyList<<std::setw(2)<<aMinutes[anIndex];
659 aPropertyList<<std::setw(2)<<aHours[anIndex];
660 aPropertyList<<std::setw(2)<<aDays[anIndex];
661 aPropertyList<<std::setw(2)<<aMonths[anIndex];
662 aPropertyList<<std::setw(4)<<aYears[anIndex];
663 aPropertyList<<aNames[anIndex];
664 aPropertyList<<char(0x1);
666 std::string aProperty = aPropertyList.str();
668 hdf_size size[] = {aProperty.size() + 1};
669 HDFdataset *hdf_dataset = new HDFdataset("AttributeStudyProperties",hdf_group,HDF_STRING,size,1);
670 hdf_dataset->CreateOnDisk();
671 hdf_dataset->WriteOnDisk(const_cast<char*>(aProperty.c_str()));
672 MESSAGE("attribute StudyProperties " << aProperty << " wrote on file");
673 hdf_dataset->CloseOnDisk();
674 hdf_dataset = 0; //will be deleted by hdf_sco_group destructor
675 aProp->SetModified(0);
678 //=============================================================================
679 /*! Function : _SaveAs
680 * Purpose : save the study in HDF file
682 //============================================================================
683 void SALOMEDS_StudyManager_i::_SaveAs(const char* aUrl,
684 SALOMEDS::Study_ptr theStudy,
685 CORBA::Boolean theMultiFile,
686 CORBA::Boolean theASCII)
688 // HDF File will be composed of differents part :
689 // * For each ComponentDataType, all data created by the component
690 // Informations in data group hdf_group_datacomponent
691 // * Study Structure -> Exactly what is contained in OCAF document
692 // Informations in data group hdf_group_study_structure
694 if(SALOMEDS_Study_i* aStudy = DownCast(theStudy)){
696 HDFgroup *hdf_group_study_structure =0;
697 HDFgroup *hdf_sco_group =0;
698 HDFgroup *hdf_sco_group2 =0;
700 HDFgroup *hdf_group_datacomponent =0;
701 HDFdataset *hdf_dataset =0;
703 hdf_int32 name_len = 0;
705 int aLocked = aStudy->GetProperties()->IsLocked();
707 aStudy->GetProperties()->SetLocked(false);
709 SALOMEDS_StudyBuilder_i* SB= aStudy->GetBuilder();
711 // mpv 15.12.2003: for saving components we have to load all data from all modules
712 SALOMEDS_SComponentIterator_i aComponentIter = aStudy->GetComponentIterator();
713 for(; aComponentIter.More(); aComponentIter.Next()){
714 SALOMEDS::SComponent_var sco = aComponentIter.Value();
715 // if there is an associated Engine call its method for saving
716 CORBA::String_var IOREngine;
718 if(!sco->ComponentIOR(IOREngine)){
719 SALOMEDS::GenericAttribute_var aGeneric;
720 SALOMEDS::AttributeName_var aName;
721 if(sco->FindAttribute(aGeneric, "AttributeName"))
722 aName = SALOMEDS::AttributeName::_narrow(aGeneric);
724 if(!aName->_is_nil()){
725 CORBA::String_var aCompType = aName->Value();
727 CORBA::String_var aFactoryType;
728 if(strcmp(aCompType, "SUPERV") == 0)
729 aFactoryType = "SuperVisionContainer";
731 aFactoryType = "FactoryServer";
733 Engines::Component_var aComp =
734 SALOME_LifeCycleCORBA(&_name_service).FindOrLoad_Component(aFactoryType, aCompType);
736 if(aComp->_is_nil()){
737 Engines::Component_var aComp =
738 SALOME_LifeCycleCORBA(&_name_service).FindOrLoad_Component("FactoryServerPy", aCompType);
741 if(!aComp->_is_nil()){
742 SALOMEDS::Driver_var aDriver = SALOMEDS::Driver::_narrow(aComp);
743 if (!CORBA::is_nil(aDriver)) {
744 // PAL8065: san - _SaveAs() should always be called from some CORBA method protected with a lock
746 SB->LoadWith(sco, aDriver);
753 MESSAGE("Can not restore information to resave it");
758 CORBA::String_var anOldName = aStudy->Name();
761 // To change for Save
762 // Do not have to do a new file but just a Open??? Rewrite all informations after erasing evrything??
763 hdf_file = new HDFfile((char *)aUrl);
764 hdf_file->CreateOnDisk();
765 MESSAGE("File " << aUrl << " created");
767 //-----------------------------------------------------------------------
768 // 1 - Create a groupe for each SComponent and Update the PersistanceRef
769 //-----------------------------------------------------------------------
770 hdf_group_datacomponent = new HDFgroup("DATACOMPONENT",hdf_file);
771 hdf_group_datacomponent->CreateOnDisk();
773 //SRN: Added 17 Nov, 2003
774 SALOMEDS::SObject_var anAutoSaveSO = aStudy->FindObjectID(AUTO_SAVE_TAG);
777 aComponentIter.Init();
778 for(; aComponentIter.More(); aComponentIter.Next()){
779 SALOMEDS::SComponent_var sco = aComponentIter.Value();
781 CORBA::String_var scoid = sco->GetID();
782 hdf_sco_group = new HDFgroup(scoid,hdf_group_datacomponent);
783 hdf_sco_group->CreateOnDisk();
785 CORBA::String_var componentDataType = sco->ComponentDataType();
786 MESSAGE ( "Look for an engine for data type :"<< componentDataType);
788 //SRN: Added 17 Nov 2003: If there is a specified attribute, the component peforms a special save
789 if(!CORBA::is_nil(anAutoSaveSO) && SB->IsGUID(sco, AUTO_SAVE_GUID)){
790 SALOMEDS::GenericAttribute_var aGeneric;
791 SALOMEDS::AttributeTableOfString_var aTable;
792 if(anAutoSaveSO->FindAttribute(aGeneric, "AttributeTableOfString")){
793 aTable = SALOMEDS::AttributeTableOfString::_narrow(aGeneric);
794 Standard_Integer nbRows = aTable->GetNbRows(), k, aTimeOut = 0;
795 if(nbRows > 0 && aTable->GetNbColumns() > 1) {
796 SALOMEDS::StringSeq_var aRow;
797 for(k=1; k<=nbRows; k++){
798 aRow = aTable->GetRow(k);
799 if(strcmp(aRow[0], componentDataType) == 0){
800 CORBA::String_var anEntry = CORBA::string_dup(aRow[1]);
801 SALOMEDS::SObject_var aCompSpecificSO = aStudy->FindObjectID(anEntry);
802 if(!CORBA::is_nil(aCompSpecificSO)) {
803 SALOMEDS::AttributeInteger_var anInteger;
804 if(aCompSpecificSO->FindAttribute(aGeneric, "AttributeInteger")) {
805 anInteger = SALOMEDS::AttributeInteger::_narrow(aGeneric);
806 anInteger->SetValue(-1);
807 while(anInteger->Value() < 0) { sleep(2); if(++aTimeOut > AUTO_SAVE_TIME_OUT_IN_SECONDS) break; }
808 } // if(aCompSpecificSO->FindAttribute(anInteger, "AttributeInteger"))
809 } // if(!CORBA::is_nil(aCompSpecificSO))
810 } // if (strcmp(aRow[0], componentDataType) == 0)
813 } // if(nbRows > 0 && aTable->GetNbColumns() > 1)
815 } // if(anAutoSaveSO->FindAttribute(aTable, "AttributeTableOfString")
817 } // if(SB->IsGUID(AUTO_SAVE_GUID)
821 CORBA::String_var IOREngine;
822 if(sco->ComponentIOR(IOREngine)){
823 // we have found the associated engine to write the data
824 MESSAGE ( "We have found an engine for data type :"<< componentDataType);
825 CORBA::Object_var obj = _orb->string_to_object(IOREngine);
826 SALOMEDS::Driver_var Engine = SALOMEDS::Driver::_narrow(obj) ;
828 if(!CORBA::is_nil(Engine)){
829 MESSAGE ( "Save the data of type:"<< componentDataType);
830 MESSAGE("Engine :"<<Engine->ComponentDataType());
832 SALOMEDS::TMPFile_var aStream;
835 aStream = Engine->SaveASCII(sco,SALOMEDS_Tool::GetDirFromPath(aUrl).c_str(),theMultiFile);
837 aStream = Engine->Save(sco,SALOMEDS_Tool::GetDirFromPath(aUrl).c_str(),theMultiFile);
839 HDFdataset *hdf_dataset;
840 hdf_size aHDFSize[1];
841 if(aStream->length() > 0){ //The component saved some auxiliary files, then put them into HDF file
843 aHDFSize[0] = aStream->length();
845 HDFdataset *hdf_dataset = new HDFdataset("FILE_STREAM", hdf_sco_group, HDF_STRING, aHDFSize, 1);
846 hdf_dataset->CreateOnDisk();
847 hdf_dataset->WriteOnDisk((unsigned char*) &aStream[0]); //Save the stream in the HDF file
848 hdf_dataset->CloseOnDisk();
850 // store multifile state
852 hdf_dataset = new HDFdataset("MULTIFILE_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
853 hdf_dataset->CreateOnDisk();
854 hdf_dataset->WriteOnDisk((void*)(theMultiFile?"M":"S")); // save: multi or single
855 hdf_dataset->CloseOnDisk();
856 hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor
860 hdf_dataset = new HDFdataset("ASCII_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
861 hdf_dataset->CreateOnDisk();
862 hdf_dataset->WriteOnDisk((void*)(theASCII?"A":"B")); // save: ASCII or BINARY
863 hdf_dataset->CloseOnDisk();
864 hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor
866 Translate_IOR_to_persistentID(aStudy,SB,sco,Engine,theMultiFile, theASCII);
867 MESSAGE("After Translate_IOR_to_persistentID");
869 // Creation of the persistance reference attribute
872 hdf_sco_group->CloseOnDisk();
873 hdf_sco_group=0; // will be deleted by hdf_group_datacomponent destructor
875 hdf_group_datacomponent->CloseOnDisk();
876 hdf_group_datacomponent =0; // will be deleted by hdf_file destructor
879 //-----------------------------------------------------------------------
880 //3 - Write the Study Structure
881 //-----------------------------------------------------------------------
882 hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
883 hdf_group_study_structure->CreateOnDisk();
885 // save component attributes
886 aComponentIter.Init();
887 for(; aComponentIter.More(); aComponentIter.Next()){
888 SALOMEDS::SComponent_var SC = aComponentIter.Value();
890 CORBA::String_var scid = SC->GetID();
891 hdf_sco_group2 = new HDFgroup(scid,hdf_group_study_structure);
892 hdf_sco_group2->CreateOnDisk();
893 SaveAttributes(SC, hdf_sco_group2);
894 // ComponentDataType treatment
895 CORBA::String_var component_name = SC->ComponentDataType();
896 MESSAGE("Component data type " << component_name << " treated");
898 name_len = (hdf_int32) strlen(component_name.in());
899 size[0] = name_len +1 ;
900 hdf_dataset = new HDFdataset("COMPONENTDATATYPE",hdf_sco_group2,HDF_STRING,size,1);
901 hdf_dataset->CreateOnDisk();
902 hdf_dataset->WriteOnDisk(const_cast<char*>(component_name.in()));
903 MESSAGE("component name " << component_name << " wrote on file");
904 hdf_dataset->CloseOnDisk();
905 hdf_dataset=0; //will be deleted by hdf_sco_group destructor
906 _SaveObject(aStudy, SC, hdf_sco_group2);
907 hdf_sco_group2->CloseOnDisk();
908 hdf_sco_group2=0; // will be deleted by hdf_group_study_structure destructor
910 //-----------------------------------------------------------------------
911 //4 - Write the Study UseCases Structure
912 //-----------------------------------------------------------------------
913 SALOMEDS::SObject_var aSO = aStudy->FindObjectID(USE_CASE_LABEL_ID);
915 HDFgroup *hdf_soo_group = new HDFgroup(USE_CASE_LABEL_ID,hdf_group_study_structure);
916 hdf_soo_group->CreateOnDisk();
917 SaveAttributes(aSO, hdf_soo_group);
918 _SaveObject(aStudy, aSO, hdf_soo_group);
919 MESSAGE("Use cases data structure writed");
920 hdf_soo_group->CloseOnDisk();
921 hdf_soo_group=0; // will be deleted by hdf_group_study_structure destructor
925 aStudy->GetProperties()->SetLocked(true);
926 //-----------------------------------------------------------------------
927 //5 - Write the Study Properties
928 //-----------------------------------------------------------------------
929 name_len = (hdf_int32) strlen(aStudy->Name());
930 size[0] = name_len +1 ;
931 hdf_dataset = new HDFdataset("STUDY_NAME",hdf_group_study_structure,HDF_STRING,size,1);
932 hdf_dataset->CreateOnDisk();
933 CORBA::String_var studid = aStudy->Name();
934 hdf_dataset->WriteOnDisk(studid);
935 MESSAGE("study name " << studid << " wrote on file");
936 hdf_dataset->CloseOnDisk();
937 hdf_dataset=0; // will be deleted by hdf_group_study_structure destructor
939 _SaveProperties(aStudy, hdf_group_study_structure);
941 hdf_group_study_structure->CloseOnDisk();
942 hdf_file->CloseOnDisk();
944 _name_service.Change_Directory("/Study");
945 _name_service.Destroy_Name(anOldName);
946 _name_service.Register(theStudy, aStudy->Name());
948 aStudy->IsSaved(true);
949 hdf_group_study_structure =0; // will be deleted by hdf_file destructor
950 delete hdf_file; // recursively deletes all hdf objects...
951 }catch(HDFexception){
952 MESSAGE( "HDFexception ! " );
954 if(theASCII){ // save file in ASCII format
955 HDFascii::ConvertFromHDFToASCII(aUrl, true);
960 //============================================================================
961 /*! Function : _SaveObject
964 //============================================================================
965 void SALOMEDS_StudyManager_i::_SaveObject(SALOMEDS_Study_i* theStudy,
966 SALOMEDS::SObject_ptr theSObject,
967 HDFgroup *hdf_group_datatype)
969 // Write in group hdf_group_datatype all informations of SObject SC
970 // Iterative function to parse all SObjects under a SComponent
971 SALOMEDS::SObject_var RefSO;
972 HDFgroup *hdf_group_sobject = 0;
974 SALOMEDS_ChildIterator_i aChildIter = theStudy->GetChildIterator(theSObject);
975 for(; aChildIter.More(); aChildIter.Next()){
976 SALOMEDS::SObject_var aSObject = aChildIter.Value();
977 SALOMEDS::ListOfAttributes_var anAllAttributes = aSObject->GetAllAttributes();
979 // mpv: don't save empty labels
980 if(anAllAttributes->length() == 0 && !aSObject->ReferencedObject(RefSO)){
981 SALOMEDS_ChildIterator_i aSubChildIter = theStudy->GetChildIterator(theSObject);
982 if(!aSubChildIter.More())
985 aSubChildIter.InitEx(true);
987 for(; aSubChildIter.More() && anEmpty; aSubChildIter.Next()){
988 SALOMEDS::SObject_var aSObj = aSubChildIter.Value();
989 SALOMEDS::ListOfAttributes_var anAllAttr = aSObj->GetAllAttributes();
990 if(anAllAttr->length() != 0 || aSObj->ReferencedObject(RefSO))
997 CORBA::String_var scoid(aSObject->GetID());
998 hdf_group_sobject = new HDFgroup(scoid,hdf_group_datatype);
999 hdf_group_sobject->CreateOnDisk();
1000 SaveAttributes(aSObject, hdf_group_sobject);
1001 _SaveObject(theStudy,aSObject, hdf_group_sobject);
1002 hdf_group_sobject->CloseOnDisk();
1003 hdf_group_sobject =0; // will be deleted by father hdf object destructor
1007 //============================================================================
1008 /*! Function : _SubstituteSlash
1011 //============================================================================
1013 std::string SALOMEDS_StudyManager_i::_SubstituteSlash(const char *theUrl)
1016 TCollection_ExtendedString aUrl(const_cast<char*>(theUrl));
1017 aUrl.ChangeAll(ToExtCharacter('/'),ToExtCharacter(':'));
1018 TCollection_AsciiString ch(aUrl);
1019 return ch.ToCString();
1022 //============================================================================
1023 /*! Function : CanCopy
1026 //============================================================================
1027 CORBA::Boolean SALOMEDS_StudyManager_i::CanCopy(SALOMEDS::SObject_ptr theObject) {
1028 SALOMEDS::Driver_var Engine;
1029 { // Guarded block of code
1030 SALOMEDS::Locker lock;
1032 SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1034 if(aComponent->_is_nil())
1037 if(aComponent == theObject)
1040 CORBA::String_var IOREngine;
1041 if(!aComponent->ComponentIOR(IOREngine))
1044 CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1045 Engine = SALOMEDS::Driver::_narrow(obj);
1046 if (CORBA::is_nil(Engine))
1048 } // End of guarded block of code
1049 return Engine->CanCopy(theObject);
1052 //============================================================================
1053 /*! Function : CopyLabel
1056 //============================================================================
1057 void SALOMEDS_StudyManager_i::CopyLabel(SALOMEDS_Study_i* theSourceStudy,
1058 const SALOMEDS::Driver_ptr theEngine,
1059 const Standard_Integer theSourceStartDepth,
1060 const TDF_Label& theSource,
1061 const TDF_Label& theDestinationMain)
1064 TDF_Label aTargetLabel = theDestinationMain;
1065 TDF_Label aAuxTargetLabel = theDestinationMain.Father().FindChild(2);
1066 for(a = theSource.Depth() - theSourceStartDepth; a > 0 ; a--) {
1067 TDF_Label aSourceLabel = theSource;
1068 for(int aNbFather = 1; aNbFather < a; aNbFather++) aSourceLabel = aSourceLabel.Father();
1069 aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
1070 aAuxTargetLabel = aAuxTargetLabel.FindChild(aSourceLabel.Tag());
1072 // iterate attributes
1073 TDF_AttributeIterator anAttrIterator(theSource);
1074 Handle(TDF_RelocationTable) aRT = new TDF_RelocationTable();
1075 for(; anAttrIterator.More(); anAttrIterator.Next()) {
1076 Handle(TDF_Attribute) anAttr = anAttrIterator.Value();
1077 if (!Handle(TDataStd_TreeNode)::DownCast(anAttr).IsNull()) continue; // never copy tree node attribute
1078 if (!Handle(SALOMEDS_TargetAttribute)::DownCast(anAttr).IsNull()) continue; // and target attribute
1080 if (!Handle(TDF_Reference)::DownCast(anAttr).IsNull()) { // reference copied as Comment in auxiliary tree
1081 TDF_Label aReferenced = Handle(TDF_Reference)::DownCast(anAttr)->Get();
1082 TCollection_AsciiString anEntry;
1083 TDF_Tool::Entry(aReferenced, anEntry);
1084 // store the value of name attribute of referenced label
1085 Handle(TDataStd_Name) aNameAttribute;
1086 if (aReferenced.FindAttribute(TDataStd_Name::GetID(), aNameAttribute)) {
1088 anEntry += aNameAttribute->Get();
1090 TDataStd_Comment::Set(aAuxTargetLabel, TCollection_ExtendedString(anEntry));
1094 if (Handle(SALOMEDS_IORAttribute)::DownCast(anAttr).IsNull()) { // IOR => ID and TMPFile of Engine
1095 Handle(TDF_Attribute) aNewAttribute = anAttr->NewEmpty();
1096 aTargetLabel.AddAttribute(aNewAttribute);
1097 anAttr->Paste(aNewAttribute, aRT);
1101 TCollection_AsciiString anEntry;
1102 TDF_Tool::Entry(theSource, anEntry);
1103 SALOMEDS::SObject_var aSO = theSourceStudy->FindObjectID(anEntry.ToCString());
1104 CORBA::Long anObjID;
1106 // PAL8065: san - CopyLabel() should always be called from some CORBA method protected with a lock
1108 SALOMEDS::TMPFile_var aStream = theEngine->CopyFrom(aSO, anObjID);
1111 int aLen = aStream->length();
1112 TCollection_ExtendedString aResStr("");
1113 for(a = 0; a < aLen; a++) {
1114 aResStr += TCollection_ExtendedString(ToExtCharacter((Standard_Character)aStream[a]));
1116 TDataStd_Integer::Set(aAuxTargetLabel, anObjID);
1117 TDataStd_Name::Set(aAuxTargetLabel, aResStr);
1119 // aRT->SetRelocation(anAttr, aNewAttribute);
1123 //============================================================================
1127 //============================================================================
1128 CORBA::Boolean SALOMEDS_StudyManager_i::Copy(SALOMEDS::SObject_ptr theObject) {
1129 SALOMEDS::Locker lock;
1131 // adoptation for alliances datamodel copy: without IOR attributes !!!
1132 // copy only SObjects and attributes without component help
1133 SALOMEDS::GenericAttribute_var anAttribute;
1134 bool aStructureOnly = !theObject->FindAttribute(anAttribute, "AttributeIOR");
1136 PortableServer::ServantBase_var aServant = GetServant(theObject,_poa);
1137 SALOMEDS_SObject_i* aSObject = dynamic_cast<SALOMEDS_SObject_i*>(aServant.in());
1138 if(aSObject == NULL)
1141 SALOMEDS_Study_i* aStudy = aSObject->GetStudyServant();
1142 SALOMEDS::Driver_var anEngine;
1143 CORBA::String_var aString;
1144 if (!aStructureOnly) {
1145 SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1146 if(!aComponent->ComponentIOR(aString))
1149 CORBA::Object_var anObj = _orb->string_to_object(aString);
1150 anEngine = SALOMEDS::Driver::_narrow(anObj) ;
1153 // CAF document of current study usage
1154 Handle(TDocStd_Document) aDocument = aStudy->GetDocument();
1155 if(aDocument.IsNull())
1158 // create new document for clipboard
1159 Handle(TDocStd_Document) aTargetDocument;
1160 _OCAFApp->NewDocument("SALOME_STUDY", aTargetDocument);
1161 // set component data type to the name attribute of root label
1162 if(!aStructureOnly){
1163 aString = anEngine->ComponentDataType();
1164 TDataStd_Comment::Set(aTargetDocument->Main().Root(),const_cast<char*>(aString.in()));
1166 // set to the Root label integer attribute: study id
1167 TDataStd_Integer::Set(aTargetDocument->Main().Root(),aStudy->StudyId());
1169 // iterate all theObject's label children
1170 TDF_Label aStartLabel;
1171 aString = theObject->GetID();
1172 TDF_Tool::Label(aDocument->GetData(),const_cast<char*>(aString.in()),aStartLabel);
1173 Standard_Integer aSourceStartDepth = aStartLabel.Depth();
1175 // copy main source label
1176 CopyLabel(aStudy,anEngine,aSourceStartDepth,aStartLabel,aTargetDocument->Main());
1178 // copy all subchildren of the main source label (all levels)
1179 TDF_ChildIterator anIterator(aStartLabel,Standard_True);
1180 for(; anIterator.More(); anIterator.Next()){
1181 CopyLabel(aStudy,anEngine,aSourceStartDepth,anIterator.Value(),aTargetDocument->Main());
1184 // done: free old clipboard document and
1185 if (!_clipboard.IsNull()) {
1186 // Handle(TDocStd_Owner) anOwner;
1187 // if (_clipboard->Main().Root().FindAttribute(TDocStd_Owner::GetID(), anOwner)) {
1188 // Handle(TDocStd_Document) anEmptyDoc;
1189 // anOwner->SetDocument(anEmptyDoc);
1191 _OCAFApp->Close(_clipboard);
1194 _clipboard = aTargetDocument;
1198 //============================================================================
1199 /*! Function : CanPaste
1202 //============================================================================
1203 CORBA::Boolean SALOMEDS_StudyManager_i::CanPaste(SALOMEDS::SObject_ptr theObject) {
1204 CORBA::String_var aName;
1205 Standard_Integer anID;
1206 SALOMEDS::Driver_var Engine;
1207 { // Guarded block of code
1208 SALOMEDS::Locker lock;
1210 if (_clipboard.IsNull()) return false;
1212 Handle(TDataStd_Comment) aCompName;
1213 if (!_clipboard->Main().Root().FindAttribute(TDataStd_Comment::GetID(), aCompName)) return false;
1214 Handle(TDataStd_Integer) anObjID;
1215 if (!_clipboard->Main().Father().FindChild(2).FindAttribute(TDataStd_Integer::GetID(), anObjID))
1218 SALOMEDS::SComponent_var aComponent = theObject->GetFatherComponent();
1219 if(aComponent->_is_nil())
1222 CORBA::String_var IOREngine;
1223 if(!aComponent->ComponentIOR(IOREngine))
1226 CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1227 Engine = SALOMEDS::Driver::_narrow(obj) ;
1228 if (CORBA::is_nil(Engine))
1231 aName = CORBA::string_dup( TCollection_AsciiString(aCompName->Get()).ToCString() );
1232 anID = anObjID->Get();
1233 } // End of guarded block of code
1234 return Engine->CanPaste(aName.in(),anID);
1236 //============================================================================
1237 /*! Function : PasteLabel
1240 //============================================================================
1241 TDF_Label SALOMEDS_StudyManager_i::PasteLabel(SALOMEDS_Study_i* theDestinationStudy,
1242 const SALOMEDS::Driver_ptr theEngine,
1243 const TDF_Label& theSource,
1244 const TDF_Label& theDestinationStart,
1245 const int theCopiedStudyID,
1246 const bool isFirstElement)
1249 // get corresponding source, target and auxiliary labels
1250 TDF_Label aTargetLabel = theDestinationStart;
1251 TDF_Label aAuxSourceLabel = theSource.Root().FindChild(2);
1253 if (!isFirstElement) {
1254 for(a = theSource.Depth() - 1; a > 0 ; a--) {
1255 TDF_Label aSourceLabel = theSource;
1256 for(int aNbFather = 1; aNbFather < a; aNbFather++)
1257 aSourceLabel = aSourceLabel.Father();
1258 aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
1259 aAuxSourceLabel = aAuxSourceLabel.FindChild(aSourceLabel.Tag());
1263 // check auxiliary label for TMPFile => IOR
1264 Handle(TDataStd_Name) aNameAttribute;
1265 if (aAuxSourceLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute)) {
1266 Handle(TDataStd_Integer) anObjID;
1268 aAuxSourceLabel.FindAttribute(TDataStd_Integer::GetID(), anObjID);
1269 Handle(TDataStd_Comment) aComponentName;
1270 theSource.Root().FindAttribute(TDataStd_Comment::GetID(), aComponentName);
1271 std::string aCompName = TCollection_AsciiString(aComponentName->Get()).ToCString();
1272 if (theEngine->CanPaste(aCompName.c_str(),anObjID->Get())) {
1273 SALOMEDS::TMPFile_var aTMPFil = new SALOMEDS::TMPFile();
1274 TCollection_ExtendedString aTMPStr = aNameAttribute->Get();
1275 int aLen = aTMPStr.Length();
1276 aTMPFil->length(aLen);
1277 for(a = 0; a < aLen; a++) {
1278 aTMPFil[a] = ToCharacter(aTMPStr.Value(a+1));
1280 TCollection_AsciiString anEntry;
1281 TDF_Tool::Entry(aTargetLabel, anEntry);
1282 SALOMEDS::SObject_var aPastedSO = theDestinationStudy->FindObjectID(anEntry.ToCString());
1284 // PAL8065: san - PasteLabel() should always be called from some CORBA method protected with a lock
1286 SALOMEDS::SObject_var aDestSO =
1287 theEngine->PasteInto(aTMPFil.in(),
1289 aPastedSO->GetFatherComponent());
1291 TDF_Tool::Label(theDestinationStart.Data(), aDestSO->GetID(), aTargetLabel);
1293 // PAL8065: san - PasteLabel() should always be called from some CORBA method protected with a lock
1295 theEngine->PasteInto(aTMPFil.in(),anObjID->Get(),aPastedSO);
1300 // iterate attributes
1301 TDF_AttributeIterator anAttrIterator(theSource);
1302 Handle(TDF_RelocationTable) aRT = new TDF_RelocationTable();
1303 for(; anAttrIterator.More(); anAttrIterator.Next()) {
1304 Handle(TDF_Attribute) anAttr = anAttrIterator.Value();
1305 if (aTargetLabel.FindAttribute(anAttr->ID(), anAttr)) {
1306 aTargetLabel.ForgetAttribute(anAttr->ID());
1307 anAttr = anAttrIterator.Value();
1309 Handle(TDF_Attribute) aNewAttribute = anAttr->NewEmpty();
1310 aTargetLabel.AddAttribute(aNewAttribute);
1311 anAttr->Paste(aNewAttribute, aRT);
1312 // aRT->SetRelocation(anAttr, aNewAttribute);
1314 // check auxiliary label for Comment => reference or name attribute of the referenced object
1315 Handle(TDataStd_Comment) aCommentAttribute;
1316 if (aAuxSourceLabel.FindAttribute(TDataStd_Comment::GetID(), aCommentAttribute)) {
1317 std::string anEntry(TCollection_AsciiString(aCommentAttribute->Get()).ToCString());
1318 std::size_t aNameStart = anEntry.find(' ');
1320 if(aNameStart != std::string::npos){
1321 aName = anEntry.substr(aNameStart+1);
1322 anEntry = anEntry.substr(0,aNameStart);
1324 if (theCopiedStudyID == theDestinationStudy->StudyId()) { // if copy to the same study, reanimate reference
1325 TDF_Label aRefLabel;
1326 TDF_Tool::Label(aTargetLabel.Data(),&anEntry[0],aRefLabel);
1327 TDF_Reference::Set(aTargetLabel, aRefLabel);
1328 SALOMEDS_TargetAttribute::Set(aRefLabel)->Append(aTargetLabel); // target attributes structure support
1330 if(aNameStart != std::string::npos)
1331 TDataStd_Name::Set(aTargetLabel, &aName[0]);
1333 TDataStd_Name::Set(aTargetLabel,
1334 TCollection_ExtendedString("Reference to:") + &anEntry[0]);
1338 return aTargetLabel;
1340 //============================================================================
1341 /*! Function : Paste
1344 //============================================================================
1345 SALOMEDS::SObject_ptr SALOMEDS_StudyManager_i::Paste(SALOMEDS::SObject_ptr theObject)
1346 throw(SALOMEDS::StudyBuilder::LockProtection)
1348 SALOMEDS::Locker lock;
1350 Unexpect aCatch(LockProtection);
1352 PortableServer::ServantBase_var aServant = GetServant(theObject,_poa);
1353 SALOMEDS_SObject_i* aSObject = dynamic_cast<SALOMEDS_SObject_i*>(aServant.in());
1354 if(aSObject == NULL)
1357 SALOMEDS_Study_i* aStudy = aSObject->GetStudyServant();
1359 // if study is locked, then paste can't be done
1360 if (aStudy->GetProperties()->IsLocked())
1361 throw SALOMEDS::StudyBuilder::LockProtection();
1363 // if there is no component name, then paste only SObjects and attributes: without component help
1364 Handle(TDataStd_Comment) aComponentName;
1365 bool aStructureOnly = !_clipboard->Main().Root().FindAttribute(TDataStd_Comment::GetID(), aComponentName);
1367 // get copied study ID
1368 Handle(TDataStd_Integer) aStudyIDAttribute;
1369 if (!_clipboard->Main().Root().FindAttribute(TDataStd_Integer::GetID(), aStudyIDAttribute))
1370 return SALOMEDS::SObject::_nil();
1372 // get component-engine
1373 SALOMEDS::SComponent_var aComponent;
1374 SALOMEDS::Driver_var anEngine;
1375 CORBA::String_var aString;
1376 if (!aStructureOnly) {
1377 aComponent = theObject->GetFatherComponent();
1378 if(!aComponent->ComponentIOR(aString))
1379 return SALOMEDS::SObject::_nil();
1381 CORBA::Object_var anObj = _orb->string_to_object(aString);
1382 anEngine = SALOMEDS::Driver::_narrow(anObj) ;
1385 // CAF document of current study usage
1386 Handle(TDocStd_Document) aDocument = aStudy->GetDocument();
1387 if (aDocument.IsNull())
1388 return SALOMEDS::SObject::_nil();
1390 // fill root inserted SObject
1391 int aCStudyID = aStudyIDAttribute->Get();
1392 TDF_Label aLabel = aStructureOnly? aSObject->GetLabel(): aSObject->GetFatherComponentLabel();
1393 TDF_Label aStartLabel = PasteLabel(aStudy,anEngine,_clipboard->Main(),aLabel,aCStudyID,true);
1395 // paste all sublebels
1396 TDF_ChildIterator anIterator(_clipboard->Main(),Standard_True);
1397 for(; anIterator.More(); anIterator.Next()) {
1398 PasteLabel(aStudy,anEngine,anIterator.Value(),aStartLabel,aCStudyID,false);
1401 return SALOMEDS_SObject_i::NewRef(aStudy,aStartLabel)._retn();