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