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