0024164: Optimization of OCAF document closing
[occt.git] / src / TDocStd / TDocStd_Document.cxx
1 // Copyright (c) 2006-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18
19 #include <TDocStd_Document.ixx>
20
21 #include <TDocStd.hxx>
22
23 #include <TDocStd_XLink.hxx>
24 #include <TDocStd_XLinkIterator.hxx>
25 #include <TDocStd_Application.hxx>
26
27 #include <TDocStd_Context.hxx>
28 #include <TCollection_ExtendedString.hxx>
29 #include <TCollection_AsciiString.hxx>
30 #include <TDF_AttributeIterator.hxx>
31 #include <TDF_ListIteratorOfDeltaList.hxx>
32 #include <TDF_AttributeList.hxx>
33 #include <TDF_ListIteratorOfAttributeList.hxx>
34 #include <TDF_AttributeDelta.hxx>
35 #include <TDF_AttributeDeltaList.hxx>
36 #include <TDF_ListIteratorOfAttributeDeltaList.hxx>
37 #include <TDF_Label.hxx>
38 #include <TDF_Delta.hxx>
39 #include <TDocStd_CompoundDelta.hxx>
40 #include <TDocStd_Owner.hxx>
41 #include <TDocStd_Modified.hxx>
42
43 #include <TDF_IDMap.hxx>
44 #include <TDocStd_LabelIDMapDataMap.hxx>
45
46 #include <CDM_MetaData.hxx>
47
48 // List should have a RemoveLast...
49 #define TDocStd_List_RemoveLast(theList) \
50 TDF_ListIteratorOfDeltaList it(theList); \
51 Standard_Integer i,n = theList.Extent(); \
52 for (i = 1; i < n; i++) it.Next(); \
53 theList.Remove(it);
54
55 #undef DEB_TRANS
56
57 #undef DEB_DELTA
58
59 #define BUC60836
60
61 #define SRN_DELTA_COMPACT
62
63 //=======================================================================
64 //function : Get
65 //purpose  : 
66 //=======================================================================
67
68 Handle(TDocStd_Document) TDocStd_Document::Get (const TDF_Label& acces)
69 {
70   return TDocStd_Owner::GetDocument(acces.Data());
71 }
72
73 //=======================================================================
74 //function : TDocStd_Document
75 //purpose  : 
76 //=======================================================================
77
78
79 TDocStd_Document::TDocStd_Document(const TCollection_ExtendedString& aStorageFormat) : 
80 myStorageFormat(aStorageFormat),
81 myData (new TDF_Data()),
82 myUndoLimit(0),
83 mySaveTime(0),
84 myIsNestedTransactionMode(0)
85 {
86   TDF_Transaction* pTr =  new TDF_Transaction (myData,"UNDO");
87   myUndoTransaction    = *pTr; delete pTr;
88   TDocStd_Owner::SetDocument(myData,this);
89
90 #ifdef SRN_DELTA_COMPACT
91   myFromUndo.Nullify();  
92   myFromRedo.Nullify();
93 #endif
94 }
95
96
97 //=======================================================================
98 //function : IsSaved
99 //purpose  : 
100 //=======================================================================
101
102 Standard_Boolean TDocStd_Document::IsSaved() const
103 {
104   return CDM_Document::IsStored();
105 }
106
107
108 //=======================================================================
109 //function : GetName
110 //purpose  : 
111 //=======================================================================
112
113 TCollection_ExtendedString TDocStd_Document::GetName () const
114 {
115   return CDM_Document::MetaData()->Name();
116 }
117
118 //=======================================================================
119 //function : GetPath
120 //purpose  : 
121 //=======================================================================
122
123 TCollection_ExtendedString TDocStd_Document::GetPath () const
124 {
125   return CDM_Document::MetaData()->Path();
126 }
127
128
129 //=======================================================================
130 //function : SetData
131 //purpose  : 
132 //=======================================================================
133
134 void TDocStd_Document::SetData (const Handle(TDF_Data)& D)
135 {
136   myData = D;
137   TDF_Transaction* pTr = new TDF_Transaction(myData,"UNDO");
138   myUndoTransaction = *pTr; delete pTr;  
139 }
140
141 //=======================================================================
142 //function : GetData
143 //purpose  : 
144 //=======================================================================
145
146 Handle(TDF_Data) TDocStd_Document::GetData () const
147 {
148   return myData;
149 }
150
151 //=======================================================================
152 //function : Main
153 //purpose  : 
154 //=======================================================================
155
156 TDF_Label TDocStd_Document::Main () const
157
158   return  myData->Root().FindChild(1,Standard_True);
159 }
160
161 //=======================================================================
162 //function : IsEmpty
163 //purpose  : 
164 //=======================================================================
165
166 Standard_Boolean TDocStd_Document::IsEmpty() const
167 {
168   TDF_AttributeIterator It (Main());
169   return !It.More();
170 }
171
172 //=======================================================================
173 //function : IsValid
174 //purpose  : 
175 //=======================================================================
176
177 Standard_Boolean TDocStd_Document::IsValid() const
178 {
179   return TDocStd_Modified::IsEmpty(Main());
180 }
181
182 //=======================================================================
183 //function : SetModified
184 //purpose  : 
185 //=======================================================================
186
187 void TDocStd_Document::SetModified (const TDF_Label& L)                                  
188 {  
189   TDocStd_Modified::Add(L);
190 }
191
192 //=======================================================================
193 //function : IsModified
194 //purpose  : 
195 //=======================================================================
196 //Standard_Boolean TDocStd_Document::IsModified (const TDF_Label& L) const                                 
197 //{  
198 //  return TDocStd_Modified::Contains(L);
199 //}
200
201 //=======================================================================
202 //function : PurgeModified
203 //purpose  : 
204 //=======================================================================
205
206 void TDocStd_Document::PurgeModified()
207 {   
208   TDocStd_Modified::Clear(Main()); 
209 }
210
211 //=======================================================================
212 //function : GetModified
213 //purpose  : 
214 //=======================================================================
215
216 const TDF_LabelMap&  TDocStd_Document::GetModified() const
217 {  
218   return TDocStd_Modified::Get(Main());  
219 }
220
221
222
223 //=======================================================================
224 //function : Update
225 //purpose  : 
226 //=======================================================================
227
228 void TDocStd_Document::Update(const Handle(CDM_Document)& /*aToDocument*/,
229                                const Standard_Integer aReferenceIdentifier,
230                                const Standard_Address aModifContext) 
231 {
232   const TDocStd_Context CC = *((TDocStd_Context *)&aModifContext);
233   if (CC.ModifiedReferences() || !IsUpToDate(aReferenceIdentifier)) {
234     TCollection_AsciiString aDocEntry(aReferenceIdentifier);
235     UpdateReferences(aDocEntry);
236     SetIsUpToDate(aReferenceIdentifier);
237   }
238 }
239
240 //=======================================================================
241 //function : NewCommand
242 //purpose  : 
243 //=======================================================================
244
245 void TDocStd_Document::NewCommand()
246 {
247 #ifdef DEB_TRANS
248   if (myUndoTransaction.IsOpen() && myData->Transaction() > 1) {
249     Standard_DomainError::Raise ("NewCommand : many open transactions");
250   }
251 #endif
252
253   CommitTransaction();
254   OpenTransaction();
255
256 #ifdef DEB_TRANS
257   cout<<"End NewCommand"<<endl;
258 #endif
259 }
260
261
262 //=======================================================================
263 //function : HasOpenCommand
264 //purpose  : 
265 //=======================================================================
266 Standard_Boolean TDocStd_Document::HasOpenCommand() const
267 {
268   return myUndoTransaction.IsOpen();
269 }
270
271 //=======================================================================
272 //function : OpenCommand
273 //purpose  : 
274 //=======================================================================
275
276 void TDocStd_Document::OpenCommand ()
277 {
278   if (!myIsNestedTransactionMode && myUndoTransaction.IsOpen()) {
279     Standard_DomainError::Raise("TDocStd_Document::OpenCommand : already open");
280   }
281   OpenTransaction();
282 //  if (myUndoLimit != 0) myUndoTransaction.Open();
283 }
284
285 //=======================================================================
286 //function : CommitCommand
287 //purpose  : 
288 //=======================================================================
289
290 Standard_Boolean TDocStd_Document::CommitCommand ()
291 {
292   return CommitTransaction();
293 }
294
295
296 //=======================================================================
297 //function : AbortCommand
298 //purpose  : 
299 //=======================================================================
300
301 void TDocStd_Document::AbortCommand ()
302
303   AbortTransaction();
304 }
305
306
307 //=======================================================================
308 //function : CommitTransaction
309 //purpose  : Private method.
310 //=======================================================================
311
312 Standard_Boolean TDocStd_Document::CommitTransaction()
313 {
314   myData->AllowModification(Standard_True);
315
316   Standard_Boolean isDone = Standard_False;
317   // nested transaction mode
318   if (myIsNestedTransactionMode && myUndoTransaction.IsOpen()) {
319
320     Handle(TDF_Delta) D = myUndoTransaction.Commit(Standard_True);
321     Handle(TDocStd_CompoundDelta) aCompDelta =
322       Handle(TDocStd_CompoundDelta)::DownCast(myUndoFILO.First());
323     AppendDeltaToTheFirst(aCompDelta, D);
324     D = aCompDelta;
325     myUndoFILO.RemoveFirst();
326     if(myUndoFILO.Extent()) {
327       aCompDelta = Handle(TDocStd_CompoundDelta)::DownCast(myUndoFILO.First());
328       AppendDeltaToTheFirst(aCompDelta, D);
329       myUndoTransaction.Open();
330     }
331     else {
332       if(!D->IsEmpty()) {
333         myUndos.Append(D);
334         myRedos.Clear(); // if we push an Undo we clear the redos
335         isDone = Standard_True;
336       }
337     }
338
339     // deny modifications if the transaction is not opened
340     if(myOnlyTransactionModification) {
341       myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
342                                 ? Standard_True :Standard_False);
343     }
344
345   } else {
346
347   // are we undoing...
348     if (myUndoLimit != 0 && myUndoTransaction.IsOpen()) {
349
350       Handle(TDF_Delta) D = myUndoTransaction.Commit(Standard_True);
351       if (!(D.IsNull() || D->IsEmpty())) {
352         isDone = Standard_True;
353
354         myRedos.Clear(); // if we push an Undo we clear the redos
355         myUndos.Append(D); // New undos are at the end of the list
356         // Check  the limit to remove the oldest one
357         if (myUndos.Extent() > myUndoLimit) {
358 #ifdef SRN_DELTA_COMPACT
359           Handle(TDF_Delta) aDelta = myUndos.First();
360 #endif
361           myUndos.RemoveFirst();
362 #ifdef SRN_DELTA_COMPACT
363           if(myFromUndo == aDelta) {
364             //The oldest Undo delta coincides with `from` delta
365             if(myUndos.Extent() == 1) {   //There is the only Undo
366               myFromUndo.Nullify();
367               myFromRedo.Nullify();
368             }
369             else
370               myFromUndo = myUndos.First();
371           }
372 #endif
373         }
374       }
375
376     }
377
378     // deny or allow modifications acording to transaction state
379     if(myOnlyTransactionModification) {
380       myData->AllowModification (myUndoTransaction.IsOpen() && myUndoLimit
381                                  ? Standard_True :Standard_False);
382     }
383   }
384   // Notify CDM_Application of the successful commit
385   if (isDone && IsOpened()) {
386     const Handle(TDocStd_Application) anAppli =
387       Handle(TDocStd_Application)::DownCast(Application());
388     if (!anAppli.IsNull())
389       anAppli -> OnCommitTransaction (this);
390   }
391   return isDone;
392 }
393
394
395 //=======================================================================
396 //function : AbortTransaction
397 //purpose  : Private method.
398 //=======================================================================
399
400 void TDocStd_Document::AbortTransaction()
401 {
402   myData->AllowModification(Standard_True);
403   
404   if (myUndoTransaction.IsOpen())
405     if (myUndoLimit != 0)
406       myUndoTransaction.Abort();
407
408   if (myIsNestedTransactionMode && myUndoFILO.Extent()) {
409     if (!myUndoFILO.First()->IsEmpty())
410       myData->Undo(myUndoFILO.First(),Standard_True);
411     myUndoFILO.RemoveFirst();
412     if (myUndoFILO.Extent())
413       myUndoTransaction.Open();
414   }
415   // deny or allow modifications acording to transaction state
416   if (myOnlyTransactionModification) {
417     myData->AllowModification (myUndoTransaction.IsOpen() && myUndoLimit
418                                ? Standard_True :Standard_False);
419   }
420   // Notify CDM_Application of the event
421   if (IsOpened()) {
422     const Handle(TDocStd_Application) anAppli =
423       Handle(TDocStd_Application)::DownCast(Application());
424     if (!anAppli.IsNull())
425       anAppli -> OnAbortTransaction (this);
426   }
427 }
428
429
430 //=======================================================================
431 //function :OpenTransaction
432 //purpose  : Private method.
433 //=======================================================================
434
435 void TDocStd_Document::OpenTransaction()
436 {
437   myData->AllowModification(Standard_True);
438
439   // nested transaction mode
440   if (myIsNestedTransactionMode) {
441
442     if (myUndoTransaction.IsOpen()) {
443       Handle(TDF_Delta) D = myUndoTransaction.Commit(Standard_True);
444       Handle(TDocStd_CompoundDelta) aCompDelta =
445         Handle(TDocStd_CompoundDelta)::DownCast(myUndoFILO.First());
446       AppendDeltaToTheFirst(aCompDelta, D);
447     }
448     Standard_Integer aLastTime = myData->Time();
449     if (myUndoFILO.Extent())
450       aLastTime = myUndoFILO.First()->EndTime();
451     Handle(TDocStd_CompoundDelta) aCompoundDelta =
452       new TDocStd_CompoundDelta;
453     aCompoundDelta->Validity(aLastTime, aLastTime);
454     myUndoFILO.Prepend(aCompoundDelta);
455   } 
456
457   if (myUndoLimit != 0) myUndoTransaction.Open();
458
459   // deny or allow modifications acording to transaction state
460   if (myOnlyTransactionModification) {
461     myData->AllowModification (myUndoTransaction.IsOpen() && myUndoLimit
462                                ? Standard_True :Standard_False);
463   }
464   // Notify CDM_Application of the event
465   if (IsOpened()) {
466     const Handle(TDocStd_Application) anAppli =
467       Handle(TDocStd_Application)::DownCast(Application());
468     if (!anAppli.IsNull())
469       anAppli -> OnOpenTransaction (this);
470   }
471 }
472
473 //=======================================================================
474 //function : SetUndoLimit
475 //purpose  : 
476 //=======================================================================
477
478 void TDocStd_Document::SetUndoLimit(const Standard_Integer L)
479 {  
480 #ifdef SRN_DELTA_COMPACT
481   myFromUndo.Nullify();  //Compaction has to aborted
482   myFromRedo.Nullify();
483 #endif
484
485   CommitTransaction ();
486   myUndoLimit = (L > 0) ? L : 0;
487   Standard_Integer n = myUndos.Extent() - myUndoLimit;
488   while (n > 0) {
489     myUndos.RemoveFirst();
490     --n;
491   }
492   // deny or allow modifications acording to transaction state
493   if(myOnlyTransactionModification) {
494     myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
495                               ? Standard_True :Standard_False);
496   }
497   //OpenTransaction(); dp 15/10/99
498 }
499
500 //=======================================================================
501 //function : GetUndoLimit
502 //purpose  : 
503 //=======================================================================
504
505 Standard_Integer TDocStd_Document::GetUndoLimit() const
506 {
507   return myUndoLimit;
508 }
509
510 //=======================================================================
511 //function : Undos
512 //purpose  : 
513 //=======================================================================
514
515 Standard_Integer TDocStd_Document::GetAvailableUndos() const
516 {
517   return myUndos.Extent();
518 }
519
520 //=======================================================================
521 //function : ClearUndos
522 //purpose  : 
523 //=======================================================================
524
525 void TDocStd_Document::ClearUndos()
526 {
527   myUndos.Clear();
528   myRedos.Clear();
529 #ifdef SRN_DELTA_COMPACT
530   myFromRedo.Nullify();
531   myFromUndo.Nullify();
532 #endif
533 }
534
535 //=======================================================================
536 //function : ClearRedos
537 //purpose  : 
538 //=======================================================================
539
540 void TDocStd_Document::ClearRedos()
541 {
542   myRedos.Clear();
543 #ifdef SRN_DELTA_COMPACT
544   myFromRedo.Nullify();
545 #endif
546 }
547
548 //=======================================================================
549 //function : Undo
550 //purpose  : 
551 // Some importante notice:
552 // 1) The most recent undo delta is at the end of the list.
553 // 2) Removing the LAST item of a list is tedious, but it is done only on
554 //    Undo. Remove first is done at each command if the limit is reached!
555 // 3) To make fun, the redos are not like the undos: the most recent delta
556 //    is at the beginning! Like this, it is easier to remove it after use.
557 //=======================================================================
558 Standard_Boolean TDocStd_Document::Undo() 
559 {
560   // Don't call NewCommand(), because it may commit Interactive Attributes
561   // and generate a undesirable Delta!
562
563   Standard_Boolean isOpened = myUndoTransaction.IsOpen();
564   Standard_Boolean undoDone = Standard_False;
565   //TDF_Label currentObjectLabel = CurrentLabel (); //Sauve pour usage ulterieur.
566
567   if (!myUndos.IsEmpty()) {
568     // Reset the transaction
569     AbortTransaction();
570
571     // only for nested transaction mode
572     while(myIsNestedTransactionMode && myUndoFILO.Extent())
573       AbortTransaction();
574
575     // allow modifications
576     myData->AllowModification(Standard_True);
577
578     // Apply the Undo
579     // should test the applicability before.
580 #ifdef DEB_DELTA
581     cout<<"DF before Undo =================================="<<endl; TDF_Tool::DeepDump(cout,myData);
582 #endif
583     Handle(TDF_Delta) D = myData->Undo(myUndos.Last(),Standard_True);
584 #ifdef BUC60836 
585     D->SetName(myUndos.Last()->Name());
586 #endif
587 #ifdef DEB_DELTA
588     cout<<"DF after Undo =================================="<<endl; TDF_Tool::DeepDump(cout,myData);
589 #endif
590     // Push the redo
591     myRedos.Prepend(D);
592     // Remove the last Undo
593     TDocStd_List_RemoveLast(myUndos);
594     undoDone = Standard_True;
595   }
596
597   if (isOpened && undoDone) OpenTransaction();
598
599   // deny or allow modifications acording to transaction state
600   if(myOnlyTransactionModification) {
601     myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
602                               ? Standard_True :Standard_False);
603   }
604   
605   return undoDone;
606 }
607
608 //=======================================================================
609 //function : GetAvailableRedos
610 //purpose  : 
611 //=======================================================================
612
613 Standard_Integer TDocStd_Document:: GetAvailableRedos() const
614 {
615   // should test the applicability before.
616   return myRedos.Extent();
617 }
618
619 //=======================================================================
620 //function : Redo
621 //purpose  : 
622 //=======================================================================
623 Standard_Boolean TDocStd_Document::Redo() 
624 {
625   Standard_Boolean isOpened = myUndoTransaction.IsOpen();
626   Standard_Boolean undoDone = Standard_False;
627   // TDF_Label currentObjectLabel = CurrentLabel();//Sauve pour usage ulterieur.
628   if (!myRedos.IsEmpty()) {
629     // should test the applicability before.
630     // Reset the transaction
631     AbortTransaction();
632
633     // only for nested transaction mode
634     while(myIsNestedTransactionMode && myUndoFILO.Extent())
635       AbortTransaction();
636
637     // allow modifications
638     myData->AllowModification(Standard_True);
639
640     // Apply the Redo
641 #ifdef DEB_DELTA
642     cout<<"DF before Redo =================================="<<endl; TDF_Tool::DeepDump(cout,myData);
643 #endif
644     Handle(TDF_Delta) D = myData->Undo(myRedos.First(),Standard_True);
645 #ifdef BUC60836
646     D->SetName(myRedos.First()->Name());
647 #endif
648 #ifdef DEB_DELTA
649     cout<<"DF after Redo =================================="<<endl; TDF_Tool::DeepDump(cout,myData);
650 #endif
651     // Push the redo of the redo as an undo (got it !)
652     myUndos.Append(D);
653     // remove the Redo from the head
654     myRedos.RemoveFirst();
655     undoDone = Standard_True;
656   }
657   
658   if (isOpened && undoDone) OpenTransaction();
659
660   // deny or allow modifications acording to transaction state
661   if(myOnlyTransactionModification) {
662     myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
663                               ? Standard_True :Standard_False);
664   }
665
666   return undoDone;
667 }
668
669 //=======================================================================
670 //function : UpdateReferences
671 //purpose  : 
672 //=======================================================================
673
674 void TDocStd_Document::UpdateReferences(const TCollection_AsciiString& aDocEntry) 
675 {
676
677   TDF_AttributeList aRefList;
678   TDocStd_XLink* xRefPtr;
679   for (TDocStd_XLinkIterator xItr (this); xItr.More(); xItr.Next()) {
680     xRefPtr = xItr.Value();
681     if (xRefPtr->DocumentEntry() == aDocEntry) {
682       aRefList.Append(xRefPtr->Update());
683     }
684   }
685   TDF_ListIteratorOfAttributeList It(aRefList);
686   for (;It.More();It.Next()) {
687     //     // mise a jour import
688     SetModified(It.Value()->Label());
689   }
690 }
691
692
693 //=======================================================================
694 //function : GetUndos
695 //purpose  : 
696 //=======================================================================
697
698 const TDF_DeltaList& TDocStd_Document::GetUndos() const 
699 {
700   return myUndos;
701 }
702
703
704 //=======================================================================
705 //function : GetRedos
706 //purpose  : 
707 //=======================================================================
708
709 const TDF_DeltaList& TDocStd_Document::GetRedos() const 
710 {
711   return myRedos;
712 }
713
714 //=======================================================================
715 //function : InitDeltaCompaction
716 //purpose  : 
717 //=======================================================================
718
719 Standard_Boolean TDocStd_Document::InitDeltaCompaction()
720 {
721 #ifdef SRN_DELTA_COMPACT
722   if (myUndoLimit == 0 || myUndos.Extent() == 0) {
723     myFromRedo.Nullify();
724     myFromUndo.Nullify();
725     return Standard_False; //No Undos to compact
726   }
727
728   myFromRedo.Nullify();
729
730   myFromUndo = myUndos.Last();
731   if(myRedos.Extent() > 0) myFromRedo = myRedos.First();
732 #endif
733   return Standard_True;
734 }
735
736 //=======================================================================
737 //function : PerformDeltaCompaction
738 //purpose  : 
739 //=======================================================================
740
741 Standard_Boolean TDocStd_Document::PerformDeltaCompaction()  
742
743 #ifdef SRN_DELTA_COMPACT
744   if(myFromUndo.IsNull()) return Standard_False;  //Redo can be Null for this operation 
745
746   TDF_DeltaList aList; 
747   Handle(TDocStd_CompoundDelta) aCompoundDelta = new TDocStd_CompoundDelta; 
748   TDF_ListIteratorOfDeltaList anIterator(myUndos); 
749   TDF_ListIteratorOfAttributeDeltaList aDeltasIterator;
750   TDocStd_LabelIDMapDataMap aMap; 
751   Standard_Boolean isFound = Standard_False, isTimeSet = Standard_False; 
752
753   //Process Undos
754
755   for(; anIterator.More(); anIterator.Next()) { 
756     if(!isFound) { 
757       if(myFromUndo == anIterator.Value()) isFound = Standard_True; 
758       aList.Append(anIterator.Value());  //Fill the list of deltas that precede compound delta 
759       continue;
760     } 
761
762     if(!isTimeSet) {  //Set begin and end time when the compound delta is valid
763       aCompoundDelta->Validity(anIterator.Value()->BeginTime(), myUndos.Last()->EndTime());
764       isTimeSet = Standard_True;
765     } 
766     
767     aDeltasIterator.Initialize(anIterator.Value()->AttributeDeltas());
768     for(; aDeltasIterator.More(); aDeltasIterator.Next()) {   
769       if(!aMap.IsBound(aDeltasIterator.Value()->Label())) {
770         TDF_IDMap* pIDMap = new TDF_IDMap();
771         aMap.Bind(aDeltasIterator.Value()->Label(), *pIDMap);
772         delete pIDMap;
773         }
774       if(aMap(aDeltasIterator.Value()->Label()).Add(aDeltasIterator.Value()->ID())) //The attribute is not 
775         aCompoundDelta->AddAttributeDelta(aDeltasIterator.Value());                 //already in the delta
776     }
777   } 
778
779   myUndos.Clear(); 
780   myUndos.Assign(aList); 
781   myUndos.Append(aCompoundDelta); 
782
783   //Process Redos
784
785   if(myFromRedo.IsNull()) {
786     myRedos.Clear();
787     return Standard_True;
788   }
789
790   aList.Clear();
791
792   for(anIterator.Initialize(myRedos); anIterator.More(); anIterator.Next()) { 
793     aList.Append(anIterator.Value()); 
794     if(anIterator.Value() == myFromRedo) break;
795   }
796
797   myRedos.Clear();
798   myRedos.Assign(aList); 
799 #endif
800   return Standard_True; 
801
802
803
804 //=======================================================================
805 //function : StorageFormat
806 //purpose  : 
807 //=======================================================================
808
809 TCollection_ExtendedString TDocStd_Document::StorageFormat() const 
810 {
811   return myStorageFormat;
812 }
813
814
815 //=======================================================================
816 //function : ChangeStorageFormat
817 //purpose  : 
818 //=======================================================================
819
820 void TDocStd_Document::ChangeStorageFormat (const TCollection_ExtendedString& newStorageFormat) 
821 {
822   if (newStorageFormat != myStorageFormat) {
823     myStorageFormat = newStorageFormat;
824     myResourcesAreLoaded = Standard_False;
825     CDM_Document::LoadResources ();
826   }
827 }
828
829
830
831
832 //=======================================================================
833 //function : Recompute
834 //purpose  : 
835 //=======================================================================
836
837 void TDocStd_Document::Recompute ()
838 {
839   if (IsValid()) return;
840   // find the top function and execute it
841   //  Handle(TDesign_Function) F;
842   //  if (Main().FindAttribute(TDesign_Function::GetID(),F)) {
843   // TFunction_Solver slv;
844   // slv.SetTouched(GetModified());
845   // slv.ExecuteFrom(F);
846   PurgeModified();
847 }
848
849 //=======================================================================
850 //function : AppendDeltaToTheFirst
851 //purpose  : Appends delta to the first delta in the myUndoFILO
852 //=======================================================================
853
854 void TDocStd_Document::AppendDeltaToTheFirst
855   (const Handle(TDocStd_CompoundDelta)& theDelta1,
856    const Handle(TDF_Delta)& theDelta2)
857 {
858   if(theDelta2->IsEmpty()) return;
859   TDocStd_LabelIDMapDataMap aMap; 
860     
861   TDF_ListIteratorOfAttributeDeltaList aDeltasIterator1
862     (theDelta1->AttributeDeltas());
863   for(; aDeltasIterator1.More(); aDeltasIterator1.Next()) {   
864     TDF_Label aLabel = aDeltasIterator1.Value()->Label();
865     if(!aMap.IsBound(aLabel)) {
866       TDF_IDMap aTmpIDMap;
867       aMap.Bind(aLabel, aTmpIDMap);
868     }
869     Standard_GUID anID = aDeltasIterator1.Value()->ID();
870     TDF_IDMap& anIDMap = aMap.ChangeFind(aLabel);
871     anIDMap.Add(anID);
872   }
873   
874   theDelta1->Validity(theDelta1->BeginTime(), theDelta2->EndTime());
875   TDF_ListIteratorOfAttributeDeltaList aDeltasIterator2
876     (theDelta2->AttributeDeltas());
877   for(; aDeltasIterator2.More(); aDeltasIterator2.Next()) {   
878     TDF_Label aLabel = aDeltasIterator2.Value()->Label();
879     Standard_GUID anID = aDeltasIterator2.Value()->ID();
880     if(aMap.IsBound(aLabel)) {
881       const TDF_IDMap& anIDMap = aMap.Find(aLabel);
882       if(anIDMap.Contains(anID)) continue;
883     }
884     theDelta1->AddAttributeDelta(aDeltasIterator2.Value());
885   }
886 }
887
888 //=======================================================================
889 //function : RemoveFirstUndo
890 //purpose  : 
891 //=======================================================================
892 void TDocStd_Document::RemoveFirstUndo() {
893   if (myUndos.IsEmpty()) return;
894   myUndos.RemoveFirst();
895 }
896
897 //=======================================================================
898 //function : BeforeClose
899 //purpose  : 
900 //=======================================================================
901 void TDocStd_Document::BeforeClose() 
902 {
903   SetModificationMode(Standard_False);
904   AbortTransaction();
905   if(myIsNestedTransactionMode)
906          myUndoFILO.Clear();
907   ClearUndos();
908 }