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