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