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