Salome HOME
1f8e0aa75067bc52597819a1a6e0a3bb702dd13a
[modules/kernel.git] / src / SALOMEDS / SALOMEDS_Study_i.cxx
1 //  SALOME SALOMEDS : data structure of SALOME and sources of Salome data server 
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOMEDS_Study_i.cxx
25 //  Author : Yves FRICAUD
26 //  Module : SALOME
27 //  $Header$
28
29 #include <TDataStd_ChildNodeIterator.hxx>
30 #include <TDocStd_Application.hxx>
31 #include <TDocStd_Owner.hxx>
32 #include <CDM_Document.hxx>
33 #include <CDM_Application.hxx>
34 #include <TDF_ChildIDIterator.hxx>
35
36 #include <TColStd_SequenceOfExtendedString.hxx>
37 #include <TCollection_ExtendedString.hxx>
38 #include <TCollection_AsciiString.hxx>
39
40 #include <TColStd_ListIteratorOfListOfInteger.hxx>
41 #include <TColStd_ListOfInteger.hxx>
42
43 #include "SALOMEDS_Study_i.hxx"
44
45 #include "SALOMEDS_StudyManager_i.hxx"
46 #include "SALOMEDS_Callback_i.hxx"
47
48 #include "SALOMEDS_SComponent_i.hxx"
49 #include "SALOMEDS_SObject_i.hxx"
50
51 #include "SALOMEDS_StudyBuilder_i.hxx"
52 #include "SALOMEDS_ChildIterator_i.hxx"
53
54 #include "SALOMEDS_UseCaseBuilder_i.hxx"
55 #include "SALOMEDS_SComponentIterator_i.hxx"
56
57 #include "SALOME_GenericObj_i.hh"
58 #include "SALOMEDS_LocalIDAttribute.hxx"
59 #include "SALOMEDS_PersRefAttribute.hxx"
60
61 #include "SALOMEDS_StudyPropertiesAttribute.hxx"
62 #include "SALOMEDS_DataMapIteratorOfDataMapStringLabel.hxx"
63
64 #include "utilities.h"
65
66 #define DIRECTORYID 16661
67 #define FILEID "FILE: "
68 #define FILELOCALID 26662 
69
70 using namespace std;
71
72 bool operator<(const TDF_Label& theLeft, const TDF_Label& theRight)
73 {
74   TColStd_ListOfInteger aTagLeftList;
75   TDF_Tool::TagList(theLeft,aTagLeftList);
76   TColStd_ListIteratorOfListOfInteger anLeftIter(aTagLeftList);
77   
78   TColStd_ListOfInteger aTagRightList;
79   TDF_Tool::TagList(theRight,aTagRightList);
80   TColStd_ListIteratorOfListOfInteger anRightIter(aTagRightList);
81   
82   for(;;){
83     Standard_Boolean aLeftMore = anLeftIter.More();
84     Standard_Boolean aRightMore = anRightIter.More();
85     
86     if(!aLeftMore && !aRightMore)
87       return Standard_False;
88     
89     if(!aLeftMore)
90       return Standard_True;
91     
92     if(!aRightMore)
93       return Standard_False;
94     
95     Standard_Integer aLeftTag = anLeftIter.Value();
96     anLeftIter.Next();
97     
98     Standard_Integer aRightTag = anRightIter.Value();
99     anRightIter.Next();
100     
101     if(aLeftTag == aRightTag)
102       continue;
103     
104     return aLeftTag < aRightTag;
105   }
106   
107   return Standard_False;
108 }
109
110   
111 //============================================================================
112 /*! Function : SALOMEDS_Study_i
113  *  Purpose  : SALOMEDS_Study_i constructor
114  */
115 //============================================================================
116 SALOMEDS_Study_i::SALOMEDS_Study_i(SALOMEDS_StudyManager_i* theStudyManager,
117                                    const Handle(TDocStd_Document)& theDoc,
118                                    const char* theStudyName):
119   _StudyManager(theStudyManager),
120   _doc(theDoc),
121   _isSaved(false),
122   _URL(NULL),
123   _StudyId(-1),
124   _autoFill(true),
125   myNbUndos(0)
126 {
127   _UseCaseBuilder = new SALOMEDS_UseCaseBuilder_i(this,_doc);
128   SALOMEDS::UseCaseBuilder_var aUseCaseBuilder = _UseCaseBuilder->_this();
129
130   _Builder = new SALOMEDS_StudyBuilder_i(this,_doc);
131   SALOMEDS::StudyBuilder_var aStudyBuilder = _Builder->_this(); 
132
133   SALOMEDS_Callback_i* aCallBackServant = new SALOMEDS_Callback_i(aUseCaseBuilder);
134   _callbackOnAdd = aCallBackServant->_this();
135   _callbackOnRemove = _callbackOnAdd;
136
137   _name = new char[strlen(theStudyName) +1];
138   strcpy(_name,theStudyName);
139   myNbPostponed.Append(0);
140 }
141   
142 //============================================================================
143 /*! Function : ~SALOMEDS_Study_i
144  *  Purpose  : SALOMEDS_Study_i destructor
145  */
146 //============================================================================
147 SALOMEDS_Study_i::~SALOMEDS_Study_i()
148 {
149   delete [] _name ;
150   delete [] _URL ;
151 }  
152
153 //============================================================================
154 CORBA::ORB_var SALOMEDS_Study_i::GetORB() const
155 {
156   return _StudyManager->GetORB();
157 }
158
159 //============================================================================
160 PortableServer::POA_var SALOMEDS_Study_i::GetPOA() const
161 {
162   return _StudyManager->GetPOA();
163 }
164
165
166 SALOMEDS_SObject_i* 
167 SALOMEDS_Study_i::DownCast(SALOMEDS::SObject_ptr theSObject) const
168 {
169   if(!CORBA::is_nil(theSObject)){
170     PortableServer::POA_var aPOA = GetPOA();
171     PortableServer::ServantBase_var aServant = SALOMEDS::GetServant(theSObject,aPOA);
172     if(aServant.in())
173       return dynamic_cast<SALOMEDS_SObject_i*>(aServant.in());
174   }
175   return NULL;
176 }
177
178 //============================================================================
179 /*! Function : SetOnAddSObject
180  *  Purpose  : 
181  */
182 //============================================================================
183 SALOMEDS::Callback_ptr SALOMEDS_Study_i::SetOnAddSObject(SALOMEDS::Callback_ptr theCallback)
184 {
185   SALOMEDS::Callback_var aRet = _callbackOnAdd;
186   _callbackOnAdd = SALOMEDS::Callback::_duplicate(theCallback);
187   return aRet._retn();
188 }
189
190 //============================================================================
191 /*! Function : SetOnNewSObject
192  *  Purpose  : 
193  */
194 //============================================================================
195 SALOMEDS::Callback_ptr SALOMEDS_Study_i::SetOnRemoveSObject(SALOMEDS::Callback_ptr theCallback)
196 {
197   SALOMEDS::Callback_var aRet = _callbackOnRemove;
198   _callbackOnAdd = SALOMEDS::Callback::_duplicate(theCallback);
199   return aRet._retn();
200 }
201
202 //============================================================================
203 void SALOMEDS_Study_i::OnAddSObject(SALOMEDS::SObject_ptr theObject)
204 {
205   if(!CORBA::is_nil(_callbackOnAdd.in()))
206     _callbackOnAdd->OnAddSObject(theObject);
207 }
208
209 //============================================================================
210 void SALOMEDS_Study_i::OnRemoveSObject(SALOMEDS::SObject_ptr theObject)
211 {
212   if(!CORBA::is_nil(_callbackOnRemove.in()))
213     _callbackOnRemove->OnRemoveSObject(theObject);
214 }
215
216 //============================================================================
217 void SALOMEDS_Study_i::CheckLocked()
218 {
219   if(_doc->HasOpenCommand()) 
220     return;
221
222   Handle(SALOMEDS_StudyPropertiesAttribute) anAttr;
223   if(_doc->Main().FindAttribute(SALOMEDS_StudyPropertiesAttribute::GetID(),anAttr))
224     if(anAttr->IsLocked())
225       throw SALOMEDS::StudyBuilder::LockProtection();
226 }
227
228
229 //============================================================================
230 char* SALOMEDS_Study_i::ConvertObjectToIOR(CORBA::Object_ptr theObject)
231 {
232   return GetORB()->object_to_string(theObject); 
233 }
234
235
236 //============================================================================
237 CORBA::Object_ptr SALOMEDS_Study_i::ConvertIORToObject(const char* theIOR) 
238
239   return GetORB()->string_to_object(theIOR); 
240 }
241
242
243 //============================================================================
244 /*! Function : GetPersistentReference
245  *  Purpose  : Get persistent reference of study (idem URL())
246  */
247 //============================================================================
248 char* SALOMEDS_Study_i::GetPersistentReference()
249 {
250   return URL();
251 }
252 //============================================================================
253 /*! Function : GetTransientReference
254  *  Purpose  : Get IOR of the Study (registred in OCAF document in doc->Root)
255  */
256 //============================================================================
257 char* SALOMEDS_Study_i::GetTransientReference()
258 {
259   CORBA::String_var IOR;
260
261   Handle(SALOMEDS_IORAttribute) Att;
262   TDF_Label _lab = _doc->GetData()->Root();
263   if (!_lab.FindAttribute(SALOMEDS_IORAttribute::GetID(),Att)){
264
265     TCollection_AsciiString ch(Att->Get());
266     IOR = CORBA::string_dup(ch.ToCString());
267   }
268   else IOR = CORBA::string_dup(""); // NULL ?
269
270   return CORBA::string_dup(IOR); 
271 }
272
273 //============================================================================
274 /*! Function : IsEmpty
275  *  Purpose  : Detect if study is empty
276  */
277 //============================================================================
278 CORBA::Boolean SALOMEDS_Study_i::IsEmpty()
279 {
280   if (_doc.IsNull()) return true;
281   return _doc->IsEmpty();
282 }
283
284 //============================================================================
285 /*! Function : FindComponent
286  *  Purpose  : Find a Component with ComponentDataType = aComponentName
287  */
288 //============================================================================
289 SALOMEDS::SComponent_ptr 
290 SALOMEDS_Study_i::FindComponent(const char* theComponentName)
291 {
292   bool anIsFound = false;
293   SALOMEDS::SComponent_var aSComponent;
294   SALOMEDS_SComponentIterator_i aComponentIter(this,_doc);
295   for(; aComponentIter.More() && !anIsFound; aComponentIter.Next()){
296     SALOMEDS::SComponent_var aSComp = aComponentIter.Value();
297     CORBA::String_var aName = aSComp->ComponentDataType();
298     if(strcmp(theComponentName,aName.in()) == 0){
299       aSComponent = aSComp;
300       anIsFound = true;
301     }
302   }
303   return aSComponent._retn();
304 }
305
306 //============================================================================
307 /*! Function : FindComponentID
308  *  Purpose  : Find a Component from it's ID
309  */
310 //============================================================================
311 SALOMEDS::SComponent_ptr SALOMEDS_Study_i::FindComponentID(const char* aComponentID)
312 {
313   // Iterate on each components defined in the study
314   // Get the component ID and compare with aComponentID 
315   bool _find = false;
316   char *ID;
317   SALOMEDS::SComponent_ptr compo;
318
319   SALOMEDS_SComponentIterator_i itcomp(this,_doc);
320   for (; itcomp.More(); itcomp.Next()) {
321     SALOMEDS::SComponent_var SC = itcomp.Value();
322     ID = SC->GetID();
323     if(strcmp(aComponentID,ID)==0)
324       {
325         // ComponentID found
326         _find = true;
327         compo = SALOMEDS::SComponent::_narrow(SC);
328       }
329   }
330   if(!_find)
331     {
332       compo = SALOMEDS::SComponent::_nil();
333     }
334   return compo;
335 }
336
337 //============================================================================
338 /*! Function : FindObject
339  *  Purpose  : Find an Object with SALOMEDS::Name = anObjectName
340  */
341 //============================================================================
342 SALOMEDS::SObject_ptr SALOMEDS_Study_i::FindObject(const char* theObjectName)
343 {
344   // Iterate to all components defined in the study
345   // After testing the component name, iterate in all objects defined under
346   // components (function _FindObject)
347   bool aIsFound = false;
348   SALOMEDS::SObject_var aRefSO;
349   SALOMEDS_SComponentIterator_i aComponentIter(this,_doc);
350   for(; aComponentIter.More() && !aIsFound; aComponentIter.Next()){
351     TDF_Label aLab = aComponentIter.GetValue();
352     Handle(TDataStd_Name) anAttr;
353     if(aLab.FindAttribute(TDataStd_Name::GetID(),anAttr)){
354       TCollection_AsciiString aString(anAttr->Get());
355       if(strcmp(aString.ToCString(),theObjectName) == 0){
356         aRefSO = SALOMEDS_SComponent_i::NewRef(this,aLab)._retn();
357         aIsFound = true;
358       }
359     }
360     if(!aIsFound) 
361       aRefSO = _FindObject(aLab,theObjectName,aIsFound);
362   }
363
364   return aRefSO._retn();
365 }
366
367 //============================================================================
368 /*! Function : FindObjectID
369  *  Purpose  : Find an Object with ID = anObjectID
370  */
371 //============================================================================
372 SALOMEDS::SObject_ptr SALOMEDS_Study_i::FindObjectID(const char* anObjectID)
373 {
374   // Convert aSO->GetID in TDF_Label.
375   TDF_Label Lab;
376   TDF_Tool::Label(_doc->GetData(), (char*)anObjectID, Lab);
377   
378   if (Lab.IsNull()) 
379     return SALOMEDS::SObject::_nil();
380
381   return SALOMEDS_SObject_i::NewRef(this,Lab)._retn();
382
383 }
384
385 //============================================================================
386 /*! Function : CreateObjectID
387  *  Purpose  : Creates an Object with ID = anObjectID
388  */
389 //============================================================================
390 SALOMEDS::SObject_ptr SALOMEDS_Study_i::CreateObjectID(const char* anObjectID)
391 {
392   // Convert aSO->GetID in TDF_Label.
393   TDF_Label Lab;
394   TDF_Tool::Label(_doc->GetData(), (char*)anObjectID, Lab, Standard_True);
395   
396   if (Lab.IsNull()) 
397     return SALOMEDS::SObject::_nil();
398
399   return SALOMEDS_SObject_i::NewRef(this,Lab)._retn();
400 }
401
402 //============================================================================
403 /*! Function : FindObjectByName
404  *  Purpose  : Find Objects with SALOMEDS::Name = anObjectName in a Component
405  *           : with ComponentDataType = aComponentName
406  */
407 //============================================================================
408 SALOMEDS::Study::ListOfSObject* 
409 SALOMEDS_Study_i::FindObjectByName(const char* theObjectName,
410                                    const char* theComponentName)
411 {
412   SALOMEDS::Study::ListOfSObject_var aListOfSObj = new SALOMEDS::Study::ListOfSObject ;
413   aListOfSObj->length(0);
414
415   SALOMEDS::SComponent_ptr aSComponent = FindComponent(theComponentName) ;
416   if(aSComponent->_is_nil()){
417     MESSAGE ("In FindObjectByName() :  Component named " << theComponentName << " not found ");
418     return aListOfSObj._retn();
419   }
420
421   // Iterate on each object and subobject of the component
422   // If objectName is found add it to the list of SObjects 
423   TDF_Label aLabel;
424   CORBA::String_var anEntry = aSComponent->GetID();
425   TDF_Tool::Label(_doc->GetData(),const_cast<char*>(anEntry.in()),aLabel);
426   
427   int aLength = 0 ;
428   SALOMEDS::SObject_var aRefSO;
429   TDF_ChildIterator aChildIter(aLabel,true);
430   for(; aChildIter.More(); aChildIter.Next()){
431     TDF_Label aLab = aChildIter.Value();
432     Handle(TDataStd_Name) anAttr;
433     if(aLab.FindAttribute(TDataStd_Name::GetID(),anAttr)){
434       TCollection_AsciiString aString(anAttr->Get());
435       if(strcmp(aString.ToCString(),theObjectName) == 0){
436         aRefSO = SALOMEDS_SObject_i::NewRef(this,aLab)._retn();
437         /* add to list */
438         aLength++ ;
439         aListOfSObj->length(aLength);
440         aListOfSObj[aLength-1] = aRefSO;
441       }
442     }
443   }
444
445   return aListOfSObj._retn() ;
446 }
447
448
449
450 //============================================================================
451 /*! Function : FindObjectIOR
452  *  Purpose  : Find an Object with IOR = anObjectIOR
453  */
454 //============================================================================
455 SALOMEDS::SObject_ptr SALOMEDS_Study_i::FindObjectIOR(const char* theObjectIOR)
456 {
457   // firstly searching in the datamap for optimization
458   char* anIOR = const_cast<char*>(theObjectIOR);
459   if(myIORLabels.IsBound(anIOR)){
460     TDF_Label aLabel = myIORLabels.Find(anIOR);
461     TSObjectHolder aSObjectHolder = SALOMEDS_SObject_i::New(this,aLabel);
462     SALOMEDS_SObject_i* aSObjectPtr = aSObjectHolder.first;
463     SALOMEDS::SObject_var aSObject = aSObjectHolder.second;
464     // 11 oct 2002: forbidden attributes must be checked here
465     SALOMEDS::GenericAttribute_var anAttr;
466     if(!aSObjectPtr->FindAttribute(anAttr,"AttributeIOR")){
467       myIORLabels.UnBind(anIOR);
468     }else{
469       return aSObject._retn();
470     }
471   }
472
473   // Iterate to all components defined in the study
474   // After testing the component name, iterate in all objects defined under
475   // components (function _FindObject)
476   bool aIsFound = false;
477   SALOMEDS::SObject_var aRefSO;
478   SALOMEDS_SComponentIterator_i aComponentIter(this,_doc);
479   for(; aComponentIter.More() && !aIsFound; aComponentIter.Next()){
480     TDF_Label aLab = aComponentIter.GetValue();
481     Handle(SALOMEDS_IORAttribute) anAttr;
482     if(aLab.FindAttribute(SALOMEDS_IORAttribute::GetID(),anAttr)){
483       TCollection_AsciiString aString(anAttr->Get());
484       if(strcmp(aString.ToCString(),theObjectIOR) == 0){
485         aRefSO = SALOMEDS_SComponent_i::NewRef(this,aLab);
486         aIsFound = true;
487       }
488     }
489     if(!aIsFound) 
490       aRefSO = _FindObjectIOR(aLab,theObjectIOR,aIsFound);
491   }
492
493   if(!aRefSO->_is_nil()) 
494     MESSAGE("SALOMEDS_Study_i::FindObjectIOR: found label with old methods");
495
496   return aRefSO._retn();
497 }
498
499 //============================================================================
500 /*! Function : FindObjectByPath
501  *  Purpose  : Find an Object by its path = thePath
502  */
503 //============================================================================
504 SALOMEDS::SObject_ptr SALOMEDS_Study_i::FindObjectByPath(const char* thePath)
505 {
506   TCollection_AsciiString aPath(CORBA::string_dup(thePath)), aToken;
507   SALOMEDS::SObject_var aSO = SALOMEDS::SObject::_nil();
508   int i = 1, aLength = aPath.Length();
509   bool isRelative = false;
510
511   if(aLength == 0) {  //Empty path - return the current context
512     return SALOMEDS_SObject_i::NewRef(this,_current)._retn();
513   }
514
515   if(aPath.Value(1) != '/')  //Relative path 
516     isRelative = true;
517
518   TDF_ChildIterator anIterator;
519   TDF_Label aLabel;
520   Handle(TDataStd_Name) anAttr;
521
522   if(isRelative) {
523     if(_current.IsNull()) throw SALOMEDS::Study::StudyInvalidContext(); 
524     anIterator.Initialize(_current, Standard_False);
525   }
526   else {
527     if(aPath.Length() == 1 && aPath.Value(1) == '/') {    //Root
528       return SALOMEDS_SObject_i::NewRef(this,_doc->Main())._retn();
529     }
530     anIterator.Initialize(_doc->Main(), Standard_False);
531   }
532
533   while(i <= aLength) {
534
535     aToken = aPath.Token("/", i);
536     if(aToken.Length() == 0) break;
537
538     for ( ; anIterator.More(); anIterator.Next() ) {
539       aLabel = anIterator.Value();
540       if(aLabel.FindAttribute(TDataStd_Name::GetID(), anAttr)) {
541         if(anAttr->Get() == aToken) {
542           aToken = aPath.Token("/", i+1); //Check if it was the last part of the path
543           if(aToken.Length() == 0) {  //The searched label is found (no part of the path is left)
544             return SALOMEDS_SObject_i::NewRef(this,aLabel)._retn();
545           }
546
547           anIterator.Initialize(aLabel, Standard_False);
548           break;
549         }
550       }
551     }
552
553     i++;
554   }
555
556   return aSO._retn();
557 }
558
559 //============================================================================
560 /*! Function : GetObjectPath
561  *  Purpose  : 
562  */
563 //============================================================================
564 char* SALOMEDS_Study_i::GetObjectPath(CORBA::Object_ptr theObject)
565 {
566   TCollection_AsciiString aPath("");
567   if(CORBA::is_nil(theObject)) 
568     return CORBA::string_dup(aPath.ToCString());
569
570   SALOMEDS::SObject_var anObject = SALOMEDS::SObject::_narrow(theObject);
571   if(anObject->_is_nil()) {
572     CORBA::String_var anIOR = GetORB()->object_to_string(theObject);
573     anObject = FindObjectIOR(anIOR);
574     if(anObject->_is_nil()) 
575       return CORBA::string_dup(aPath.ToCString());
576   }
577
578   SALOMEDS::GenericAttribute_var anAttr;
579   if(anObject->FindAttribute(anAttr, "AttributeName")) {
580     SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
581     if(anAttr->_is_nil()) 
582       return CORBA::string_dup(aPath.ToCString());
583     TCollection_AsciiString aValue(aName->Value());
584     aValue.Prepend("/");
585     aValue += aPath;
586     aPath = aValue;
587     SALOMEDS::SObject_ptr aFather = anObject->GetFather();
588     if(!aFather->_is_nil()) {
589       TDF_Label aLabel;
590       Handle(TDataStd_Name) aNameAttrib;
591       TDF_Tool::Label(_doc->GetData(), aFather->GetID(), aLabel);
592       if(aLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttrib)) {
593           aValue = GetObjectPath(aFather);
594           aPath = aValue + aPath;
595       }
596     }
597   }
598
599   return  CORBA::string_dup(aPath.ToCString());
600 }
601
602
603 //============================================================================
604 /*! Function : SetContext
605  *  Purpose  : Sets the current context
606  */
607 //============================================================================
608 void SALOMEDS_Study_i::SetContext(const char* thePath) 
609 {
610   if(thePath == NULL || strlen(thePath) == 0) throw SALOMEDS::Study::StudyInvalidDirectory();
611   TCollection_AsciiString aPath(CORBA::string_dup(thePath)), aContext("");
612   bool isInvalid = false;
613   SALOMEDS::SObject_var aSO;
614   
615   if(aPath.Value(1) != '/') { //Relative path 
616     aContext = TCollection_AsciiString(GetContext());
617     aContext += '/';
618     aContext += aPath;
619   }
620   else
621     aContext = aPath;
622   
623   try {
624     aSO = FindObjectByPath(aContext.ToCString());
625   }
626   catch( ... ) {
627     isInvalid = true;
628   }
629
630   if(isInvalid || aSO->_is_nil()) throw SALOMEDS::Study::StudyInvalidContext();
631
632   TDF_Label aLabel;
633   TDF_Tool::Label(_doc->GetData(), aSO->GetID(), aLabel);
634   if(aLabel.IsNull()) throw SALOMEDS::Study::StudyInvalidContext();
635   else
636     _current = aLabel;  //Set the current context
637   
638 }
639
640 //============================================================================
641 /*! Function : GetContext
642  *  Purpose  : Gets the current context
643  */
644 //============================================================================
645 char* SALOMEDS_Study_i::GetContext() 
646 {
647   if(_current.IsNull()) 
648     throw SALOMEDS::Study::StudyInvalidContext();   
649
650   SALOMEDS::SObject_var aSObject = SALOMEDS_SObject_i::NewRef(this,_current);
651   return GetObjectPath(aSObject);
652 }
653
654 //============================================================================
655 /*! Function : GetObjectNames
656  *  Purpose  : method to get all object names in the given context (or in the current context, if 'theContext' is empty)
657  */
658 //============================================================================
659 SALOMEDS::ListOfStrings* SALOMEDS_Study_i::GetObjectNames(const char* theContext) {
660   TColStd_SequenceOfExtendedString aResultSeq;
661   SALOMEDS::ListOfStrings_var aResult = new SALOMEDS::ListOfStrings;
662   TDF_Label aLabel;
663   if (strlen(theContext) == 0) {
664     if(_current.IsNull()) throw SALOMEDS::Study::StudyInvalidContext();   
665     aLabel = _current;
666   } else {
667     TDF_Label aTmp = _current;
668     SetContext(theContext);
669     aLabel = _current;
670     _current = aTmp;
671   }
672   TDF_ChildIterator anIter(aLabel, Standard_False); // iterate all subchildren at all sublevels
673   for(; anIter.More(); anIter.Next()) {
674     TDF_Label aLabel = anIter.Value();
675 //      Handle(TDF_Attribute) anAttribute;
676 //      if (aLabel.FindAttribute(SALOMEDS_IORAttribute::GetID(), anAttribute) ||
677 //      aLabel.FindAttribute(SALOMEDS_LocalIDAttribute::GetID(), anAttribute)) {
678     Handle(TDataStd_Name) aName;
679     if (aLabel.FindAttribute(TDataStd_Name::GetID(), aName)) aResultSeq.Append(aName->Get());
680 //    }
681   }
682   // fill the result table
683   int anIndex, aLength = aResultSeq.Length();
684   aResult->length(aLength);
685   for(anIndex = 0; anIndex < aLength; anIndex++) {
686     aResult[anIndex] = CORBA::string_dup(TCollection_AsciiString(aResultSeq.Value(anIndex + 1)).ToCString());
687   }
688   return aResult._retn();
689 }
690
691 //============================================================================
692 /*! Function : GetDirectoryNames
693  *  Purpose  : method to get all directory names in the given context (or in the current context, if 'theContext' is empty)
694  */
695 //============================================================================
696 SALOMEDS::ListOfStrings* SALOMEDS_Study_i::GetDirectoryNames(const char* theContext) {
697   TColStd_SequenceOfExtendedString aResultSeq;
698   SALOMEDS::ListOfStrings_var aResult = new SALOMEDS::ListOfStrings;
699   TDF_Label aLabel;
700   if (strlen(theContext) == 0) {
701     if(_current.IsNull()) throw SALOMEDS::Study::StudyInvalidContext();   
702     aLabel = _current;
703   } else {
704     TDF_Label aTmp = _current;
705     SetContext(theContext);
706     aLabel = _current;
707     _current = aTmp;
708   }
709   TDF_ChildIterator anIter(aLabel, Standard_False); // iterate first-level children at all sublevels
710   for(; anIter.More(); anIter.Next()) {
711     TDF_Label aLabel = anIter.Value();
712     Handle(SALOMEDS_LocalIDAttribute) anID;
713     if (aLabel.FindAttribute(SALOMEDS_LocalIDAttribute::GetID(), anID)) {
714       if (anID->Get() == DIRECTORYID) {
715         Handle(TDataStd_Name) aName;
716         if (aLabel.FindAttribute(TDataStd_Name::GetID(), aName)) {
717           aResultSeq.Append(aName->Get());
718         }
719       }
720     }
721   }
722   // fill the result table
723   int anIndex, aLength = aResultSeq.Length();
724   aResult->length(aLength);
725   for(anIndex = 0; anIndex < aLength; anIndex++) {
726     aResult[anIndex] = CORBA::string_dup(TCollection_AsciiString(aResultSeq.Value(anIndex + 1)).ToCString());
727   }
728   return aResult._retn();
729 }
730
731 //============================================================================
732 /*! Function : GetFileNames
733  *  Purpose  : method to get all file names in the given context (or in the current context, if 'theContext' is empty)
734  */
735 //============================================================================
736 SALOMEDS::ListOfStrings* SALOMEDS_Study_i::GetFileNames(const char* theContext) {
737   TColStd_SequenceOfExtendedString aResultSeq;
738   SALOMEDS::ListOfStrings_var aResult = new SALOMEDS::ListOfStrings;
739   TDF_Label aLabel;
740   if (strlen(theContext) == 0) {
741     if(_current.IsNull()) throw SALOMEDS::Study::StudyInvalidContext();   
742     aLabel = _current;
743   } else {
744     TDF_Label aTmp = _current;
745     SetContext(theContext);
746     aLabel = _current;
747     _current = aTmp;
748   }
749   TDF_ChildIterator anIter(aLabel, Standard_False); // iterate all subchildren at all sublevels
750   for(; anIter.More(); anIter.Next()) {
751     TDF_Label aLabel = anIter.Value();
752     Handle(SALOMEDS_LocalIDAttribute) anID;
753     if (aLabel.FindAttribute(SALOMEDS_LocalIDAttribute::GetID(), anID)) {
754       if (anID->Get() == FILELOCALID) {
755         Handle(SALOMEDS_PersRefAttribute) aName;
756         if(aLabel.FindAttribute(SALOMEDS_PersRefAttribute::GetID(), aName)) {
757           TCollection_ExtendedString aFileName = aName->Get();
758           if(aFileName.Length() > 0)
759             aResultSeq.Append(aFileName.Split(strlen(FILEID)));
760         }
761       }
762     }
763 //      }
764   }
765   // fill the result table
766   int anIndex, aLength = aResultSeq.Length();
767   aResult->length(aLength);
768   for(anIndex = 0; anIndex < aLength; anIndex++) {
769     aResult[anIndex] = CORBA::string_dup(TCollection_AsciiString(aResultSeq.Value(anIndex + 1)).ToCString());
770   }
771   return aResult._retn();
772 }
773
774 //============================================================================
775 /*! Function : GetComponentNames
776  *  Purpose  : method to get all components names
777  */
778 //============================================================================
779 SALOMEDS::ListOfStrings* SALOMEDS_Study_i::GetComponentNames(const char* theContext) {
780   TColStd_SequenceOfExtendedString aResultSeq;
781   SALOMEDS::ListOfStrings_var aResult = new SALOMEDS::ListOfStrings;
782   TDF_ChildIterator anIter(_doc->Main(), Standard_False); // iterate all subchildren at first level
783   for(; anIter.More(); anIter.Next()) {
784     TDF_Label aLabel = anIter.Value();
785     Handle(TDataStd_Name) aName;
786     if (aLabel.FindAttribute(TDataStd_Name::GetID(), aName)) aResultSeq.Append(aName->Get());
787   }
788   // fill the result table
789   int anIndex, aLength = aResultSeq.Length();
790   aResult->length(aLength);
791   for(anIndex = 0; anIndex < aLength; anIndex++) {
792     aResult[anIndex] = CORBA::string_dup(TCollection_AsciiString(aResultSeq.Value(anIndex + 1)).ToCString());
793   }
794   return aResult._retn();
795 }
796
797 //============================================================================
798 /*! Function : NewChildIterator
799  *  Purpose  : Create a ChildIterator from an SObject
800  */
801 //============================================================================
802 SALOMEDS::ChildIterator_ptr 
803 SALOMEDS_Study_i::NewChildIterator(SALOMEDS::SObject_ptr theSObject)
804 {
805   SALOMEDS_ChildIterator_i* aServant = 
806     new SALOMEDS_ChildIterator_i(GetChildIterator(theSObject));
807
808   return aServant->_this();
809 }
810
811 SALOMEDS_ChildIterator_i 
812 SALOMEDS_Study_i::GetChildIterator(SALOMEDS::SObject_ptr theSObject)
813 {
814   TDF_Label aLab;
815   TDF_Tool::Label(_doc->GetData(),theSObject->GetID(),aLab);
816   return SALOMEDS_ChildIterator_i(this,aLab);
817 }
818
819 //============================================================================
820 /*! Function : NewComponentIterator
821  *  Purpose  : Create a SComponentIterator
822  */
823 //============================================================================
824 SALOMEDS::SComponentIterator_ptr 
825 SALOMEDS_Study_i::NewComponentIterator()
826 {
827   SALOMEDS_SComponentIterator_i* aServant = 
828     new SALOMEDS_SComponentIterator_i(GetComponentIterator());
829
830   return aServant->_this();
831 }
832
833 SALOMEDS_SComponentIterator_i 
834 SALOMEDS_Study_i::GetComponentIterator()
835 {
836   return SALOMEDS_SComponentIterator_i(this,_doc);
837 }
838
839 //============================================================================
840 /*! Function : GetUseCaseBuilder
841  *  Purpose  : Returns a UseCase builder
842  */
843 //============================================================================
844 SALOMEDS::UseCaseBuilder_ptr SALOMEDS_Study_i::GetUseCaseBuilder() 
845 {
846   return _UseCaseBuilder->_this();
847 }
848
849 //============================================================================
850 /*! Function : NewBuilder
851  *  Purpose  : Create a StudyBuilder
852  */
853 //============================================================================
854 SALOMEDS_StudyBuilder_i* SALOMEDS_Study_i::GetBuilder()
855 {
856   return _Builder;
857 }
858  
859 SALOMEDS::StudyBuilder_ptr SALOMEDS_Study_i::NewBuilder()
860 {
861   return GetBuilder()->_this();
862 }
863  
864 //============================================================================
865 /*! Function : Name
866  *  Purpose  : get study name
867  */
868 //============================================================================
869 char* SALOMEDS_Study_i::Name()
870 {
871   return CORBA::string_dup(_name);
872 }
873
874 //============================================================================
875 /*! Function : Name
876  *  Purpose  : set study name
877  */
878 //============================================================================
879 void SALOMEDS_Study_i::Name(const char* name)
880 {
881   _name = new char[strlen(name) +1];
882   strcpy(_name,name);
883 }
884
885 //============================================================================
886 /*! Function : IsSaved
887  *  Purpose  : get if study has been saved
888  */
889 //============================================================================
890 CORBA::Boolean  SALOMEDS_Study_i::IsSaved()
891 {
892   return _isSaved;
893 }
894
895 //============================================================================
896 /*! Function : IsSaved
897  *  Purpose  : set if study has been saved
898  */
899 //============================================================================
900 void SALOMEDS_Study_i::IsSaved(CORBA::Boolean save)
901 {
902   _isSaved = save;
903 }
904
905 //============================================================================
906 /*! Function : IsModified
907  *  Purpose  : Detect if a Study has been modified since it has been saved
908  */
909 //============================================================================
910 CORBA::Boolean  SALOMEDS_Study_i::IsModified()
911 {
912   // True if is modified and not saved
913   if (_doc->IsModified())
914     if (!_isSaved) return true;
915     else return false;
916   else return false;
917 }
918
919 //============================================================================
920 /*! Function : URL
921  *  Purpose  : get URL of the study (persistent reference of the study)
922  */
923 //============================================================================
924 char* SALOMEDS_Study_i::URL()
925 {
926   if(!_URL) {
927     _URL = new char[1];
928     _URL[0] = (char)0;
929   }
930   return CORBA::string_dup(_URL);
931 }
932
933 //============================================================================
934 /*! Function : URL
935  *  Purpose  : set URL of the study (persistent reference of the study)
936  */
937 //============================================================================
938 void SALOMEDS_Study_i::URL(const char* url)
939 {
940   if (_URL) delete [] _URL;
941   _URL = new char[strlen(url) +1];
942   strcpy(_URL,url);
943   SCRUTE(_URL);
944
945   char *aName = _URL;
946   char *adr = strtok(aName, "/");
947   while (adr)
948     {
949       aName = adr;
950       adr = strtok(NULL, "/");
951     }
952   strcpy(_URL,url);
953   Name(aName);
954 }
955
956
957 //============================================================================
958 /*! Function : _FindObject
959  *  Purpose  : Find an Object with SALOMEDS::Name = anObjectName
960  */
961 //============================================================================
962 SALOMEDS::SObject_ptr 
963 SALOMEDS_Study_i::_FindObject(TDF_Label theLabel,
964                               const char* theObjectName, 
965                               bool& theIsFound)
966 {
967   theIsFound = false;
968   // Iterate on each objects and subobjects of the component
969   // If objectName find, stop the loop and get the object reference
970   SALOMEDS::SObject_var aRefSO;
971   TDF_ChildIterator aChildIter(theLabel,true);
972   for(; aChildIter.More() && !theIsFound; aChildIter.Next()){
973     TDF_Label aLab = aChildIter.Value();
974     Handle(TDataStd_Name) anAttr;
975     if(aLab.FindAttribute(TDataStd_Name::GetID(),anAttr)){
976       TCollection_AsciiString aString(anAttr->Get());
977       if(strcmp(aString.ToCString(),theObjectName) == 0){
978         aRefSO = SALOMEDS_SObject_i::NewRef(this,aLab);
979         theIsFound = true;
980       }
981     }
982   }
983   return aRefSO._retn();
984 }
985
986 //============================================================================
987 /*! Function : _FindObject
988  *  Purpose  : Find an Object with SALOMEDS::IOR = anObjectIOR
989  */
990 //============================================================================
991 SALOMEDS::SObject_ptr 
992 SALOMEDS_Study_i::_FindObjectIOR(TDF_Label theLabel,
993                                  const char* theObjectIOR, 
994                                  bool& theIsFound)
995 {
996   // Iterate on each objects and subobjects of the component
997   // If objectName find, stop the loop and get the object reference
998   SALOMEDS::SObject_var aRefSO;
999   TDF_ChildIterator aChildIter(theLabel,true);
1000   for(; aChildIter.More() && !theIsFound; aChildIter.Next()){
1001     TDF_Label aLab = aChildIter.Value();
1002     Handle(SALOMEDS_IORAttribute) anAttr;
1003     if(aLab.FindAttribute(SALOMEDS_IORAttribute::GetID(),anAttr)){
1004       TCollection_AsciiString aString(anAttr->Get());
1005       if(strcmp(aString.ToCString(),theObjectIOR) == 0){
1006         aRefSO = SALOMEDS_SObject_i::NewRef(this,aLab);
1007         theIsFound = true;
1008       }
1009     }
1010   }
1011   return aRefSO._retn();
1012 }
1013
1014 CORBA::Short SALOMEDS_Study_i::StudyId()
1015 {
1016   return _StudyId;
1017 }
1018
1019 void SALOMEDS_Study_i::StudyId(CORBA::Short id)
1020 {
1021   _StudyId = id;
1022 }
1023
1024 void SALOMEDS_Study_i::UpdateIORLabelMap(const char* anIOR,const char* anEntry) {
1025   TDF_Label aLabel;
1026   CORBA::String_var anEn = CORBA::string_dup(anEntry);
1027   CORBA::String_var IOR = CORBA::string_dup(anIOR);
1028   TDF_Tool::Label(_doc->GetData(),anEn,aLabel, Standard_True);
1029   if (myIORLabels.IsBound(TCollection_ExtendedString(IOR))) myIORLabels.UnBind(TCollection_ExtendedString(IOR));
1030   myIORLabels.Bind(TCollection_ExtendedString(IOR), aLabel);
1031 }
1032
1033 void SALOMEDS_Study_i::IORUpdated(const Handle(SALOMEDS_IORAttribute) theAttribute) {
1034   TCollection_AsciiString aString;
1035   TDF_Tool::Entry(theAttribute->Label(),aString);
1036   TCollection_AsciiString aValue(theAttribute->Get());
1037   UpdateIORLabelMap(aValue.ToCString(),aString.ToCString());
1038 }
1039
1040 SALOMEDS::Study::ListOfSObject* SALOMEDS_Study_i::FindDependances(SALOMEDS::SObject_ptr anObject) {
1041   SALOMEDS::GenericAttribute_ptr aTarget;
1042   if (anObject->FindAttribute(aTarget,"AttributeTarget")) {
1043     return SALOMEDS::AttributeTarget::_narrow(aTarget)->Get();
1044   }
1045   SALOMEDS::Study::ListOfSObject* aList = new SALOMEDS::Study::ListOfSObject;
1046   aList->length(0);
1047   return aList;
1048 }
1049
1050
1051 SALOMEDS::AttributeStudyProperties_ptr SALOMEDS_Study_i::GetProperties(){
1052   SALOMEDS::SObject_var aSObject = FindObjectID("0:1");
1053
1054   SALOMEDS::GenericAttribute_var anAttr =  
1055     GetBuilder()->FindOrCreateAttribute(aSObject,"AttributeStudyProperties");
1056
1057   return SALOMEDS::AttributeStudyProperties::_narrow(anAttr);
1058 }
1059
1060 char* SALOMEDS_Study_i::GetLastModificationDate() {
1061   SALOMEDS::AttributeStudyProperties_var aProp = GetProperties();
1062   SALOMEDS::StringSeq_var aNames;
1063   SALOMEDS::LongSeq_var aMinutes, aHours, aDays, aMonths, aYears;
1064   aProp->GetModificationsList(aNames , aMinutes ,aHours, aDays, aMonths, aYears, true);
1065   int aLastIndex = aNames->length() - 1;
1066   char aResult[20];
1067   sprintf(aResult, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d", (int)(aDays[aLastIndex]),(int)(aMonths[aLastIndex]),
1068           (int)(aYears[aLastIndex]), (int)(aHours[aLastIndex]), (int)(aMinutes[aLastIndex]));
1069   CORBA::String_var aResStr = CORBA::string_dup(aResult);
1070   return aResStr._retn();
1071 }
1072
1073 SALOMEDS::ListOfDates* SALOMEDS_Study_i::GetModificationsDate() {
1074   SALOMEDS::AttributeStudyProperties_var aProp = GetProperties();
1075   SALOMEDS::StringSeq_var aNames;
1076   SALOMEDS::LongSeq_var aMinutes, aHours, aDays, aMonths, aYears;
1077   aProp->GetModificationsList(aNames , aMinutes ,aHours, aDays, aMonths, aYears, false);
1078
1079   int anIndex, aLength = aNames->length();
1080   SALOMEDS::ListOfDates_var aDates = new SALOMEDS::ListOfDates;
1081   aDates->length(aLength);
1082
1083   for(anIndex = 0; anIndex < aLength; anIndex++) {
1084     char aDate[20];
1085     sprintf(aDate, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d", (int)(aDays[anIndex]), (int)(aMonths[anIndex]),
1086             (int)(aYears[anIndex]), (int)(aHours[anIndex]), (int)(aMinutes[anIndex]));
1087     aDates[anIndex] = CORBA::string_dup(aDate);
1088   }
1089   return aDates._retn();
1090 }
1091
1092
1093
1094 //============================================================================
1095 /*! Function : Close
1096  *  Purpose  : 
1097  */
1098 //============================================================================
1099 void SALOMEDS_Study_i::Close()
1100 {
1101   SALOMEDS_SComponentIterator_i itcomponent(this,_doc);
1102
1103   const CORBA::ORB_var& anORB = GetORB();
1104   for (; itcomponent.More(); itcomponent.Next()) {
1105     SALOMEDS::SComponent_var sco = itcomponent.Value();
1106           
1107     MESSAGE ( "Look for an engine for data type :"<< sco->ComponentDataType());
1108     // if there is an associated Engine call its method for closing
1109     CORBA::String_var IOREngine;
1110     if (sco->ComponentIOR(IOREngine)) {
1111       // we have found the associated engine to write the data 
1112       MESSAGE ( "We have found an engine for data type :"<< sco->ComponentDataType());
1113       CORBA::Object_var obj = anORB->string_to_object(IOREngine);
1114       if (!CORBA::is_nil(obj)) {
1115         SALOMEDS::Driver_var anEngine = SALOMEDS::Driver::_narrow(obj) ;
1116         
1117         if (!anEngine->_is_nil())  
1118           anEngine->Close(sco);
1119       }
1120     }
1121   }
1122
1123   Handle(TDocStd_Application) anApp = Handle(TDocStd_Application)::DownCast(_doc->Application());
1124 //    Handle(TDocStd_Owner) anOwner;
1125 //    if (_doc->Main().Root().FindAttribute(TDocStd_Owner::GetID(), anOwner)) {
1126 //      Handle(TDocStd_Document) anEmptyDoc;
1127 //      anOwner->SetDocument(anEmptyDoc);
1128 //    }
1129   if(!anApp.IsNull()) anApp->Close(_doc);
1130   _doc.Nullify();
1131 }
1132
1133 //============================================================================
1134 /*! Function : AddPostponed
1135  *  Purpose  : 
1136  */
1137  //============================================================================
1138 void SALOMEDS_Study_i::AddPostponed(const char* theIOR) {
1139   if (!GetBuilder()->HasOpenCommand()) return;
1140   try {
1141     CORBA::Object_var obj = GetORB()->string_to_object(theIOR);
1142     if (!CORBA::is_nil(obj)) {
1143       SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj) ;
1144       if (!CORBA::is_nil(aGeneric)) {
1145         TCollection_AsciiString anIOR(const_cast<char*>(theIOR));
1146         anIOR.Prepend("d");
1147         myPostponedIORs.Append(anIOR); // add prefix: deleted
1148         myNbPostponed.SetValue(myNbPostponed.Length(), myNbPostponed.Last() + 1);
1149       }
1150     }
1151   } catch(...) {}
1152 }
1153
1154 void SALOMEDS_Study_i::AddCreatedPostponed(const char* theIOR) {
1155   if (!GetBuilder()->HasOpenCommand()) return;
1156   try {
1157     CORBA::Object_var obj = GetORB()->string_to_object(theIOR);
1158     if (!CORBA::is_nil(obj)) {
1159       SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj) ;
1160       if (!CORBA::is_nil(aGeneric)) {
1161         TCollection_AsciiString anIOR(const_cast<char*>(theIOR));
1162         anIOR.Prepend("c");
1163         myPostponedIORs.Append(anIOR); // add prefix: created
1164         myNbPostponed.SetValue(myNbPostponed.Length(), myNbPostponed.Last() + 1);
1165       }
1166     }
1167   } catch(...) {}
1168 }
1169
1170 //============================================================================
1171 /*! Function : RemovePostponed
1172  *  Purpose  : 
1173  */
1174 //============================================================================
1175 void SALOMEDS_Study_i::RemovePostponed(const CORBA::Long theUndoLimit) {
1176   int anIndex;
1177   int anOld;
1178
1179   int aUndoLimit = theUndoLimit;
1180   if (theUndoLimit < 0) aUndoLimit = 0;
1181
1182   const CORBA::ORB_var& anORB = GetORB();
1183   if (myNbUndos > 0) { // remove undone
1184     anOld = 0;
1185     for(anIndex = 1; anIndex < myNbPostponed.Length() - myNbUndos; anIndex++)
1186       anOld += myNbPostponed(anIndex);
1187     int aNew = myPostponedIORs.Length() - myNbPostponed.Last();
1188
1189     for(anIndex = anOld + 1; anIndex <= aNew; anIndex++) {
1190       TCollection_AsciiString anIOR = myPostponedIORs(anIndex);
1191       if (anIOR.Value(1) == 'c') {
1192         CORBA::Object_var obj = anORB->string_to_object(anIOR.Split(1).ToCString());
1193         SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj);
1194         if (!CORBA::is_nil(aGeneric)) aGeneric->Destroy();
1195       }
1196     }
1197     if (anOld < aNew) myPostponedIORs.Remove(anOld + 1, aNew);
1198     if (myNbPostponed.Length() > 0) myNbPostponed.Remove(myNbPostponed.Length() - myNbUndos, myNbPostponed.Length() - 1);
1199
1200     myNbUndos = 0;
1201   }
1202
1203   if (myNbPostponed.Length() > aUndoLimit) { // remove objects, that can not be undone
1204     anOld = 0;
1205     for(anIndex = myNbPostponed.Length() - aUndoLimit; anIndex >= 1; anIndex--)
1206       anOld += myNbPostponed(anIndex);
1207     for(anIndex = 1; anIndex <= anOld; anIndex++) {
1208       TCollection_AsciiString anIOR = myPostponedIORs(anIndex);
1209       if (anIOR.Value(1) == 'd') {
1210         CORBA::Object_var obj = anORB->string_to_object(anIOR.Split(1).ToCString());
1211         SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj);
1212         if (!CORBA::is_nil(aGeneric)) aGeneric->Destroy();
1213       }
1214     }
1215     if (anOld > 0) myPostponedIORs.Remove(1, anOld);
1216     myNbPostponed.Remove(1, myNbPostponed.Length() - aUndoLimit);
1217   }
1218
1219   if (theUndoLimit == -1) { // remove all IORs from the study on the study close
1220     TDF_ChildIDIterator anIter(_doc->GetData()->Root(), SALOMEDS_IORAttribute::GetID(), Standard_True);
1221     for(; anIter.More(); anIter.Next()) {
1222       Handle(SALOMEDS_IORAttribute) anAttr = Handle(SALOMEDS_IORAttribute)::DownCast(anIter.Value());
1223       CORBA::String_var anIOR = CORBA::string_dup(TCollection_AsciiString(anAttr->Get()).ToCString());
1224       try {
1225         CORBA::Object_var obj = anORB->string_to_object(anIOR);
1226         SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj);
1227         if (!CORBA::is_nil(aGeneric)) aGeneric->Destroy();
1228       } catch (...) {}
1229     }
1230   } else myNbPostponed.Append(0);
1231 }
1232
1233 //============================================================================
1234 /*! Function : UndoPostponed
1235  *  Purpose  : 
1236  */
1237 //============================================================================
1238 void SALOMEDS_Study_i::UndoPostponed(const CORBA::Long theWay) {
1239   myNbUndos += theWay;
1240   // remove current postponed
1241   if (myNbPostponed.Last() > 0)
1242     myPostponedIORs.Remove(myPostponedIORs.Length() - myNbPostponed.Last() + 1, myPostponedIORs.Length());
1243   myNbPostponed(myNbPostponed.Length()) = 0;
1244 }