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