0023064: MSVC compiler warnings when Freeimage is not used
[occt.git] / src / TDF / TDF_Label.cxx
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
20 //              --------------
21
22 // Version:     0.0
23 //Version Date            Purpose
24 //              0.0     Feb  6 1997     Creation
25
26
27
28 #include <TDF_Label.ixx>
29
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>
39
40
41 //=======================================================================
42 //function : TDF_Label
43 //purpose  : 
44 //=======================================================================
45
46 TDF_Label::TDF_Label()
47 :myLabelNode(NULL)
48 {}
49
50 //=======================================================================
51 //function : TDF_Label
52 //purpose  : 
53 //=======================================================================
54
55 TDF_Label::TDF_Label(const TDF_LabelNodePtr& aNode)
56 :myLabelNode(aNode)
57 {}
58
59 // Attribute methods ++++++++++++++++++++++++++++++++++++++++++++++++++++
60
61
62 //=======================================================================
63 //function : Imported
64 //purpose  : Sets imported and all its descendants.
65 //=======================================================================
66
67 void TDF_Label::Imported(const Standard_Boolean aStatus) const
68 {
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);
75   }
76 }
77
78
79 //=======================================================================
80 //function : FindAttribute
81 //purpose  : Finds an attributes according to an ID.
82 //=======================================================================
83
84 Standard_Boolean TDF_Label::FindAttribute
85 (const Standard_GUID& anID,
86  Handle(TDF_Attribute)& anAttribute) const
87 {
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();
93       return Standard_True;
94     }
95   }
96   return Standard_False;
97 }
98
99
100 //=======================================================================
101 //function : FindAttribute
102 //purpose  : Finds an attributes according to an ID and a Transaction.
103 //=======================================================================
104
105 Standard_Boolean TDF_Label::FindAttribute
106 (const Standard_GUID& anID,
107  const Standard_Integer aTransaction,
108  Handle(TDF_Attribute)& anAttribute) const
109 {
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;
117     }
118   }
119   return Standard_False;
120 }
121
122 // Label comfort methods ++++++++++++++++++++++++++++++++++++++++++++++++
123
124 //=======================================================================
125 //function : Depth
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 //=======================================================================
129
130 Standard_Integer TDF_Label::Depth() const
131 {
132   if (IsNull()) Standard_NullObject::Raise("A null Label has no depth.");
133   return myLabelNode->Depth();
134 }
135
136
137 //=======================================================================
138 //function : IsDescendant
139 //purpose  : Returns True if <me> is a descendant of <aLabel>.
140 //=======================================================================
141
142 Standard_Boolean TDF_Label::IsDescendant(const TDF_Label& aLabel) const
143 {
144   // Cet algorithme remonte jusqu'a la racine. On peut s'arreter
145   // si la profondeur atteinte est inferieure a celle de <aLabel>.
146
147   const TDF_LabelNode* lp1 = aLabel.myLabelNode;
148   TDF_LabelNode*   lp2 = myLabelNode;
149 #ifdef DEB
150   if ((lp1 == NULL) || (lp2 == NULL))
151     Standard_NullObject::Raise("A null label has no ancestor nor descendant.");
152 #endif
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)) {
158       lp2 = lp2->Father();
159       d2  = lp2->Depth();
160     }
161     return (lp1 == lp2);
162   }
163   return Standard_False;
164 }
165
166
167 //=======================================================================
168 //function : Root
169 //purpose  : 
170 //=======================================================================
171
172 const TDF_Label TDF_Label::Root() const
173 {
174   if (IsNull()) Standard_NullObject::Raise("A null Label has no root.");
175   return myLabelNode->RootNode();
176 }
177
178
179 //=======================================================================
180 //function : NbChildren
181 //purpose  : Returns the number of children.
182 //=======================================================================
183
184 Standard_Integer TDF_Label::NbChildren() const
185 {
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;
190   return n;
191 }
192
193
194 //=======================================================================
195 //function : FindChild
196 //purpose  : 
197 //=======================================================================
198
199 TDF_Label TDF_Label::FindChild
200 (const Standard_Integer aTag,
201  const Standard_Boolean create) const
202 {
203   if (IsNull())
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");
207
208   return FindOrAddChild(aTag,create);
209 }
210
211 // Attribute comfort methods ++++++++++++++++++++++++++++++++++++++++++++
212
213 //=======================================================================
214 //function : IsA
215 //purpose  : Returns true if owns an attribute with <anID> as ID.
216 //=======================================================================
217
218 // Standard_Boolean TDF_Label::IsA(const Standard_GUID& anID) const
219 // {
220 //   Handle(TDF_Attribute) att;
221 //   return FindAttribute(anID,att);
222 // }
223
224 //=======================================================================
225 //function : IsAttribute
226 //purpose  : Returns true if owns an attribute with <anID> as ID.
227 //=======================================================================
228
229 Standard_Boolean TDF_Label::IsAttribute(const Standard_GUID& anID) const
230 {
231   Handle(TDF_Attribute) att;
232   return FindAttribute(anID,att);
233 }
234
235
236 //=======================================================================
237 //function : HasAttribute
238 //purpose  : Returns true if the label has at least one unremoved attribute.
239 //=======================================================================
240
241 Standard_Boolean TDF_Label::HasAttribute() const
242 {
243   if (IsNull()) Standard_NullObject::Raise("A null Label has no attribute.");
244
245   if (!myLabelNode->FirstAttribute().IsNull()) {
246     TDF_AttributeIterator itr (myLabelNode); // Without removed attributes.
247     return itr.More();
248   }
249   return Standard_False;
250 }
251
252
253 //=======================================================================
254 //function : NbAttributes
255 //purpose  : Returns the number of attributes.
256 //=======================================================================
257
258 Standard_Integer TDF_Label::NbAttributes() const
259 {
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;
264   return n;
265 }
266
267
268 // Miscelleaneous +++++++++++++++++++++++++++++++++++++++++++++++++++++++
269
270
271 //=======================================================================
272 //function : Transaction
273 //purpose  : 
274 //=======================================================================
275
276 Standard_Integer TDF_Label::Transaction() const
277 {
278   if (IsNull()) Standard_NullObject::Raise("A null Label has no transaction.");
279   return myLabelNode->Data()->Transaction();
280 }
281
282
283 //=======================================================================
284 //function : Dump
285 //purpose  : This method is equivalent to operator <<
286 //=======================================================================
287
288 Standard_OStream& TDF_Label::Dump
289 (Standard_OStream& anOS) const
290 {
291   TDF_IDFilter f; TDF_AttributeIndexedMap m;
292   TDF_Label::InternalDump(anOS,f,m,Standard_False);
293   return anOS;
294 }
295
296
297 //=======================================================================
298 //function : ExtendedDump
299 //purpose  : 
300 //=======================================================================
301
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); }
307
308
309 //=======================================================================
310 //function : EntryDump
311 //purpose  : 
312 //=======================================================================
313
314 void TDF_Label::EntryDump(Standard_OStream& anOS) const
315 {
316   if (IsNull ()) {
317     anOS<<"This label is null.";
318   }
319   else {
320     TCollection_AsciiString entry;
321     TDF_Tool::Entry(*this,entry);
322     anOS<<entry;
323   }
324 }
325
326 //=======================================================================
327 //function : FindOrAddChild
328 //purpose  : Finds or adds a label child having <aTag> as tag.
329 //=======================================================================
330
331 TDF_LabelNode* TDF_Label::FindOrAddChild
332 (const Standard_Integer aTag,
333  const Standard_Boolean create) const
334 {
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;
339
340   // Finds the right place.
341
342   //jfa 10.01.2003
343   // 1. Check, if we access to a child, which is after last touched upon
344   if (lastFoundLnp != NULL) {
345     if (lastFoundLnp->Tag() == aTag) {
346       return lastFoundLnp;
347     }
348     else if (lastFoundLnp->Tag() < aTag) {
349       lastLnp = lastFoundLnp;
350       currentLnp = lastFoundLnp->Brother();
351     }
352   }
353   //jfa 10.01.2003 end
354
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();
359   }
360
361   if ( (currentLnp != NULL) && (currentLnp->Tag() == aTag) ) {
362     // The label exists.
363     childLabelNode = currentLnp;
364   }
365   else if (create) {
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());
373     //Inserts the label:
374     if (lastLnp == NULL) // ... at beginning.
375       myLabelNode->myFirstChild = childLabelNode;
376     else                 // ... somewhere.
377       lastLnp->myBrother = childLabelNode;
378   }
379
380   if (lastLnp)                               //agv 14.07.2010
381     myLabelNode->myLastFoundChild = lastLnp; //jfa 10.01.2003
382
383   return childLabelNode;
384 }
385
386 //=======================================================================
387 //function : InternalDump
388 //purpose  : Private method.
389 //=======================================================================
390
391 void TDF_Label::InternalDump
392 (Standard_OStream& anOS,
393  const TDF_IDFilter& aFilter,
394  TDF_AttributeIndexedMap& aMap,
395  const Standard_Boolean extended) const
396 {
397   if (IsNull ()) {
398     anOS<<"This label is null.";
399   }
400   else {
401     TCollection_AsciiString entry; TDF_Tool::Entry(*this,entry);
402     anOS<<entry<<"\t";
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()) {
410         // CLE
411         // const Handle(TDF_Attribute)& att = itr.Value();
412         Handle(TDF_Attribute) att = itr.Value();
413         // ENDCLE
414         if (extended && aFilter.IsKept(att)) anOS<<"\t# "<<aMap.Add(att);
415         att->TDF_Attribute::Dump(anOS);
416       }
417     }
418     else {
419       anOS<<" has no attribute"<<endl;
420     }
421   }
422 }
423
424 Standard_Boolean TDF_Label::HasLowerNode(const TDF_Label& aLabel) const
425 { return (myLabelNode < aLabel.myLabelNode); }
426
427 Standard_Boolean TDF_Label::HasGreaterNode(const TDF_Label& aLabel) const
428 { return (myLabelNode > aLabel.myLabelNode); }
429
430 // from insertor ////////////////////////////////////////////////////////
431
432 //=======================================================================
433 //function : Add
434 //purpose  : 
435 //=======================================================================
436
437 // void TDF_Label::Add(const Handle(TDF_Attribute)& anAttribute)  const
438 // { AddToNode(myLabelNode,anAttribute); }
439
440 //=======================================================================
441 //function : AddAttribute
442 //purpose  : 
443 //=======================================================================
444
445 void TDF_Label::AddAttribute (const Handle(TDF_Attribute)& anAttribute)  const
446 { AddToNode(myLabelNode,anAttribute); }
447
448
449 //=======================================================================
450 //function : Forget
451 //purpose  : 
452 //=======================================================================
453
454 // void TDF_Label::Forget(const Handle(TDF_Attribute)& anAttribute)  const
455 // { ForgetFromNode(myLabelNode,anAttribute); }
456
457
458 //=======================================================================
459 //function : ForgetAttribute
460 //purpose  : 
461 //=======================================================================
462
463 void TDF_Label::ForgetAttribute (const Handle(TDF_Attribute)& anAttribute)  const
464 { ForgetFromNode(myLabelNode,anAttribute); }
465
466
467 //=======================================================================
468 //function : Forget
469 //purpose  : 
470 //=======================================================================
471
472 // Standard_Boolean  TDF_Label::Forget (const Standard_GUID& anID) const
473 // {  
474 //   Handle(TDF_Attribute) anAttribute;
475 //   //if (Label().FindAttribute(anID,anAttribute)) { 
476 //   if (FindAttribute(anID,anAttribute)) {
477 //     Forget(anAttribute);
478 //     return Standard_True;
479 //   }
480 //   return Standard_False;
481 // }
482
483 //=======================================================================
484 //function : ForgetAttribute
485 //purpose  : 
486 //=======================================================================
487
488 Standard_Boolean  TDF_Label::ForgetAttribute (const Standard_GUID& anID) const
489 {  
490   Handle(TDF_Attribute) anAttribute;
491   //if (Label().FindAttribute(anID,anAttribute)) { 
492   if (FindAttribute(anID,anAttribute)) {
493     ForgetAttribute (anAttribute);
494     return Standard_True;
495   }
496   return Standard_False;
497 }
498
499
500 //=======================================================================
501 //function : ForgetAll
502 //purpose  : 
503 //=======================================================================
504
505 // void TDF_Label::ForgetAll (const Standard_Boolean clearChildren) const
506 // {
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);
512 //     }
513 // }
514
515
516 //=======================================================================
517 //function : ForgetAllAttributes
518 //purpose  : 
519 //=======================================================================
520
521 void TDF_Label::ForgetAllAttributes (const Standard_Boolean clearChildren) const
522 {
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();
527     itr1.Next();
528     ForgetFromNode (myLabelNode, anAttr);
529   }
530 // while (itr1.More()) {
531 //   ForgetFromNode(myLabelNode,itr1.Value());
532 //   itr1.Next();
533 // }
534   if (clearChildren)
535     for (TDF_ChildIterator itr2(myLabelNode); itr2.More(); itr2.Next()) {
536       itr2.Value().ForgetAllAttributes (clearChildren);
537     }
538 }
539
540
541 //=======================================================================
542 //function : Resume
543 //purpose  : 
544 //=======================================================================
545
546 // void TDF_Label::Resume (const Handle(TDF_Attribute)& anAttribute)  const
547 // { ResumeToNode(myLabelNode,anAttribute); }
548
549 //=======================================================================
550 //function : ResumeAttribute
551 //purpose  : 
552 //=======================================================================
553
554 void TDF_Label::ResumeAttribute (const Handle(TDF_Attribute)& anAttribute)  const
555 { ResumeToNode(myLabelNode,anAttribute); }
556
557
558
559 //=======================================================================
560 //function : AddToNode
561 //purpose  : Private method used by Add
562 //=======================================================================
563
564 void TDF_Label::AddToNode (const TDF_LabelNodePtr& toNode,
565                            const Handle(TDF_Attribute)& anAttribute) const
566 {
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());
574   }
575     
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.");
582
583   anAttribute->myTransaction = toNode->Data()->Transaction();  /// myData->Transaction();
584   anAttribute->mySavedTransaction = 0;
585   dummyAtt.Nullify();
586   toNode->AddAttribute(dummyAtt,anAttribute);
587   toNode->AttributesModified(anAttribute->myTransaction != 0);
588   //if (myData->NotUndoMode()) anAttribute->AfterAddition();  
589   if (toNode->Data()->NotUndoMode()) anAttribute->AfterAddition();
590 }
591
592
593 //=======================================================================
594 //function : ForgetFromNode
595 //purpose  : Private method used by Forget
596 //=======================================================================
597
598 void TDF_Label::ForgetFromNode (const TDF_LabelNodePtr& fromNode,
599                                 const Handle(TDF_Attribute)& anAttribute) const
600 {
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());
608   }
609     
610   if (fromNode != anAttribute->Label().myLabelNode)
611     Standard_DomainError::Raise
612       ("Attribute to forget not attached to my label.");
613
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;
620       // OR
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);
625            itr.More();
626            itr.Next()) {
627         if (itr.Value() == anAttribute) {
628           //if (myData->NotUndoMode()) { 
629           if (fromNode->Data()->NotUndoMode()) {
630             anAttribute->BeforeForget();
631             anAttribute->BeforeRemoval();
632           }
633           fromNode->RemoveAttribute(lastAtt,anAttribute);
634           anAttribute->Forget(fromNode->Data()->Transaction()); // vro
635           break;
636         }
637         lastAtt = itr.Value();
638       }
639     }
640     else {
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());
648     }
649   }
650 }
651
652 //=======================================================================
653 //function : ResumeToNode
654 //purpose  : Private method used by Resume
655 //=======================================================================
656
657 void TDF_Label::ResumeToNode (const TDF_LabelNodePtr& toNode,
658                               const Handle(TDF_Attribute)& anAttribute) const
659 {
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.");
668
669   AddToNode(toNode, anAttribute); // vro
670   anAttribute->Resume();
671   if (toNode->Data()->NotUndoMode()) anAttribute->AfterResume();
672 }
673
674 //////////////////end from insertor ///////////////////////////////////////////////////