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