0031313: Foundation Classes - Dump improvement for classes
[occt.git] / src / TDataStd / TDataStd_TreeNode.cxx
1 // Created on: 1999-06-10
2 // Created by: Vladislav ROMASHKO
3 // Copyright (c) 1999-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <TDataStd_TreeNode.hxx>
18
19 #include <TDF_Label.hxx>
20 #include <TDF_DataSet.hxx>
21 #include <TDF_DeltaOnAddition.hxx>
22 #include <TDF_DeltaOnRemoval.hxx>
23 #include <TDF_RelocationTable.hxx>
24 #include <TDF_Tool.hxx>
25 #include <Standard_DomainError.hxx>
26 #include <Standard_Dump.hxx>
27
28 IMPLEMENT_STANDARD_RTTIEXT(TDataStd_TreeNode,TDF_Attribute)
29
30 //=======================================================================
31 //function : Find
32 //purpose  : 
33 //=======================================================================
34
35 Standard_Boolean TDataStd_TreeNode::Find(const TDF_Label& L,
36                                          Handle(TDataStd_TreeNode)& T)
37 {
38   return L.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(), T);
39 }
40
41 //=======================================================================
42 //TreeNode : GetDefaultTreeID
43 //purpose  : Static method to get the default ID of a TreeNode
44 //=======================================================================
45
46 const Standard_GUID&  TDataStd_TreeNode::GetDefaultTreeID() 
47 {  
48   static Standard_GUID TDataStd_TreeNodeID ("2a96b621-ec8b-11d0-bee7-080009dc3333");
49   return TDataStd_TreeNodeID; 
50 }
51
52 //=======================================================================
53 //TreeNode : Set
54 //purpose  : Finds or creates a TreeNode attribute with default ID
55 //=======================================================================
56
57 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Set(const TDF_Label& L)
58 {
59   Handle(TDataStd_TreeNode) TN;
60   if (!L.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(),TN)) {
61     TN = new TDataStd_TreeNode();
62     TN->SetTreeID(TDataStd_TreeNode::GetDefaultTreeID());
63     L.AddAttribute(TN);
64   }
65   return TN;
66 }
67
68 //=======================================================================
69 //function : Set
70 //purpose  : Finds or creates a TreeNode  attribute with explicit ID
71 //         : a driver for it
72 //=======================================================================
73
74 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Set (const TDF_Label& L, 
75                                                   const Standard_GUID& explicitID)
76 {
77   Handle(TDataStd_TreeNode) TN;
78   if (!L.FindAttribute(explicitID,TN)) {
79     TN = new TDataStd_TreeNode ();    
80     TN->SetTreeID(explicitID);
81     L.AddAttribute(TN);
82   }
83   return TN;
84 }
85
86 //=======================================================================
87 //TreeNode : ID
88 //purpose  : Returns GUID of the TreeNode
89 //=======================================================================
90
91 const Standard_GUID& TDataStd_TreeNode::ID() const
92 {
93   return myTreeID; 
94 }
95
96 //=======================================================================
97 //TreeNode : TDataStd_TreeNode
98 //purpose  : Constructor
99 //=======================================================================
100
101 TDataStd_TreeNode::TDataStd_TreeNode () :
102   myFather(NULL),  myPrevious(NULL), myNext(NULL), myFirst(NULL), myLast(NULL)
103 {}  
104
105
106 //=======================================================================
107 //function : Append
108 //purpose  : Add <TN> as last child of me
109 //=======================================================================
110
111 Standard_Boolean TDataStd_TreeNode::Append (const Handle(TDataStd_TreeNode)& TN)
112 {  
113   if (!(TN->ID() == myTreeID) )
114     throw Standard_DomainError("TDataStd_TreeNode::Append : uncompatible GUID");
115
116   Handle(TDataStd_TreeNode) bid;
117   TN->SetNext(bid); // Deconnects from next.
118
119   // Find the last
120   if (!HasFirst()) {
121     SetFirst(TN);
122     TN->SetPrevious(bid); // Deconnects from previous.
123   }
124   else 
125   {
126     Handle(TDataStd_TreeNode) L = Last();
127     L->SetNext(TN);
128     TN->SetPrevious(L);
129   }
130   // Set Father
131   TN->SetFather(this);
132   myLast=TN.operator->();
133   return !TN.IsNull();
134 }
135
136 //=======================================================================
137 //function : Prepend
138 //purpose  : Add <TN> as first child of me
139 //=======================================================================
140
141 Standard_Boolean TDataStd_TreeNode::Prepend (const Handle(TDataStd_TreeNode)& TN)
142 {  
143   if (!(TN->ID() == myTreeID) ) 
144     throw Standard_DomainError("TDataStd_TreeNode::Prepend : uncompatible GUID");
145
146   Handle(TDataStd_TreeNode) bid;
147   TN->SetPrevious(bid);
148   if (HasFirst()) {
149     TN->SetNext(First());
150     First()->SetPrevious(TN);
151   }
152   else {
153     TN->SetNext(bid);
154     SetLast(TN);
155   }
156   TN->SetFather(this);
157   SetFirst(TN);
158   return !TN.IsNull();
159 }
160
161 //=======================================================================
162 //function : InsertBefore
163 //purpose  : Inserts the TreeNode  <TN> before me
164 //=======================================================================
165
166 Standard_Boolean TDataStd_TreeNode::InsertBefore (const Handle(TDataStd_TreeNode)& TN)
167 {
168   if (!(TN->ID() == myTreeID) ) 
169     throw Standard_DomainError("TDataStd_TreeNode::InsertBefore : uncompatible GUID");
170
171   TN->SetFather(Father());
172   TN->SetPrevious(Previous());
173   TN->SetNext(this);
174   
175   if (!HasPrevious())
176     Father()->SetFirst(TN);
177   else
178     Previous()->SetNext(TN);
179   
180   SetPrevious(TN);
181   return !TN.IsNull();
182 }
183
184 //=======================================================================
185 //function : InsertAfter
186 //purpose  : Inserts the TreeNode  <TN> after me
187 //=======================================================================
188
189 Standard_Boolean TDataStd_TreeNode::InsertAfter (const Handle(TDataStd_TreeNode)& TN)
190 {
191   if (!(TN->ID() == myTreeID) ) 
192     throw Standard_DomainError("TDataStd_TreeNode::InsertAfter : uncompatible GUID");
193   
194   if (HasFather() && !HasNext())
195     Father()->SetLast(TN);
196
197   TN->SetFather(Father());
198   TN->SetPrevious(this);
199   TN->SetNext(Next());
200   
201   if (HasNext()) 
202     Next()->SetPrevious(TN);
203
204   SetNext(TN);
205   return !TN.IsNull();
206 }
207
208 //=======================================================================
209 //function : Remove
210 //purpose  : Removees the function from the function tree
211 //=======================================================================
212
213 Standard_Boolean TDataStd_TreeNode::Remove ()
214 {
215   if (IsRoot()) return Standard_True;
216
217   Handle(TDataStd_TreeNode) bid;
218   if (!HasPrevious())
219     Father()->SetFirst(Next());
220   else
221     Previous()->SetNext(Next());
222
223   if (HasNext()) {
224     if (HasPrevious()) Next()->SetPrevious(Previous());
225     else Next()->SetPrevious(bid);
226   }
227   else {
228     if (HasPrevious()) Previous()->SetNext(bid);
229   }
230
231   if (Father()->HasFirst()) {
232     if (this == Father()->First().operator->()) {
233       if (HasNext()) {
234             Father()->SetFirst(Next());
235       }
236       else Father()->SetFirst(bid);
237     }
238   }
239   
240   if(Father()->HasLast()) {
241     Father()->SetLast(bid);
242   }
243
244   SetFather(bid);
245   SetNext(bid);
246   SetPrevious(bid);
247   return Standard_True;
248 }
249
250
251 //=======================================================================
252 //function : Depth
253 //purpose  : 
254 //=======================================================================
255
256 Standard_Integer TDataStd_TreeNode::Depth () const
257 {  
258   Standard_Integer depth = 0;
259
260   TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
261   while (O->myFather != NULL)
262   {
263     depth++;
264     O = O->myFather;
265   }
266
267   return depth;
268 }
269
270 //=======================================================================
271 //function : NbChildren
272 //purpose  : Returns the number of child nodes.
273 //           If <allLevels> is true, the method counts children of all levels
274 //           (children of children ...)
275 //=======================================================================
276 Standard_Integer TDataStd_TreeNode::NbChildren(const Standard_Boolean allLevels) const
277 {  
278     Standard_Integer nb = 0;
279     TDataStd_TreeNode* C = myFirst;
280     while (C != NULL)
281     {
282         if (allLevels && 
283             C->myFirst != NULL)
284         {
285             nb += C->NbChildren(allLevels);
286         }
287         nb++;
288         C = C->myNext;
289     }
290     return nb;
291 }
292  
293 //=======================================================================
294 //function : SetTreeID
295 //purpose  : Finds or creates a TreeNode  attribute with explicit ID
296 //         : a driver for it
297 //=======================================================================
298
299 void TDataStd_TreeNode::SetTreeID (const Standard_GUID& explicitID)
300 {
301   myTreeID = explicitID;
302 }
303
304
305 //=======================================================================
306 //function : IsAscendant
307 //purpose  : 
308 //=======================================================================
309
310 Standard_Boolean TDataStd_TreeNode::IsAscendant (const Handle(TDataStd_TreeNode)& ofTN) const
311 {
312   return ofTN->IsDescendant(this);
313 }
314
315
316 //=======================================================================
317 //function : IsDescendant
318 //purpose  : 
319 //=======================================================================
320
321 Standard_Boolean TDataStd_TreeNode::IsDescendant (const Handle(TDataStd_TreeNode)& ofTN) const
322 {
323   TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
324   while (O->myFather != NULL)
325   {
326     if (O->myFather == ofTN)
327       return Standard_True;
328     O = O->myFather;
329   }
330   return Standard_False;
331 }
332
333 //=======================================================================
334 //function : IsFather
335 //purpose  : 
336 //=======================================================================
337
338 Standard_Boolean TDataStd_TreeNode::IsFather (const Handle(TDataStd_TreeNode)& ofTN) const
339 {
340   return (ofTN->Father() == this);
341 }
342
343
344 //=======================================================================
345 //function : IsChild
346 //purpose  : 
347 //=======================================================================
348
349 Standard_Boolean TDataStd_TreeNode::IsChild (const Handle(TDataStd_TreeNode)& ofTN) const
350 {
351   return (myFather == ofTN.operator->());
352 }
353
354
355 //=======================================================================
356 //TreeNode : Father
357 //purpose  : Returns the Father of the TreeNode
358 //=======================================================================
359
360 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Father() const
361 {
362   Handle(TDataStd_TreeNode) O = myFather;
363   return O;
364 }
365
366 //=======================================================================
367 //TreeNode : IsRoot
368 //purpose  : Returns Standard_True if the TreeNode is not attached to a
369 //           TreeNode tree or hasn't an Father.
370 //=======================================================================
371
372 Standard_Boolean TDataStd_TreeNode::IsRoot() const
373 {
374   if (myFather    == NULL && 
375       myPrevious == NULL &&
376       myNext     == NULL)
377     return Standard_True;
378   return Standard_False;
379 }
380
381 //=======================================================================
382 //TreeNode : Root
383 //purpose  : Returns the TreeNode which has no Father
384 //=======================================================================
385
386 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Root() const
387 {
388   TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
389   while (O->myFather != NULL)
390   {
391     O = O->myFather;
392   }
393   return O;
394 }
395
396 //=======================================================================
397 //TreeNode : Next
398 //purpose  : Returns next (in the TreeNode tree) TreeNode
399 //=======================================================================
400
401 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Next() const
402 {
403   Handle(TDataStd_TreeNode) O = myNext;  
404   return O;
405 }
406
407 //=======================================================================
408 //TreeNode : Previous
409 //purpose  : Returns previous (in the TreeNode tree) TreeNode
410 //=======================================================================
411
412 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Previous() const
413 {
414   Handle(TDataStd_TreeNode) O = myPrevious;
415   return O;
416 }
417
418 //=======================================================================
419 //TreeNode : First 
420 //purpose  : Returns first child
421 //=======================================================================
422
423 Handle(TDataStd_TreeNode) TDataStd_TreeNode::First () const
424 {
425   Handle(TDataStd_TreeNode) O = myFirst;
426   return O;
427 }
428
429 //=======================================================================
430 //TreeNode : Last 
431 //purpose  : Returns last child
432 //           Optimize an Append operation if it is called in a circle
433 //=======================================================================
434
435 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Last ()
436 {
437   if(myLast && !myLast->IsChild(this))
438     myLast=NULL;
439
440   if(myLast == NULL) 
441     return FindLast();
442   
443   return myLast;
444 }
445
446 //=======================================================================
447 //TreeNode : FindLast 
448 //purpose  : Returns last child
449 //           Optimizes an Append operation if it is called in a circle
450 //=======================================================================
451 Handle(TDataStd_TreeNode) TDataStd_TreeNode::FindLast ()
452 {
453         if (myFirst == NULL)
454                 return myFirst;
455         TDataStd_TreeNode* L = myFirst;
456         while (L->myNext != NULL)
457         {
458                 L = L->myNext;
459         }
460         return L;
461 }
462
463 //=======================================================================
464 //TreeNode : SetFather
465 //purpose  : Sets the TreeNode F as Father of me
466 //=======================================================================
467
468 void TDataStd_TreeNode::SetFather(const Handle(TDataStd_TreeNode)& F)
469 {
470   Backup();
471   if (F.IsNull()) myFather = NULL;
472   else            myFather = F.operator->();
473   myLast=NULL;
474 }
475
476 //=======================================================================
477 //TreeNode : SetNext
478 //purpose  : Sets the TreeNode F next to me 
479 //=======================================================================
480
481 void TDataStd_TreeNode::SetNext(const Handle(TDataStd_TreeNode)& F)
482 {
483   Backup();
484   if (F.IsNull()) myNext = NULL;
485   else            myNext = F.operator->();
486   myLast=NULL;
487 }
488
489
490 //=======================================================================
491 //TreeNode : SetPrevious
492 //purpose  : Sets the TreeNode F previous to me
493 //=======================================================================
494
495 void TDataStd_TreeNode::SetPrevious(const Handle(TDataStd_TreeNode)& F)
496 {
497   Backup();
498   if (F.IsNull()) myPrevious = NULL;
499   else            myPrevious = F.operator->();
500   myLast=NULL;
501 }
502
503 //=======================================================================
504 //TreeNode : SetFirst
505 //purpose  : Sets the TreeNode F as first in the TreeNode tree
506 //=======================================================================
507
508 void TDataStd_TreeNode::SetFirst(const Handle(TDataStd_TreeNode)& F)
509 {
510   Backup();
511   if (F.IsNull()) myFirst = NULL;
512   else            myFirst = F.operator->();
513   myLast=NULL;
514 }
515
516 //=======================================================================
517 //TreeNode : SetLast
518 //purpose  : Sets the TreeNode F as last in the TreeNode tree
519 //=======================================================================
520
521 void TDataStd_TreeNode::SetLast(const Handle(TDataStd_TreeNode)& F)
522 {
523   Backup();
524   if (F.IsNull()) myLast = NULL;
525   else            myLast = F.operator->();
526 }
527
528 //=======================================================================
529 //TreeNode : AfterAddition
530 //purpose  : Connects the TreeNode to the tree.
531 //           Backuped attribute must stay disconnected
532 //=======================================================================
533
534 void TDataStd_TreeNode::AfterAddition() {
535   if (!IsBackuped()) {
536     if (myPrevious)
537       myPrevious->SetNext(this);
538     else if (myFather)
539       myFather->SetFirst(this);
540     if (myNext)
541       myNext->SetPrevious(this);
542   }
543 }
544
545 //=======================================================================
546 //TreeNode : BeforeForget
547 //purpose  : Disconnect the TreeNode from the tree.
548 //           Backuped attribute is normaly not concerned by such an operation
549 //=======================================================================
550
551 void TDataStd_TreeNode::BeforeForget() {
552   if (!IsBackuped()) {
553     Remove();
554     while (HasFirst()) First()->Remove();
555   }
556 }
557
558 //=======================================================================
559 //TreeNode : AfterResume
560 //purpose  : Connects the TreeNode to the tree
561 //=======================================================================
562
563 void TDataStd_TreeNode::AfterResume() {
564   AfterAddition();
565 }
566
567 //=======================================================================
568 //TreeNode : BeforeUndo
569 //purpose  : Disconnect the TreeNode from the tree.
570 //=======================================================================
571
572 Standard_Boolean TDataStd_TreeNode::BeforeUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
573                                                 const Standard_Boolean /*forceIt*/)
574 {
575   if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnAddition))) BeforeForget(); // Disconnect.
576   return Standard_True;
577 }
578
579 //=======================================================================
580 //TreeNode : AfterUndo
581 //purpose  : Connect the TreeNode from the tree.
582 //=======================================================================
583
584 Standard_Boolean TDataStd_TreeNode::AfterUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
585                                               const Standard_Boolean /*forceIt*/)
586 {
587   if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnRemoval))) AfterAddition(); // Reconnect.
588   return Standard_True;
589 }
590
591 //=======================================================================
592 //TreeNode : Restore
593 //purpose  : 
594 //=======================================================================
595
596 void TDataStd_TreeNode::Restore(const Handle(TDF_Attribute)& other) {
597   Handle(TDataStd_TreeNode) F =  Handle(TDataStd_TreeNode)::DownCast(other);
598   myFather     = F->myFather;
599   myPrevious   = F->myPrevious;
600   myNext       = F->myNext;
601   myFirst      = F->myFirst; 
602   myTreeID     = F->myTreeID;
603   myLast       = NULL;
604 }
605
606 //=======================================================================
607 //TreeNode : Paste
608 //purpose  : Method for Copy mechanism
609 //=======================================================================
610
611 void TDataStd_TreeNode::Paste(const Handle(TDF_Attribute)& into,
612                               const Handle(TDF_RelocationTable)& RT) const
613 {
614   Handle(TDataStd_TreeNode) intof = Handle(TDataStd_TreeNode)::DownCast(into);
615   Handle(TDataStd_TreeNode) func;
616   if (!RT->HasRelocation(myFather, func) && RT->AfterRelocate()) {
617     func.Nullify();
618   }
619   intof->SetFather(func);
620   if (!RT->HasRelocation(myNext, func) && RT->AfterRelocate()) {
621     func.Nullify();
622   }
623   intof->SetNext(func);
624   if (!RT->HasRelocation(myPrevious, func) && RT->AfterRelocate()) {
625     func.Nullify();
626   }
627   intof->SetPrevious(func);
628   if (!RT->HasRelocation(myFirst, func) && RT->AfterRelocate()) {
629     func.Nullify();
630   }
631
632   intof->SetFirst(func);
633   intof->SetTreeID(myTreeID);
634 }
635
636 //=======================================================================
637 //TreeNode : NewEmpty
638 //purpose  : Returns new empty TreeNode attribute
639 //=======================================================================
640
641 Handle(TDF_Attribute) TDataStd_TreeNode::NewEmpty() const
642 {
643   Handle(TDataStd_TreeNode) T = new TDataStd_TreeNode();
644   T->SetTreeID(myTreeID);
645   return T;
646 }
647
648 //=======================================================================
649 //TreeNode : References
650 //purpose  : Collects the references
651 //=======================================================================
652
653 void TDataStd_TreeNode::References(const Handle(TDF_DataSet)& aDataSet) const
654 {
655   TDataStd_TreeNode* fct = myFirst;
656   while (fct != NULL) {
657     aDataSet->AddAttribute(fct);
658     fct = fct->myNext;
659   }
660 }
661
662 //=======================================================================
663 //TreeNode : Dump
664 //purpose  : Dump of the TreeNode
665 //=======================================================================
666
667 Standard_OStream& TDataStd_TreeNode::Dump (Standard_OStream& anOS) const
668 {
669   TDF_Attribute::Dump (anOS);
670   if (myFather) {
671     anOS<<"  Father=";
672     if (!myFather->Label().IsNull()) myFather->Label().EntryDump(anOS);
673   }
674   if (myPrevious) {
675     anOS<<"  Previous=";
676     if (!myPrevious->Label().IsNull()) myPrevious->Label().EntryDump(anOS);
677   }
678   if (myNext) {
679     anOS<<"  Next=";
680     if (!myNext->Label().IsNull()) myNext->Label().EntryDump(anOS);
681   }
682   if (myFirst) {
683     anOS<<"  First=";
684     if (!myFirst->Label().IsNull()) myFirst->Label().EntryDump(anOS);
685   }
686   if (myLast) {
687     anOS<<"  Last=";
688     if (!myLast->Label().IsNull()) myLast->Label().EntryDump(anOS);
689   }
690   anOS<<std::endl;
691   return anOS;
692 }
693
694 //=======================================================================
695 //function : DumpJson
696 //purpose  : 
697 //=======================================================================
698 void TDataStd_TreeNode::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
699 {
700   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
701   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, TDF_Attribute)
702
703   if (myFather)
704   {
705     TCollection_AsciiString aFather;
706     TDF_Tool::Entry (myFather->Label(), aFather);
707     OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aFather)
708   }
709   if (myPrevious)
710   {
711     TCollection_AsciiString aPrevious;
712     TDF_Tool::Entry (myPrevious->Label(), aPrevious);
713     OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aPrevious)
714   }
715   if (myNext)
716   {
717     TCollection_AsciiString aNext;
718     TDF_Tool::Entry (myNext->Label(), aNext);
719     OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aNext)
720   }
721   if (myFirst)
722   {
723     TCollection_AsciiString aFirst;
724     TDF_Tool::Entry (myFirst->Label(), aFirst);
725     OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aFirst)
726   }
727   if (myLast)
728   {
729     TCollection_AsciiString aLast;
730     TDF_Tool::Entry (myLast->Label(), aLast);
731     OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aLast)
732   }
733
734   OCCT_DUMP_FIELD_VALUE_GUID (theOStream, myTreeID)
735 }