0023002: empty delete operator in TDF_LabelNode
[occt.git] / src / TDF / TDF_Label.cxx
CommitLineData
b311480e 1// Created by: DAUTRY Philippe
2// Copyright (c) 1997-1999 Matra Datavision
3// Copyright (c) 1999-2012 OPEN CASCADE SAS
4//
5// The content of this file is subject to the Open CASCADE Technology Public
6// License Version 6.5 (the "License"). You may not use the content of this file
7// except in compliance with the License. Please obtain a copy of the License
8// at http://www.opencascade.org and read it completely before using this file.
9//
10// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12//
13// The Original Code and all software distributed under the License is
14// distributed on an "AS IS" basis, without warranty of any kind, and the
15// Initial Developer hereby disclaims all such warranties, including without
16// limitation, any warranties of merchantability, fitness for a particular
17// purpose or non-infringement. Please see the License for the specific terms
18// and conditions governing the rights and limitations under the License.
19
7fd59977 20#include <TDF_Label.ixx>
21
22#include <TDF_Attribute.hxx>
23#include <TDF_AttributeIterator.hxx>
24#include <TDF_ChildIterator.hxx>
25#include <TDF_Data.hxx>
26#include <TDF_LabelNode.hxx>
27#include <TDF_LabelNodePtr.hxx>
28#include <TDF_Tool.hxx>
29#include <TCollection_AsciiString.hxx>
30#include <Standard_ImmutableObject.hxx>
31
32
33//=======================================================================
34//function : TDF_Label
35//purpose :
36//=======================================================================
37
38TDF_Label::TDF_Label()
39:myLabelNode(NULL)
40{}
41
42//=======================================================================
43//function : TDF_Label
44//purpose :
45//=======================================================================
46
47TDF_Label::TDF_Label(const TDF_LabelNodePtr& aNode)
48:myLabelNode(aNode)
49{}
50
51// Attribute methods ++++++++++++++++++++++++++++++++++++++++++++++++++++
52
53
54//=======================================================================
55//function : Imported
56//purpose : Sets imported and all its descendants.
57//=======================================================================
58
59void TDF_Label::Imported(const Standard_Boolean aStatus) const
60{
61 if (IsNull()) Standard_NullObject::Raise("A null Label has no status.");
62 if (myLabelNode->IsImported() != aStatus) {
63 myLabelNode->Imported(aStatus);
64 for (TDF_ChildIterator itr(*this, Standard_True);
65 itr.More(); itr.Next())
66 itr.Value().myLabelNode->Imported(aStatus);
67 }
68}
69
70
71//=======================================================================
72//function : FindAttribute
73//purpose : Finds an attributes according to an ID.
74//=======================================================================
75
76Standard_Boolean TDF_Label::FindAttribute
77(const Standard_GUID& anID,
78 Handle(TDF_Attribute)& anAttribute) const
79{
80 if (IsNull()) Standard_NullObject::Raise("A null Label has no attribute.");
81 TDF_AttributeIterator itr (myLabelNode); // Without removed attributes.
82 for ( ; itr.More(); itr.Next()) {
83 if (itr.Value()->ID() == anID) {
84 anAttribute = itr.Value();
85 return Standard_True;
86 }
87 }
88 return Standard_False;
89}
90
91
92//=======================================================================
93//function : FindAttribute
94//purpose : Finds an attributes according to an ID and a Transaction.
95//=======================================================================
96
97Standard_Boolean TDF_Label::FindAttribute
98(const Standard_GUID& anID,
99 const Standard_Integer aTransaction,
100 Handle(TDF_Attribute)& anAttribute) const
101{
102 Handle(TDF_Attribute) locAtt;
103 if (FindAttribute(anID, locAtt)) {
104 while ((!locAtt.IsNull()) && (locAtt->myTransaction > aTransaction))
105 locAtt = locAtt->myBackup;
106 if (!locAtt.IsNull()) {
107 anAttribute = locAtt;
108 return Standard_True;
109 }
110 }
111 return Standard_False;
112}
113
114// Label comfort methods ++++++++++++++++++++++++++++++++++++++++++++++++
115
116//=======================================================================
117//function : Depth
118//purpose : Returns the depth of the label in the tree.
119// Root has depth 0. So the depth is the number of fathers.
120//=======================================================================
121
122Standard_Integer TDF_Label::Depth() const
123{
124 if (IsNull()) Standard_NullObject::Raise("A null Label has no depth.");
125 return myLabelNode->Depth();
126}
127
128
129//=======================================================================
130//function : IsDescendant
131//purpose : Returns True if <me> is a descendant of <aLabel>.
132//=======================================================================
133
134Standard_Boolean TDF_Label::IsDescendant(const TDF_Label& aLabel) const
135{
136 // Cet algorithme remonte jusqu'a la racine. On peut s'arreter
137 // si la profondeur atteinte est inferieure a celle de <aLabel>.
138
139 const TDF_LabelNode* lp1 = aLabel.myLabelNode;
140 TDF_LabelNode* lp2 = myLabelNode;
141#ifdef DEB
142 if ((lp1 == NULL) || (lp2 == NULL))
143 Standard_NullObject::Raise("A null label has no ancestor nor descendant.");
144#endif
145 if ((lp1 != NULL) && (lp2 != NULL)) {
146 const Standard_Integer d1 = lp1->Depth();
147 Standard_Integer d2 = lp2->Depth();
148 // Tester (d1 > d2) optimise la recherche ET dispense du test (lp2 != NULL)
149 while ((d2 > d1) && (lp2 != lp1)) {
150 lp2 = lp2->Father();
151 d2 = lp2->Depth();
152 }
153 return (lp1 == lp2);
154 }
155 return Standard_False;
156}
157
158
159//=======================================================================
160//function : Root
161//purpose :
162//=======================================================================
163
164const TDF_Label TDF_Label::Root() const
165{
166 if (IsNull()) Standard_NullObject::Raise("A null Label has no root.");
167 return myLabelNode->RootNode();
168}
169
170
171//=======================================================================
172//function : NbChildren
173//purpose : Returns the number of children.
174//=======================================================================
175
176Standard_Integer TDF_Label::NbChildren() const
177{
178 if (IsNull()) Standard_NullObject::Raise("A null Label has no children.");
179 Standard_Integer n = 0;
180 if (myLabelNode->FirstChild() != NULL)
181 for (TDF_ChildIterator itr(*this); itr.More(); itr.Next()) ++n;
182 return n;
183}
184
185
186//=======================================================================
187//function : FindChild
188//purpose :
189//=======================================================================
190
191TDF_Label TDF_Label::FindChild
192(const Standard_Integer aTag,
193 const Standard_Boolean create) const
194{
195 if (IsNull())
196 Standard_NullObject::Raise("A null Label has no child.");
197 if (create && ((Depth()+1) & TDF_LabelNodeFlagsMsk))
198 Standard_OutOfRange::Raise("Depth value out of range");
199
200 return FindOrAddChild(aTag,create);
201}
202
203// Attribute comfort methods ++++++++++++++++++++++++++++++++++++++++++++
204
205//=======================================================================
206//function : IsA
207//purpose : Returns true if owns an attribute with <anID> as ID.
208//=======================================================================
209
210// Standard_Boolean TDF_Label::IsA(const Standard_GUID& anID) const
211// {
212// Handle(TDF_Attribute) att;
213// return FindAttribute(anID,att);
214// }
215
216//=======================================================================
217//function : IsAttribute
218//purpose : Returns true if owns an attribute with <anID> as ID.
219//=======================================================================
220
221Standard_Boolean TDF_Label::IsAttribute(const Standard_GUID& anID) const
222{
223 Handle(TDF_Attribute) att;
224 return FindAttribute(anID,att);
225}
226
227
228//=======================================================================
229//function : HasAttribute
230//purpose : Returns true if the label has at least one unremoved attribute.
231//=======================================================================
232
233Standard_Boolean TDF_Label::HasAttribute() const
234{
235 if (IsNull()) Standard_NullObject::Raise("A null Label has no attribute.");
236
237 if (!myLabelNode->FirstAttribute().IsNull()) {
238 TDF_AttributeIterator itr (myLabelNode); // Without removed attributes.
239 return itr.More();
240 }
241 return Standard_False;
242}
243
244
245//=======================================================================
246//function : NbAttributes
247//purpose : Returns the number of attributes.
248//=======================================================================
249
250Standard_Integer TDF_Label::NbAttributes() const
251{
252 if (IsNull()) Standard_NullObject::Raise("A null Label has no attribute.");
253 Standard_Integer n = 0;
254 if (!myLabelNode->FirstAttribute().IsNull())
255 for (TDF_AttributeIterator itr (myLabelNode); itr.More(); itr.Next()) ++n;
256 return n;
257}
258
259
260// Miscelleaneous +++++++++++++++++++++++++++++++++++++++++++++++++++++++
261
262
263//=======================================================================
264//function : Transaction
265//purpose :
266//=======================================================================
267
268Standard_Integer TDF_Label::Transaction() const
269{
270 if (IsNull()) Standard_NullObject::Raise("A null Label has no transaction.");
271 return myLabelNode->Data()->Transaction();
272}
273
274
275//=======================================================================
276//function : Dump
277//purpose : This method is equivalent to operator <<
278//=======================================================================
279
280Standard_OStream& TDF_Label::Dump
281(Standard_OStream& anOS) const
282{
283 TDF_IDFilter f; TDF_AttributeIndexedMap m;
284 TDF_Label::InternalDump(anOS,f,m,Standard_False);
285 return anOS;
286}
287
288
289//=======================================================================
290//function : ExtendedDump
291//purpose :
292//=======================================================================
293
294void TDF_Label::ExtendedDump
295(Standard_OStream& anOS,
296 const TDF_IDFilter& aFilter,
297 TDF_AttributeIndexedMap& aMap) const
298{ TDF_Label::InternalDump(anOS,aFilter,aMap,Standard_True); }
299
300
301//=======================================================================
302//function : EntryDump
303//purpose :
304//=======================================================================
305
306void TDF_Label::EntryDump(Standard_OStream& anOS) const
307{
308 if (IsNull ()) {
309 anOS<<"This label is null.";
310 }
311 else {
312 TCollection_AsciiString entry;
313 TDF_Tool::Entry(*this,entry);
314 anOS<<entry;
315 }
316}
317
7fd59977 318//=======================================================================
319//function : FindOrAddChild
320//purpose : Finds or adds a label child having <aTag> as tag.
321//=======================================================================
322
323TDF_LabelNode* TDF_Label::FindOrAddChild
324(const Standard_Integer aTag,
325 const Standard_Boolean create) const
326{
327 TDF_LabelNode* currentLnp = myLabelNode->FirstChild();
328 TDF_LabelNode* lastLnp = NULL;
329 TDF_LabelNode* lastFoundLnp = myLabelNode->myLastFoundChild; //jfa 10.01.2003
330 TDF_LabelNode* childLabelNode = NULL;
331
332 // Finds the right place.
333
334 //jfa 10.01.2003
335 // 1. Check, if we access to a child, which is after last touched upon
336 if (lastFoundLnp != NULL) {
337 if (lastFoundLnp->Tag() == aTag) {
338 return lastFoundLnp;
339 }
340 else if (lastFoundLnp->Tag() < aTag) {
341 lastLnp = lastFoundLnp;
342 currentLnp = lastFoundLnp->Brother();
343 }
344 }
345 //jfa 10.01.2003 end
346
347 // To facilitate many tools, label brethren are stored in increasing order.
348 while ((currentLnp != NULL) && (currentLnp->Tag() < aTag) ) {
349 lastLnp = currentLnp;
350 currentLnp = currentLnp->Brother();
351 }
352
353 if ( (currentLnp != NULL) && (currentLnp->Tag() == aTag) ) {
354 // The label exists.
355 childLabelNode = currentLnp;
356 }
357 else if (create) {
358 // Creates the label to be inserted always before currentLnp.
60d4560d 359 const TDF_HAllocator& anAllocator = myLabelNode->Data()->LabelNodeAllocator();
360 childLabelNode = new (anAllocator) TDF_LabelNode (aTag, myLabelNode);
7fd59977 361 childLabelNode->myBrother = currentLnp; // May be NULL.
362 childLabelNode->Imported(IsImported());
363 //Inserts the label:
364 if (lastLnp == NULL) // ... at beginning.
365 myLabelNode->myFirstChild = childLabelNode;
366 else // ... somewhere.
367 lastLnp->myBrother = childLabelNode;
368 }
369
370 if (lastLnp) //agv 14.07.2010
371 myLabelNode->myLastFoundChild = lastLnp; //jfa 10.01.2003
372
373 return childLabelNode;
374}
375
7fd59977 376//=======================================================================
377//function : InternalDump
378//purpose : Private method.
379//=======================================================================
380
381void TDF_Label::InternalDump
382(Standard_OStream& anOS,
383 const TDF_IDFilter& aFilter,
384 TDF_AttributeIndexedMap& aMap,
385 const Standard_Boolean extended) const
386{
387 if (IsNull ()) {
388 anOS<<"This label is null.";
389 }
390 else {
391 TCollection_AsciiString entry; TDF_Tool::Entry(*this,entry);
392 anOS<<entry<<"\t";
393 if (IsImported()) anOS<<"IS "; else anOS<<"NOT"; anOS<<" imported; ";
394 if (MayBeModified()) anOS<<"MAYBE"; else anOS<<"NOT"; anOS<<" modified; ";
395 if (AttributesModified()) anOS<<"HAS attributes"; else anOS<<"NO attribute"; anOS<<" modified; ";
396 if (HasAttribute()) {
397 Standard_Integer nba = NbAttributes();
398 anOS<<"has "<<nba<<" attribute"; if (nba > 1) anOS<<"s"; anOS<<"."<<endl;
399 for (TDF_AttributeIterator itr(myLabelNode); itr.More(); itr.Next()) {
400 // CLE
401 // const Handle(TDF_Attribute)& att = itr.Value();
402 Handle(TDF_Attribute) att = itr.Value();
403 // ENDCLE
404 if (extended && aFilter.IsKept(att)) anOS<<"\t# "<<aMap.Add(att);
405 att->TDF_Attribute::Dump(anOS);
406 }
407 }
408 else {
409 anOS<<" has no attribute"<<endl;
410 }
411 }
412}
413
414Standard_Boolean TDF_Label::HasLowerNode(const TDF_Label& aLabel) const
415{ return (myLabelNode < aLabel.myLabelNode); }
416
417Standard_Boolean TDF_Label::HasGreaterNode(const TDF_Label& aLabel) const
418{ return (myLabelNode > aLabel.myLabelNode); }
419
420// from insertor ////////////////////////////////////////////////////////
421
422//=======================================================================
423//function : Add
424//purpose :
425//=======================================================================
426
427// void TDF_Label::Add(const Handle(TDF_Attribute)& anAttribute) const
428// { AddToNode(myLabelNode,anAttribute); }
429
430//=======================================================================
431//function : AddAttribute
432//purpose :
433//=======================================================================
434
435void TDF_Label::AddAttribute (const Handle(TDF_Attribute)& anAttribute) const
436{ AddToNode(myLabelNode,anAttribute); }
437
438
439//=======================================================================
440//function : Forget
441//purpose :
442//=======================================================================
443
444// void TDF_Label::Forget(const Handle(TDF_Attribute)& anAttribute) const
445// { ForgetFromNode(myLabelNode,anAttribute); }
446
447
448//=======================================================================
449//function : ForgetAttribute
450//purpose :
451//=======================================================================
452
453void TDF_Label::ForgetAttribute (const Handle(TDF_Attribute)& anAttribute) const
454{ ForgetFromNode(myLabelNode,anAttribute); }
455
456
457//=======================================================================
458//function : Forget
459//purpose :
460//=======================================================================
461
462// Standard_Boolean TDF_Label::Forget (const Standard_GUID& anID) const
463// {
464// Handle(TDF_Attribute) anAttribute;
465// //if (Label().FindAttribute(anID,anAttribute)) {
466// if (FindAttribute(anID,anAttribute)) {
467// Forget(anAttribute);
468// return Standard_True;
469// }
470// return Standard_False;
471// }
472
473//=======================================================================
474//function : ForgetAttribute
475//purpose :
476//=======================================================================
477
478Standard_Boolean TDF_Label::ForgetAttribute (const Standard_GUID& anID) const
479{
480 Handle(TDF_Attribute) anAttribute;
481 //if (Label().FindAttribute(anID,anAttribute)) {
482 if (FindAttribute(anID,anAttribute)) {
483 ForgetAttribute (anAttribute);
484 return Standard_True;
485 }
486 return Standard_False;
487}
488
489
490//=======================================================================
491//function : ForgetAll
492//purpose :
493//=======================================================================
494
495// void TDF_Label::ForgetAll (const Standard_Boolean clearChildren) const
496// {
497// for (TDF_AttributeIterator itr1(myLabelNode); itr1.More(); itr1.Next())
498// ForgetFromNode(myLabelNode,itr1.Value());
499// if (clearChildren)
500// for (TDF_ChildIterator itr2(myLabelNode); itr2.More(); itr2.Next()) {
501// itr2.Value().ForgetAll(clearChildren);
502// }
503// }
504
505
506//=======================================================================
507//function : ForgetAllAttributes
508//purpose :
509//=======================================================================
510
511void TDF_Label::ForgetAllAttributes (const Standard_Boolean clearChildren) const
512{
513 TDF_AttributeIterator itr1 (myLabelNode);
514// AGV-OCC5031: iterator must be incremented before removal of the attribute
515 while (itr1.More()) {
516 const Handle(TDF_Attribute) anAttr = itr1.Value();
517 itr1.Next();
518 ForgetFromNode (myLabelNode, anAttr);
519 }
520// while (itr1.More()) {
521// ForgetFromNode(myLabelNode,itr1.Value());
522// itr1.Next();
523// }
524 if (clearChildren)
525 for (TDF_ChildIterator itr2(myLabelNode); itr2.More(); itr2.Next()) {
526 itr2.Value().ForgetAllAttributes (clearChildren);
527 }
528}
529
530
531//=======================================================================
532//function : Resume
533//purpose :
534//=======================================================================
535
536// void TDF_Label::Resume (const Handle(TDF_Attribute)& anAttribute) const
537// { ResumeToNode(myLabelNode,anAttribute); }
538
539//=======================================================================
540//function : ResumeAttribute
541//purpose :
542//=======================================================================
543
544void TDF_Label::ResumeAttribute (const Handle(TDF_Attribute)& anAttribute) const
545{ ResumeToNode(myLabelNode,anAttribute); }
546
547
548
549//=======================================================================
550//function : AddToNode
551//purpose : Private method used by Add
552//=======================================================================
553
554void TDF_Label::AddToNode (const TDF_LabelNodePtr& toNode,
555 const Handle(TDF_Attribute)& anAttribute) const
556{
557 // check that modification is allowed
558 if ( !toNode->Data()->IsModificationAllowed() ) {
559 TCollection_AsciiString aMess;
560 aMess = "Attribute \"";
561 aMess += anAttribute->DynamicType()->Name();
562 aMess += "\" is added to label outside transaction";
563 Standard_ImmutableObject::Raise(aMess.ToCString());
564 }
565
566 if (!anAttribute->Label().IsNull())
567 Standard_DomainError::Raise("Attribute to add is already attached to a label.");
568 Handle(TDF_Attribute) dummyAtt;
569 //if (Find(anAttribute->ID(),dummyAtt))
570 if (FindAttribute(anAttribute->ID(),dummyAtt))
571 Standard_DomainError::Raise("This label has already such an attribute.");
572
573 anAttribute->myTransaction = toNode->Data()->Transaction(); /// myData->Transaction();
574 anAttribute->mySavedTransaction = 0;
575 dummyAtt.Nullify();
576 toNode->AddAttribute(dummyAtt,anAttribute);
577 toNode->AttributesModified(anAttribute->myTransaction != 0);
578 //if (myData->NotUndoMode()) anAttribute->AfterAddition();
579 if (toNode->Data()->NotUndoMode()) anAttribute->AfterAddition();
580}
581
582
583//=======================================================================
584//function : ForgetFromNode
585//purpose : Private method used by Forget
586//=======================================================================
587
588void TDF_Label::ForgetFromNode (const TDF_LabelNodePtr& fromNode,
589 const Handle(TDF_Attribute)& anAttribute) const
590{
591 // check that modification is allowed
592 if ( !fromNode->Data()->IsModificationAllowed() ) {
593 TCollection_AsciiString aMess;
594 aMess = "Attribute \"";
595 aMess += anAttribute->DynamicType()->Name();
596 aMess += "\" is removed from label outside transaction";
597 Standard_ImmutableObject::Raise(aMess.ToCString());
598 }
599
600 if (fromNode != anAttribute->Label().myLabelNode)
601 Standard_DomainError::Raise
602 ("Attribute to forget not attached to my label.");
603
604 Standard_Integer curTrans = fromNode->Data()->Transaction();
605 if (!anAttribute->IsForgotten()) {
606 if ( (curTrans == 0) ||
607 ( (anAttribute->myTransaction == curTrans) &&
608 anAttribute->myBackup.IsNull())) {
609 // 1- No transaction is open;
610 // OR
611 // 2- The attribute has been created in the current transaction;
612 // ==> Complete disparition of the attribute.
613 Handle(TDF_Attribute) lastAtt;
614 for (TDF_AttributeIterator itr(fromNode, Standard_False);
615 itr.More();
616 itr.Next()) {
617 if (itr.Value() == anAttribute) {
618 //if (myData->NotUndoMode()) {
619 if (fromNode->Data()->NotUndoMode()) {
620 anAttribute->BeforeForget();
621 anAttribute->BeforeRemoval();
622 }
623 fromNode->RemoveAttribute(lastAtt,anAttribute);
624 anAttribute->Forget(fromNode->Data()->Transaction()); // vro
625 break;
626 }
627 lastAtt = itr.Value();
628 }
629 }
630 else {
631 // One case is here ignored:
632 // The attribute has been modified in the current transaction.
633 // (It has at least one backup.) We don't restore the previous
634 // version before forgetting. It may generated a strange behaviour
635 // in case of forgetting, commiting, aborting...
636 if (fromNode->Data()->NotUndoMode()) anAttribute->BeforeForget();
637 anAttribute->Forget(fromNode->Data()->Transaction());
638 }
639 }
640}
641
642//=======================================================================
643//function : ResumeToNode
644//purpose : Private method used by Resume
645//=======================================================================
646
647void TDF_Label::ResumeToNode (const TDF_LabelNodePtr& toNode,
648 const Handle(TDF_Attribute)& anAttribute) const
649{
650 if (anAttribute.IsNull())
651 Standard_NullObject::Raise("The attribute is a null handle.");
652 if (!anAttribute->Label().IsNull())
653 Standard_NullObject::Raise
654 ("Cannot resume an attribute already attached to a label.");
655 if (!anAttribute->IsForgotten())
656 Standard_DomainError::Raise
657 ("Cannot resume an unforgotten attribute.");
658
659 AddToNode(toNode, anAttribute); // vro
660 anAttribute->Resume();
661 if (toNode->Data()->NotUndoMode()) anAttribute->AfterResume();
662}
663
664//////////////////end from insertor ///////////////////////////////////////////////////