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