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