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