1 // Created by: DAUTRY Philippe
2 // Copyright (c) 1997-1999 Matra Datavision
3 // Copyright (c) 1999-2012 OPEN CASCADE SAS
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.
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.
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.
23 //Version Date Purpose
24 // 0.0 Feb 6 1997 Creation
28 #include <TDF_Label.ixx>
30 #include <TDF_Attribute.hxx>
31 #include <TDF_AttributeIterator.hxx>
32 #include <TDF_ChildIterator.hxx>
33 #include <TDF_Data.hxx>
34 #include <TDF_LabelNode.hxx>
35 #include <TDF_LabelNodePtr.hxx>
36 #include <TDF_Tool.hxx>
37 #include <TCollection_AsciiString.hxx>
38 #include <Standard_ImmutableObject.hxx>
41 //=======================================================================
42 //function : TDF_Label
44 //=======================================================================
46 TDF_Label::TDF_Label()
50 //=======================================================================
51 //function : TDF_Label
53 //=======================================================================
55 TDF_Label::TDF_Label(const TDF_LabelNodePtr& aNode)
59 // Attribute methods ++++++++++++++++++++++++++++++++++++++++++++++++++++
62 //=======================================================================
64 //purpose : Sets imported and all its descendants.
65 //=======================================================================
67 void TDF_Label::Imported(const Standard_Boolean aStatus) const
69 if (IsNull()) Standard_NullObject::Raise("A null Label has no status.");
70 if (myLabelNode->IsImported() != aStatus) {
71 myLabelNode->Imported(aStatus);
72 for (TDF_ChildIterator itr(*this, Standard_True);
73 itr.More(); itr.Next())
74 itr.Value().myLabelNode->Imported(aStatus);
79 //=======================================================================
80 //function : FindAttribute
81 //purpose : Finds an attributes according to an ID.
82 //=======================================================================
84 Standard_Boolean TDF_Label::FindAttribute
85 (const Standard_GUID& anID,
86 Handle(TDF_Attribute)& anAttribute) const
88 if (IsNull()) Standard_NullObject::Raise("A null Label has no attribute.");
89 TDF_AttributeIterator itr (myLabelNode); // Without removed attributes.
90 for ( ; itr.More(); itr.Next()) {
91 if (itr.Value()->ID() == anID) {
92 anAttribute = itr.Value();
96 return Standard_False;
100 //=======================================================================
101 //function : FindAttribute
102 //purpose : Finds an attributes according to an ID and a Transaction.
103 //=======================================================================
105 Standard_Boolean TDF_Label::FindAttribute
106 (const Standard_GUID& anID,
107 const Standard_Integer aTransaction,
108 Handle(TDF_Attribute)& anAttribute) const
110 Handle(TDF_Attribute) locAtt;
111 if (FindAttribute(anID, locAtt)) {
112 while ((!locAtt.IsNull()) && (locAtt->myTransaction > aTransaction))
113 locAtt = locAtt->myBackup;
114 if (!locAtt.IsNull()) {
115 anAttribute = locAtt;
116 return Standard_True;
119 return Standard_False;
122 // Label comfort methods ++++++++++++++++++++++++++++++++++++++++++++++++
124 //=======================================================================
126 //purpose : Returns the depth of the label in the tree.
127 // Root has depth 0. So the depth is the number of fathers.
128 //=======================================================================
130 Standard_Integer TDF_Label::Depth() const
132 if (IsNull()) Standard_NullObject::Raise("A null Label has no depth.");
133 return myLabelNode->Depth();
137 //=======================================================================
138 //function : IsDescendant
139 //purpose : Returns True if <me> is a descendant of <aLabel>.
140 //=======================================================================
142 Standard_Boolean TDF_Label::IsDescendant(const TDF_Label& aLabel) const
144 // Cet algorithme remonte jusqu'a la racine. On peut s'arreter
145 // si la profondeur atteinte est inferieure a celle de <aLabel>.
147 const TDF_LabelNode* lp1 = aLabel.myLabelNode;
148 TDF_LabelNode* lp2 = myLabelNode;
150 if ((lp1 == NULL) || (lp2 == NULL))
151 Standard_NullObject::Raise("A null label has no ancestor nor descendant.");
153 if ((lp1 != NULL) && (lp2 != NULL)) {
154 const Standard_Integer d1 = lp1->Depth();
155 Standard_Integer d2 = lp2->Depth();
156 // Tester (d1 > d2) optimise la recherche ET dispense du test (lp2 != NULL)
157 while ((d2 > d1) && (lp2 != lp1)) {
163 return Standard_False;
167 //=======================================================================
170 //=======================================================================
172 const TDF_Label TDF_Label::Root() const
174 if (IsNull()) Standard_NullObject::Raise("A null Label has no root.");
175 return myLabelNode->RootNode();
179 //=======================================================================
180 //function : NbChildren
181 //purpose : Returns the number of children.
182 //=======================================================================
184 Standard_Integer TDF_Label::NbChildren() const
186 if (IsNull()) Standard_NullObject::Raise("A null Label has no children.");
187 Standard_Integer n = 0;
188 if (myLabelNode->FirstChild() != NULL)
189 for (TDF_ChildIterator itr(*this); itr.More(); itr.Next()) ++n;
194 //=======================================================================
195 //function : FindChild
197 //=======================================================================
199 TDF_Label TDF_Label::FindChild
200 (const Standard_Integer aTag,
201 const Standard_Boolean create) const
204 Standard_NullObject::Raise("A null Label has no child.");
205 if (create && ((Depth()+1) & TDF_LabelNodeFlagsMsk))
206 Standard_OutOfRange::Raise("Depth value out of range");
208 return FindOrAddChild(aTag,create);
211 // Attribute comfort methods ++++++++++++++++++++++++++++++++++++++++++++
213 //=======================================================================
215 //purpose : Returns true if owns an attribute with <anID> as ID.
216 //=======================================================================
218 // Standard_Boolean TDF_Label::IsA(const Standard_GUID& anID) const
220 // Handle(TDF_Attribute) att;
221 // return FindAttribute(anID,att);
224 //=======================================================================
225 //function : IsAttribute
226 //purpose : Returns true if owns an attribute with <anID> as ID.
227 //=======================================================================
229 Standard_Boolean TDF_Label::IsAttribute(const Standard_GUID& anID) const
231 Handle(TDF_Attribute) att;
232 return FindAttribute(anID,att);
236 //=======================================================================
237 //function : HasAttribute
238 //purpose : Returns true if the label has at least one unremoved attribute.
239 //=======================================================================
241 Standard_Boolean TDF_Label::HasAttribute() const
243 if (IsNull()) Standard_NullObject::Raise("A null Label has no attribute.");
245 if (!myLabelNode->FirstAttribute().IsNull()) {
246 TDF_AttributeIterator itr (myLabelNode); // Without removed attributes.
249 return Standard_False;
253 //=======================================================================
254 //function : NbAttributes
255 //purpose : Returns the number of attributes.
256 //=======================================================================
258 Standard_Integer TDF_Label::NbAttributes() const
260 if (IsNull()) Standard_NullObject::Raise("A null Label has no attribute.");
261 Standard_Integer n = 0;
262 if (!myLabelNode->FirstAttribute().IsNull())
263 for (TDF_AttributeIterator itr (myLabelNode); itr.More(); itr.Next()) ++n;
268 // Miscelleaneous +++++++++++++++++++++++++++++++++++++++++++++++++++++++
271 //=======================================================================
272 //function : Transaction
274 //=======================================================================
276 Standard_Integer TDF_Label::Transaction() const
278 if (IsNull()) Standard_NullObject::Raise("A null Label has no transaction.");
279 return myLabelNode->Data()->Transaction();
283 //=======================================================================
285 //purpose : This method is equivalent to operator <<
286 //=======================================================================
288 Standard_OStream& TDF_Label::Dump
289 (Standard_OStream& anOS) const
291 TDF_IDFilter f; TDF_AttributeIndexedMap m;
292 TDF_Label::InternalDump(anOS,f,m,Standard_False);
297 //=======================================================================
298 //function : ExtendedDump
300 //=======================================================================
302 void TDF_Label::ExtendedDump
303 (Standard_OStream& anOS,
304 const TDF_IDFilter& aFilter,
305 TDF_AttributeIndexedMap& aMap) const
306 { TDF_Label::InternalDump(anOS,aFilter,aMap,Standard_True); }
309 //=======================================================================
310 //function : EntryDump
312 //=======================================================================
314 void TDF_Label::EntryDump(Standard_OStream& anOS) const
317 anOS<<"This label is null.";
320 TCollection_AsciiString entry;
321 TDF_Tool::Entry(*this,entry);
326 //=======================================================================
327 //function : FindOrAddChild
328 //purpose : Finds or adds a label child having <aTag> as tag.
329 //=======================================================================
331 TDF_LabelNode* TDF_Label::FindOrAddChild
332 (const Standard_Integer aTag,
333 const Standard_Boolean create) const
335 TDF_LabelNode* currentLnp = myLabelNode->FirstChild();
336 TDF_LabelNode* lastLnp = NULL;
337 TDF_LabelNode* lastFoundLnp = myLabelNode->myLastFoundChild; //jfa 10.01.2003
338 TDF_LabelNode* childLabelNode = NULL;
340 // Finds the right place.
343 // 1. Check, if we access to a child, which is after last touched upon
344 if (lastFoundLnp != NULL) {
345 if (lastFoundLnp->Tag() == aTag) {
348 else if (lastFoundLnp->Tag() < aTag) {
349 lastLnp = lastFoundLnp;
350 currentLnp = lastFoundLnp->Brother();
355 // To facilitate many tools, label brethren are stored in increasing order.
356 while ((currentLnp != NULL) && (currentLnp->Tag() < aTag) ) {
357 lastLnp = currentLnp;
358 currentLnp = currentLnp->Brother();
361 if ( (currentLnp != NULL) && (currentLnp->Tag() == aTag) ) {
363 childLabelNode = currentLnp;
366 // Creates the label to be inserted always before currentLnp.
367 const Handle(NCollection_IncAllocator)& anIncAllocator =
368 (const Handle(NCollection_IncAllocator)&)
369 myLabelNode ->Data() -> LabelNodeAllocator();
370 childLabelNode = new (anIncAllocator) TDF_LabelNode (aTag, myLabelNode);
371 childLabelNode->myBrother = currentLnp; // May be NULL.
372 childLabelNode->Imported(IsImported());
374 if (lastLnp == NULL) // ... at beginning.
375 myLabelNode->myFirstChild = childLabelNode;
376 else // ... somewhere.
377 lastLnp->myBrother = childLabelNode;
380 if (lastLnp) //agv 14.07.2010
381 myLabelNode->myLastFoundChild = lastLnp; //jfa 10.01.2003
383 return childLabelNode;
386 //=======================================================================
387 //function : InternalDump
388 //purpose : Private method.
389 //=======================================================================
391 void TDF_Label::InternalDump
392 (Standard_OStream& anOS,
393 const TDF_IDFilter& aFilter,
394 TDF_AttributeIndexedMap& aMap,
395 const Standard_Boolean extended) const
398 anOS<<"This label is null.";
401 TCollection_AsciiString entry; TDF_Tool::Entry(*this,entry);
403 if (IsImported()) anOS<<"IS "; else anOS<<"NOT"; anOS<<" imported; ";
404 if (MayBeModified()) anOS<<"MAYBE"; else anOS<<"NOT"; anOS<<" modified; ";
405 if (AttributesModified()) anOS<<"HAS attributes"; else anOS<<"NO attribute"; anOS<<" modified; ";
406 if (HasAttribute()) {
407 Standard_Integer nba = NbAttributes();
408 anOS<<"has "<<nba<<" attribute"; if (nba > 1) anOS<<"s"; anOS<<"."<<endl;
409 for (TDF_AttributeIterator itr(myLabelNode); itr.More(); itr.Next()) {
411 // const Handle(TDF_Attribute)& att = itr.Value();
412 Handle(TDF_Attribute) att = itr.Value();
414 if (extended && aFilter.IsKept(att)) anOS<<"\t# "<<aMap.Add(att);
415 att->TDF_Attribute::Dump(anOS);
419 anOS<<" has no attribute"<<endl;
424 Standard_Boolean TDF_Label::HasLowerNode(const TDF_Label& aLabel) const
425 { return (myLabelNode < aLabel.myLabelNode); }
427 Standard_Boolean TDF_Label::HasGreaterNode(const TDF_Label& aLabel) const
428 { return (myLabelNode > aLabel.myLabelNode); }
430 // from insertor ////////////////////////////////////////////////////////
432 //=======================================================================
435 //=======================================================================
437 // void TDF_Label::Add(const Handle(TDF_Attribute)& anAttribute) const
438 // { AddToNode(myLabelNode,anAttribute); }
440 //=======================================================================
441 //function : AddAttribute
443 //=======================================================================
445 void TDF_Label::AddAttribute (const Handle(TDF_Attribute)& anAttribute) const
446 { AddToNode(myLabelNode,anAttribute); }
449 //=======================================================================
452 //=======================================================================
454 // void TDF_Label::Forget(const Handle(TDF_Attribute)& anAttribute) const
455 // { ForgetFromNode(myLabelNode,anAttribute); }
458 //=======================================================================
459 //function : ForgetAttribute
461 //=======================================================================
463 void TDF_Label::ForgetAttribute (const Handle(TDF_Attribute)& anAttribute) const
464 { ForgetFromNode(myLabelNode,anAttribute); }
467 //=======================================================================
470 //=======================================================================
472 // Standard_Boolean TDF_Label::Forget (const Standard_GUID& anID) const
474 // Handle(TDF_Attribute) anAttribute;
475 // //if (Label().FindAttribute(anID,anAttribute)) {
476 // if (FindAttribute(anID,anAttribute)) {
477 // Forget(anAttribute);
478 // return Standard_True;
480 // return Standard_False;
483 //=======================================================================
484 //function : ForgetAttribute
486 //=======================================================================
488 Standard_Boolean TDF_Label::ForgetAttribute (const Standard_GUID& anID) const
490 Handle(TDF_Attribute) anAttribute;
491 //if (Label().FindAttribute(anID,anAttribute)) {
492 if (FindAttribute(anID,anAttribute)) {
493 ForgetAttribute (anAttribute);
494 return Standard_True;
496 return Standard_False;
500 //=======================================================================
501 //function : ForgetAll
503 //=======================================================================
505 // void TDF_Label::ForgetAll (const Standard_Boolean clearChildren) const
507 // for (TDF_AttributeIterator itr1(myLabelNode); itr1.More(); itr1.Next())
508 // ForgetFromNode(myLabelNode,itr1.Value());
509 // if (clearChildren)
510 // for (TDF_ChildIterator itr2(myLabelNode); itr2.More(); itr2.Next()) {
511 // itr2.Value().ForgetAll(clearChildren);
516 //=======================================================================
517 //function : ForgetAllAttributes
519 //=======================================================================
521 void TDF_Label::ForgetAllAttributes (const Standard_Boolean clearChildren) const
523 TDF_AttributeIterator itr1 (myLabelNode);
524 // AGV-OCC5031: iterator must be incremented before removal of the attribute
525 while (itr1.More()) {
526 const Handle(TDF_Attribute) anAttr = itr1.Value();
528 ForgetFromNode (myLabelNode, anAttr);
530 // while (itr1.More()) {
531 // ForgetFromNode(myLabelNode,itr1.Value());
535 for (TDF_ChildIterator itr2(myLabelNode); itr2.More(); itr2.Next()) {
536 itr2.Value().ForgetAllAttributes (clearChildren);
541 //=======================================================================
544 //=======================================================================
546 // void TDF_Label::Resume (const Handle(TDF_Attribute)& anAttribute) const
547 // { ResumeToNode(myLabelNode,anAttribute); }
549 //=======================================================================
550 //function : ResumeAttribute
552 //=======================================================================
554 void TDF_Label::ResumeAttribute (const Handle(TDF_Attribute)& anAttribute) const
555 { ResumeToNode(myLabelNode,anAttribute); }
559 //=======================================================================
560 //function : AddToNode
561 //purpose : Private method used by Add
562 //=======================================================================
564 void TDF_Label::AddToNode (const TDF_LabelNodePtr& toNode,
565 const Handle(TDF_Attribute)& anAttribute) const
567 // check that modification is allowed
568 if ( !toNode->Data()->IsModificationAllowed() ) {
569 TCollection_AsciiString aMess;
570 aMess = "Attribute \"";
571 aMess += anAttribute->DynamicType()->Name();
572 aMess += "\" is added to label outside transaction";
573 Standard_ImmutableObject::Raise(aMess.ToCString());
576 if (!anAttribute->Label().IsNull())
577 Standard_DomainError::Raise("Attribute to add is already attached to a label.");
578 Handle(TDF_Attribute) dummyAtt;
579 //if (Find(anAttribute->ID(),dummyAtt))
580 if (FindAttribute(anAttribute->ID(),dummyAtt))
581 Standard_DomainError::Raise("This label has already such an attribute.");
583 anAttribute->myTransaction = toNode->Data()->Transaction(); /// myData->Transaction();
584 anAttribute->mySavedTransaction = 0;
586 toNode->AddAttribute(dummyAtt,anAttribute);
587 toNode->AttributesModified(anAttribute->myTransaction != 0);
588 //if (myData->NotUndoMode()) anAttribute->AfterAddition();
589 if (toNode->Data()->NotUndoMode()) anAttribute->AfterAddition();
593 //=======================================================================
594 //function : ForgetFromNode
595 //purpose : Private method used by Forget
596 //=======================================================================
598 void TDF_Label::ForgetFromNode (const TDF_LabelNodePtr& fromNode,
599 const Handle(TDF_Attribute)& anAttribute) const
601 // check that modification is allowed
602 if ( !fromNode->Data()->IsModificationAllowed() ) {
603 TCollection_AsciiString aMess;
604 aMess = "Attribute \"";
605 aMess += anAttribute->DynamicType()->Name();
606 aMess += "\" is removed from label outside transaction";
607 Standard_ImmutableObject::Raise(aMess.ToCString());
610 if (fromNode != anAttribute->Label().myLabelNode)
611 Standard_DomainError::Raise
612 ("Attribute to forget not attached to my label.");
614 Standard_Integer curTrans = fromNode->Data()->Transaction();
615 if (!anAttribute->IsForgotten()) {
616 if ( (curTrans == 0) ||
617 ( (anAttribute->myTransaction == curTrans) &&
618 anAttribute->myBackup.IsNull())) {
619 // 1- No transaction is open;
621 // 2- The attribute has been created in the current transaction;
622 // ==> Complete disparition of the attribute.
623 Handle(TDF_Attribute) lastAtt;
624 for (TDF_AttributeIterator itr(fromNode, Standard_False);
627 if (itr.Value() == anAttribute) {
628 //if (myData->NotUndoMode()) {
629 if (fromNode->Data()->NotUndoMode()) {
630 anAttribute->BeforeForget();
631 anAttribute->BeforeRemoval();
633 fromNode->RemoveAttribute(lastAtt,anAttribute);
634 anAttribute->Forget(fromNode->Data()->Transaction()); // vro
637 lastAtt = itr.Value();
641 // One case is here ignored:
642 // The attribute has been modified in the current transaction.
643 // (It has at least one backup.) We don't restore the previous
644 // version before forgetting. It may generated a strange behaviour
645 // in case of forgetting, commiting, aborting...
646 if (fromNode->Data()->NotUndoMode()) anAttribute->BeforeForget();
647 anAttribute->Forget(fromNode->Data()->Transaction());
652 //=======================================================================
653 //function : ResumeToNode
654 //purpose : Private method used by Resume
655 //=======================================================================
657 void TDF_Label::ResumeToNode (const TDF_LabelNodePtr& toNode,
658 const Handle(TDF_Attribute)& anAttribute) const
660 if (anAttribute.IsNull())
661 Standard_NullObject::Raise("The attribute is a null handle.");
662 if (!anAttribute->Label().IsNull())
663 Standard_NullObject::Raise
664 ("Cannot resume an attribute already attached to a label.");
665 if (!anAttribute->IsForgotten())
666 Standard_DomainError::Raise
667 ("Cannot resume an unforgotten attribute.");
669 AddToNode(toNode, anAttribute); // vro
670 anAttribute->Resume();
671 if (toNode->Data()->NotUndoMode()) anAttribute->AfterResume();
674 //////////////////end from insertor ///////////////////////////////////////////////////