0028832: MMgt_TShared can be replaced by Standard_Transient
[occt.git] / src / TObj / TObj_Object.cxx
1 // Created on: 2004-11-22
2 // Created by: Pavel TELKOV
3 // Copyright (c) 2004-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 // The original implementation Copyright: (C) RINA S.p.A
17
18 #include <TObj_Object.hxx>
19
20 #include <TObj_Assistant.hxx>
21 #include <TObj_LabelIterator.hxx>
22 #include <TObj_Model.hxx>
23 #include <TObj_ObjectIterator.hxx>
24 #include <TObj_OcafObjectIterator.hxx>
25 #include <TObj_Persistence.hxx>
26 #include <TObj_ReferenceIterator.hxx>
27 #include <TObj_SequenceIterator.hxx>
28 #include <TDataStd_AsciiString.hxx>
29 #include <TObj_TModel.hxx>
30 #include <TObj_TNameContainer.hxx>
31 #include <TObj_TObject.hxx>
32 #include <TObj_TReference.hxx>
33
34 #include <TCollection_HAsciiString.hxx>
35 #include <TColStd_HArray1OfInteger.hxx>
36 #include <TColStd_HArray1OfReal.hxx>
37 #include <TColStd_HArray1OfExtendedString.hxx>
38 #include <TColStd_SequenceOfInteger.hxx>
39 #include <TDF_AttributeIterator.hxx>
40 #include <TDF_ChildIDIterator.hxx>
41 #include <TDF_ChildIterator.hxx>
42 #include <TDF_CopyLabel.hxx>
43 #include <TDF_Data.hxx>
44 #include <TDF_RelocationTable.hxx>
45 #include <TDF_Tool.hxx>
46 #include <TDataStd_ExtStringArray.hxx>
47 #include <TDataStd_Integer.hxx>
48 #include <TDataStd_IntegerArray.hxx>
49 #include <TDataStd_Name.hxx>
50 #include <TDataStd_Real.hxx>
51 #include <TDataStd_RealArray.hxx>
52 #include <TDocStd_Document.hxx>
53 #include <TDocStd_Owner.hxx>
54 #include <TDF_TagSource.hxx>
55
56
57 IMPLEMENT_STANDARD_RTTIEXT(TObj_Object,Standard_Transient)
58
59 //=======================================================================
60 //function : Constructor
61 //purpose  :
62 //=======================================================================
63
64 TObj_Object::TObj_Object(const TDF_Label& theLabel,
65                                  const Standard_Boolean theSetName)
66      : myLabel(theLabel)
67 {
68   Handle(TObj_Object) aMe = this;
69   TObj_TObject::Set(myLabel, aMe);
70   if (theSetName)
71     TObj_Model::SetNewName(aMe);
72 }
73
74 //=======================================================================
75 //function : GetModel
76 //purpose  :
77 //=======================================================================
78
79 Handle(TObj_Model) TObj_Object::GetModel() const
80 {
81   Handle(TObj_Model) aModel;
82   // if object label is null object is not alive
83   if ( myLabel.IsNull() )
84     return aModel;
85
86   //TDF_Label aLabel = TDocStd_Document::Get(myLabel)->Main();
87   Handle(TDF_Data) aData = myLabel.Data();
88   if (aData.IsNull())
89     return aModel;
90   
91   // try get the document from owner attribute manually
92   TDF_Label aLabel = aData->Root();
93   Handle(TDocStd_Owner) anOwnerAttr;
94   Handle(TDocStd_Document) aTDoc;
95   if ( !aLabel.IsNull() && aLabel.FindAttribute( TDocStd_Owner::GetID(), anOwnerAttr ) )
96     aTDoc = anOwnerAttr->GetDocument();
97   if (aTDoc.IsNull())
98     return aModel;
99   
100   // use main label of the document to find TObj model attribute
101   aLabel = aTDoc->Main();
102   Handle(TObj_TModel) aModelAttr;
103   if (!aLabel.IsNull() && aLabel.FindAttribute(TObj_TModel::GetID(), aModelAttr))
104     aModel = aModelAttr->Model();
105
106   return aModel;
107 }
108
109 //=======================================================================
110 //function : GetChildren
111 //purpose  : Returns iterator for the child objects.
112 //           This method provides tree-like view of the objects hierarchy.
113 //           The references to other objects are not considered as children.
114 //           theType narrows a variety of iterated objects
115 //=======================================================================
116
117 static void addObjToOrderSequence( const Handle(TObj_Object)& theObj,
118                                    const Standard_Integer         theOrder,
119                                    Handle(TObj_HSequenceOfObject)& theHSeqOfObj,
120                                    const Standard_Integer theHSeqLength,
121                                    Standard_Integer& theLastIndex,
122                                    Standard_Integer& theLastOrder )
123 {
124   if ( theOrder > theLastOrder )
125   {
126     while ( theOrder > theLastOrder )
127     {
128       // get next object and compare with them
129       if ( ++theLastIndex > theHSeqLength )
130       {
131         theHSeqOfObj->Append( theObj );
132         theLastIndex = theHSeqLength + 1;
133         theLastOrder = theOrder;
134         return;
135       }
136       Handle(TObj_Object) aNext = theHSeqOfObj->Value(theLastIndex);
137       theLastOrder = aNext->GetOrder();
138     }
139     // add before current position
140     theHSeqOfObj->InsertBefore( theLastIndex, theObj );
141     theLastOrder = theOrder;
142   }
143   else
144   {
145     while ( theOrder < theLastOrder )
146     {
147       if ( --theLastIndex < 1 )
148       {
149         theHSeqOfObj->InsertBefore( 1, theObj );
150         theLastIndex = 1;
151         theLastOrder = theOrder;
152         return;
153       }
154       // get next object and compare with them
155       Handle(TObj_Object) aNext = theHSeqOfObj->Value(theLastIndex);
156       theLastOrder = aNext->GetOrder();
157     }
158     // add object after current position
159     theHSeqOfObj->InsertAfter( theLastIndex, theObj );
160     theLastIndex++;
161     theLastOrder = theOrder;
162     return;
163   }
164 }
165
166 Handle(TObj_ObjectIterator) TObj_Object::GetChildren
167                          (const Handle(Standard_Type)& theType) const
168 {
169   Handle(TObj_ObjectIterator) anItr =
170     new TObj_OcafObjectIterator(GetChildLabel(), theType, Standard_True);
171   if ( !TestFlags( ObjectState_Ordered ) )
172     return anItr;
173   // return object according to their order
174   Standard_Integer aLastIndex = 0;
175   Standard_Integer aLastOrder = 0;
176   Handle(TObj_HSequenceOfObject) aHSeqOfObj = new TObj_HSequenceOfObject();
177   for ( ; anItr->More(); anItr->Next() )
178   {
179     Handle(TObj_Object) anObj = anItr->Value();
180     if ( anObj.IsNull() )
181       continue;
182     Standard_Integer anOrder = anObj->GetOrder();
183     if ( !aLastIndex )
184     {
185       aHSeqOfObj->Append( anObj );
186       aLastIndex = 1;
187       aLastOrder = anOrder;
188     }
189     else
190       addObjToOrderSequence( anObj, anOrder, aHSeqOfObj, aHSeqOfObj->Length(),
191                              aLastIndex, aLastOrder );
192   }
193   return new TObj_SequenceIterator( aHSeqOfObj );
194 }
195
196 //=======================================================================
197 //function : getLabelByRank
198 //purpose  : Auxiliary function to get a label and attache a name to it
199 //           Used in debug mode only
200 //=======================================================================
201
202 #ifdef DFBROWSE
203 static TDF_Label getLabelByRank(const TDF_Label& theL,
204                                 const Standard_Integer theRank,
205                                 const Standard_CString theName)
206 {
207   TDF_Label L = theL.FindChild(theRank,Standard_False);
208   if ( L.IsNull() )
209   {
210     L = theL.FindChild(theRank,Standard_True);
211     TDataStd_Name::Set(L, theName);
212   }
213   return L;
214 }
215 #endif
216
217 //=======================================================================
218 //function : GetChildLabel
219 //purpose  :
220 //=======================================================================
221
222 TDF_Label TObj_Object::GetChildLabel() const
223 {
224 #ifdef DFBROWSE
225   return getLabelByRank(GetLabel(),4,"Children");
226 #else
227   return GetLabel().FindChild ( 4, Standard_True );
228 #endif
229 }
230
231 //=======================================================================
232 //function : getChildLabel
233 //purpose  :
234 //=======================================================================
235
236 TDF_Label TObj_Object::getChildLabel(const Standard_Integer theRank) const
237 {
238   TDF_Label aLabel = GetChildLabel();
239   if ( theRank > 0 )
240     aLabel = aLabel.FindChild( theRank, Standard_True );
241   return aLabel;
242 }
243
244 //=======================================================================
245 //function : GetLabel
246 //purpose  :
247 //=======================================================================
248
249 TDF_Label TObj_Object::GetLabel() const
250 {
251   return myLabel;
252 }
253
254 //=======================================================================
255 //function : SetName
256 //purpose  :
257 //=======================================================================
258
259 Standard_Boolean TObj_Object::SetName(const Handle(TCollection_HExtendedString)& theName) const
260 {
261   // check if the name is exactly the same
262   Handle(TCollection_HExtendedString) anOldName = GetName();
263   if( !anOldName.IsNull() && theName->String().IsEqual(anOldName->String()) )
264     return Standard_True;
265
266   // check if name is already registered and do nothing in that case
267   const Handle(TObj_TNameContainer) aDictionary = GetDictionary();
268   Handle(TObj_Model) aModel = GetModel();
269   if( aModel->IsRegisteredName( theName, aDictionary ) )
270     return Standard_False;
271
272   // change name and update registry
273   if (!anOldName.IsNull())
274     aModel->UnRegisterName( anOldName, aDictionary );
275   if ( theName.IsNull() ) 
276     GetLabel().ForgetAttribute ( TDataStd_Name::GetID() );
277   else
278   {
279     aModel->RegisterName( theName, GetLabel(), aDictionary );
280     TDataStd_Name::Set(GetLabel(),theName->String());
281   }
282   return Standard_True;
283 }
284
285 //=======================================================================
286 //function : SetName
287 //purpose  :
288 //=======================================================================
289
290 Standard_Boolean TObj_Object::SetName(const Handle(TCollection_HAsciiString)& theName) const
291 {
292   return SetName( new TCollection_HExtendedString ( theName ) );
293 }
294
295 //=======================================================================
296 //function : SetName
297 //purpose  :
298 //=======================================================================
299
300 Standard_Boolean TObj_Object::SetName(const Standard_CString theName) const
301 {
302   return SetName ( new TCollection_HExtendedString ( theName ) );
303 }
304
305 //=======================================================================
306 //function : GetName
307 //purpose  :
308 //=======================================================================
309
310 Handle(TCollection_HExtendedString) TObj_Object::GetName() const
311 {
312   Handle(TCollection_HExtendedString) aName;
313   Handle(TDataStd_Name) A;
314   if (GetLabel().FindAttribute (TDataStd_Name::GetID(), A))
315     aName = new TCollection_HExtendedString(A->Get());
316   else aName = new TCollection_HExtendedString("");
317   return aName;
318 }
319
320 //=======================================================================
321 //function : GetName
322 //purpose  :
323 //=======================================================================
324
325 Standard_Boolean TObj_Object::GetName(TCollection_ExtendedString& theStr) const
326 {
327   Handle(TCollection_HExtendedString) aName = GetName();
328   theStr = aName->String();
329   return theStr.Length() != 0;
330 }
331
332 //=======================================================================
333 //function : GetName
334 //purpose  :
335 //=======================================================================
336
337 Standard_Boolean TObj_Object::GetName(TCollection_AsciiString& theName) const
338 {
339   Handle(TCollection_HExtendedString) aName = GetName();
340   if(aName.IsNull())
341     return Standard_False;
342   theName = TCollection_AsciiString (aName->String());
343   return theName.Length() != 0;
344 }
345
346 //=======================================================================
347 //function : HasReference
348 //purpose  :
349 //=======================================================================
350
351 Standard_Boolean TObj_Object::HasReference
352                          (const Handle(TObj_Object)& theObject) const
353 {
354   if ( theObject.IsNull() )
355     return Standard_False;
356   Handle(TObj_ObjectIterator) anItr = GetReferences(theObject->DynamicType());
357   if ( anItr.IsNull() || !anItr->More() )
358     return Standard_False;
359   for ( ; anItr->More(); anItr->Next() )
360     if ( anItr->Value() == theObject )
361       return Standard_True;
362   return Standard_False;
363 }
364
365 //=======================================================================
366 //function : GetReferences
367 //purpose  :
368 //=======================================================================
369
370 Handle(TObj_ObjectIterator) TObj_Object::GetReferences
371                          (const Handle(Standard_Type)& theType) const
372 {
373   return new TObj_ReferenceIterator(GetReferenceLabel(), theType);
374 }
375
376 //=======================================================================
377 //function : RemoveAllReferences
378 //purpose  :
379 //=======================================================================
380
381 void TObj_Object::RemoveAllReferences()
382 {
383   GetReferenceLabel().ForgetAllAttributes();
384   // other implementation may be get all reference by iterator
385   // and replace all of them by null handle with help of ::ReplaceReference
386 }
387
388 //=======================================================================
389 //function : AddBackReference
390 //purpose  :
391 //=======================================================================
392
393 void TObj_Object::AddBackReference (const Handle(TObj_Object)& theObject)
394 {
395   if (myHSeqBackRef.IsNull())
396     myHSeqBackRef = new TObj_HSequenceOfObject;
397
398   myHSeqBackRef->Append( theObject );
399 }
400
401 //=======================================================================
402 //function : RemoveBackReference
403 //purpose  :
404 //=======================================================================
405
406 void TObj_Object::RemoveBackReference (const Handle(TObj_Object)& theObject,
407                                            const Standard_Boolean theSingleOnly)
408 {
409   if (myHSeqBackRef.IsNull()) // to avoid exception.
410     return;
411
412   for (Standard_Integer i = 1; i <= myHSeqBackRef->Length(); i++)
413   {
414     if (theObject != myHSeqBackRef->Value(i))
415       continue;
416
417     myHSeqBackRef->Remove(i--);
418     if (theSingleOnly)
419       break;
420   }
421   if (myHSeqBackRef->Length() < 1)
422     myHSeqBackRef.Nullify(); // do not need to store empty sequence.
423 }
424 //=======================================================================
425 //function : GetBackReferences
426 //purpose  :
427 //=======================================================================
428
429 Handle(TObj_ObjectIterator) TObj_Object::GetBackReferences
430                          (const Handle(Standard_Type)& theType) const
431 {
432   return new TObj_SequenceIterator( myHSeqBackRef, theType );
433 }
434
435 //=======================================================================
436 //function : ClearBackReferences
437 //purpose  :
438 //=======================================================================
439
440 void TObj_Object::ClearBackReferences ()
441 {
442   myHSeqBackRef.Nullify();
443 }
444
445 //=======================================================================
446 //function : HasBackReferences
447 //purpose  : 
448 //=======================================================================
449
450 Standard_Boolean TObj_Object::HasBackReferences() const
451 {
452   Handle(TObj_ObjectIterator) anItr = GetBackReferences();
453   if ( anItr.IsNull() || !anItr->More() )
454     return Standard_False;
455   return Standard_True;
456 }
457
458 //=======================================================================
459 //function : CanRemoveReference
460 //purpose  : 
461 //=======================================================================
462
463 Standard_Boolean TObj_Object::CanRemoveReference
464   (const Handle(TObj_Object)& /*theObject*/) const
465 {
466   return Standard_False;
467 }
468
469 //=======================================================================
470 //function : RemoveReference
471 //purpose  : 
472 //=======================================================================
473
474 void TObj_Object::RemoveReference (const Handle(TObj_Object)& theObject)
475 {
476   Handle(TObj_Object) aNullObj;
477   ReplaceReference (theObject, aNullObj);
478 }
479   
480 //=======================================================================
481 //function : CanDetach
482 //purpose  :
483 //=======================================================================
484  Standard_Boolean TObj_Object::CanDetach(const TObj_DeletingMode theMode )
485 {
486   if( !IsAlive() )
487     return Standard_False;
488   
489   Handle(TObj_ObjectIterator) aRefs = GetBackReferences();
490   
491   // Free Object can be deleted in any Mode
492   if ( aRefs.IsNull() || ! aRefs->More() )
493     return Standard_True;
494   
495   if( theMode == TObj_FreeOnly )
496     return Standard_False;
497
498   if( theMode == TObj_Forced )
499     return Standard_True;
500
501   // check the last KeepDepending mode
502   Handle(TObj_Object) aMe = this;
503   for( ; aRefs->More(); aRefs->Next()) 
504   {
505     Handle(TObj_Object) anObject = aRefs->Value();
506     if (! anObject->CanRemoveReference(aMe) )
507       return Standard_False; // one of objects could not be unlinked
508   }
509     
510   return Standard_True;
511 }
512
513 //=======================================================================
514 //function : Detach
515 //purpose  :
516 //=======================================================================
517
518 Standard_Boolean TObj_Object::Detach(const TObj_DeletingMode theMode)
519 {
520   if( !IsAlive() )
521     return Standard_False;
522
523   // if object can not be deleted returns False
524   if(!RemoveBackReferences(theMode))
525     return Standard_False;
526
527   Handle(TCollection_HExtendedString) anOldName = GetName();
528
529   // detaching childs
530   Handle(TObj_ObjectIterator) aChildren = GetChildren();
531
532   for(;aChildren->More(); aChildren->Next())
533     aChildren->Value()->Detach(theMode);
534
535   // Clearing its own data
536   GetReferenceLabel().ForgetAllAttributes();
537   // clear back references container
538   ClearBackReferences();
539   // remove data
540   GetDataLabel().ForgetAllAttributes();
541
542   if (!anOldName.IsNull())
543   {
544     const Handle(TObj_TNameContainer) aDictionary = GetDictionary();
545     // unregister only it is registered to me.
546     if ( !aDictionary.IsNull() && aDictionary->IsRegistered( anOldName ) )
547     {
548       TDF_Label aRegisteredLabel = aDictionary->Get().Find( anOldName );
549       if ( !aRegisteredLabel.IsNull() && aRegisteredLabel == GetLabel() )
550         aDictionary->RemoveName( anOldName );
551     }
552   }
553   GetLabel().ForgetAllAttributes();
554
555   return Standard_True;
556 }
557
558 //=======================================================================
559 //function : Detach
560 //purpose  : public static method
561 //=======================================================================
562
563 Standard_Boolean TObj_Object::Detach(const TDF_Label& theLabel,
564                                          const  TObj_DeletingMode theMode)
565 {
566   Handle(TObj_Object) anObject;
567   if( GetObj(theLabel, anObject) )
568     return anObject->Detach(theMode);
569   return Standard_True;
570 }
571
572 //=======================================================================
573 //function : GetObj
574 //purpose  :
575 //=======================================================================
576
577 Standard_Boolean TObj_Object::GetObj(const TDF_Label& theLabel,
578                                          Handle(TObj_Object)& theResult,
579                                          const Standard_Boolean isSuper)
580 {
581   if(theLabel.IsNull())
582     return Standard_False;
583
584   Handle(TObj_TObject) A;
585
586   // find on the current label
587   if ( theLabel.FindAttribute(TObj_TObject::GetID(), A) )
588     theResult = A->Get();
589   else
590     theResult.Nullify();
591
592   if( !theResult.IsNull() )
593   {
594     if( !theResult->myLabel.IsNull() )
595       return Standard_True;
596
597     // if the object is not allive then it is a wrong data in the Data Model
598     theResult.Nullify();
599   }
600   else if( isSuper )
601   {
602     // try to get object from the father label
603     return GetObj(theLabel.Father(),theResult,isSuper);
604   }
605
606   return Standard_False;
607 }
608
609 //=======================================================================
610 //function : GetFatherObject
611 //purpose  : Returns the father object, which may be NULL
612 //           theType gives type of father object to search
613 //=======================================================================
614
615 Handle(TObj_Object) TObj_Object::GetFatherObject
616                          (const Handle(Standard_Type)& theType) const
617 {
618   Handle(TObj_Object) aFather, aSon(this);
619
620   while ( aSon->GetObj( aSon->GetLabel().Father(), aFather, Standard_True ) )
621   {
622     if (theType.IsNull() || aFather->IsKind( theType ))
623       break;
624     else
625     {
626       aSon = aFather;
627       aFather.Nullify();
628     }
629   }
630
631   return aFather;
632 }
633
634
635 //=======================================================================
636 //function : AfterRetrieval
637 //purpose  :
638 //=======================================================================
639
640 void TObj_Object::AfterRetrieval()
641 {
642   // Register the name
643   Handle(TObj_Model) aModel = GetModel();
644   if ( !aModel.IsNull() )
645     aModel->RegisterName( GetName(), GetLabel(), GetDictionary() );
646 }
647
648 //=======================================================================
649 //function : BeforeStoring
650 //purpose  : base implementation
651 //=======================================================================
652
653 void TObj_Object::BeforeStoring()
654 {
655 }
656
657 //=======================================================================
658 //function : GetReferenceLabel
659 //purpose  :
660 //=======================================================================
661
662 TDF_Label TObj_Object::GetReferenceLabel() const
663 {
664 #ifdef DFBROWSE
665   return getLabelByRank(GetLabel(),1,"References");
666 #else
667   return GetLabel().FindChild ( 1, Standard_True );
668 #endif
669 }
670
671 //=======================================================================
672 //function : GetDataLabel
673 //purpose  :
674 //=======================================================================
675
676 TDF_Label TObj_Object::GetDataLabel() const
677 {
678 #ifdef DFBROWSE
679   return getLabelByRank(GetLabel(),3,"Data");
680 #else
681   return GetLabel().FindChild ( 3, Standard_True );
682 #endif
683 }
684
685 //=======================================================================
686 //function : getDataLabel
687 //purpose  :
688 //=======================================================================
689
690 TDF_Label TObj_Object::getDataLabel (const Standard_Integer theRank1,
691                                          const Standard_Integer theRank2) const
692 {
693   TDF_Label aLabel;
694   if ( theRank1 > 0 ) // protection
695   {
696     aLabel = GetDataLabel().FindChild ( theRank1, Standard_True );
697     if ( theRank2 > 0 )
698       aLabel = aLabel.FindChild ( theRank2, Standard_True );
699   }
700   return aLabel;
701 }
702
703 //=======================================================================
704 //function : getReferenceLabel
705 //purpose  :
706 //=======================================================================
707
708 TDF_Label TObj_Object::getReferenceLabel (const Standard_Integer theRank1,
709                                               const Standard_Integer theRank2) const
710 {
711   TDF_Label aLabel;
712   if ( theRank1 > 0 ) // protection
713   {
714     aLabel = GetReferenceLabel().FindChild ( theRank1, Standard_True );
715     if ( theRank2 > 0 )
716       aLabel = aLabel.FindChild ( theRank2, Standard_True );
717   }
718   return aLabel;
719 }
720
721 //=======================================================================
722 //function : isDataAttribute
723 //purpose  : Returns True if there is an attribute having theGUID on the
724 //           theRank2-th sublabel of theRank1-th sublabel of the Data
725 //           label of the object.
726 //           If theRank2 is 0 (default), label theRank1 is supposed, not
727 //           its sublabel
728 //=======================================================================
729
730 Standard_Boolean TObj_Object::isDataAttribute
731                         (const Standard_GUID&   theGUID,
732                          const Standard_Integer theRank1,
733                          const Standard_Integer theRank2) const
734 {
735   return getDataLabel(theRank1,theRank2).IsAttribute(theGUID);
736 }
737
738 //=======================================================================
739 //function : getReal
740 //purpose  :
741 //=======================================================================
742
743 Standard_Real TObj_Object::getReal (const Standard_Integer theRank1,
744                                         const Standard_Integer theRank2) const
745 {
746   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
747
748   Handle(TDataStd_Real) aReal;
749   aLabel.FindAttribute ( TDataStd_Real::GetID(), aReal );
750   return aReal.IsNull() ? 0. : aReal->Get();
751 }
752
753 //=======================================================================
754 //function : setReal
755 //purpose  :
756 //=======================================================================
757
758 Standard_Boolean TObj_Object::setReal (const Standard_Real theValue,
759                                            const Standard_Integer theRank1,
760                                            const Standard_Integer theRank2,
761                                            const Standard_Real theTolerance) const
762 {
763   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
764
765   // check that value is actually changed
766   Handle(TDataStd_Real) A;
767   if ( aLabel.FindAttribute(TDataStd_Real::GetID(), A) &&
768        fabs ( A->Get() - theValue ) <= theTolerance ) return Standard_False;
769
770   TDataStd_Real::Set ( aLabel, theValue );
771   return Standard_True;
772 }
773
774 //=======================================================================
775 //function : getExtString
776 //purpose  :
777 //=======================================================================
778
779 Handle(TCollection_HExtendedString) TObj_Object::getExtString
780        (const Standard_Integer theRank1,
781         const Standard_Integer theRank2) const
782 {
783   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
784
785   Handle(TDataStd_Name) aName;
786   aLabel.FindAttribute ( TDataStd_Name::GetID(), aName );
787   return aName.IsNull() ? 0 : new TCollection_HExtendedString(aName->Get());
788 }
789
790 //=======================================================================
791 //function : setExtString
792 //purpose  :
793 //=======================================================================
794
795 void TObj_Object::setExtString
796   (const Handle(TCollection_HExtendedString)& theValue,
797    const Standard_Integer theRank1,
798    const Standard_Integer theRank2) const
799 {
800   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
801   if ( !theValue.IsNull() )
802     TDataStd_Name::Set ( aLabel, theValue->String() );
803   else
804     aLabel.ForgetAttribute( TDataStd_Name::GetID() );
805 }
806
807 //=======================================================================
808 //function : getAsciiString
809 //purpose  :
810 //=======================================================================
811
812 Handle(TCollection_HAsciiString) TObj_Object::getAsciiString
813        (const Standard_Integer theRank1,
814         const Standard_Integer theRank2) const
815 {
816   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
817
818   Handle(TDataStd_AsciiString) aStrAttr;
819   aLabel.FindAttribute ( TDataStd_AsciiString::GetID(), aStrAttr );
820   return aStrAttr.IsNull() ? 0 : new TCollection_HAsciiString( aStrAttr->Get() );
821 }
822
823 //=======================================================================
824 //function : setAsciiString
825 //purpose  :
826 //=======================================================================
827
828 void TObj_Object::setAsciiString
829   (const Handle(TCollection_HAsciiString)& theValue,
830    const Standard_Integer theRank1,
831    const Standard_Integer theRank2) const
832 {
833   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
834   if ( !theValue.IsNull() )
835     TDataStd_AsciiString::Set ( aLabel, theValue->String() );
836   else
837     aLabel.ForgetAttribute( TDataStd_AsciiString::GetID() );
838 }
839
840 //=======================================================================
841 //function : getInteger
842 //purpose  :
843 //=======================================================================
844
845 Standard_Integer TObj_Object::getInteger (const Standard_Integer theRank1,
846                                               const Standard_Integer theRank2) const
847 {
848   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
849
850   Handle(TDataStd_Integer) aNum;
851   aLabel.FindAttribute ( TDataStd_Integer::GetID(), aNum );
852   return aNum.IsNull() ? 0 : aNum->Get();
853 }
854
855 //=======================================================================
856 //function : setInteger
857 //purpose  :
858 //=======================================================================
859
860 Standard_Boolean TObj_Object::setInteger (const Standard_Integer theValue,
861                                               const Standard_Integer theRank1,
862                                               const Standard_Integer theRank2) const
863 {
864   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
865
866   // check that value is actually changed
867   Handle(TDataStd_Integer) A;
868   if ( aLabel.FindAttribute(TDataStd_Integer::GetID(), A) &&
869        A->Get() == theValue ) return Standard_False;
870
871   TDataStd_Integer::Set ( aLabel, theValue );
872   return Standard_True;
873 }
874
875 //=======================================================================
876 //function : getReference
877 //purpose  :
878 //=======================================================================
879
880 Handle(TObj_Object) TObj_Object::getReference (const Standard_Integer theRank1,
881                                                        const Standard_Integer theRank2) const
882 {
883   TDF_Label aLabel = getReferenceLabel(theRank1,theRank2);
884
885   Handle(TObj_TReference) aRef;
886   aLabel.FindAttribute ( TObj_TReference::GetID(), aRef );
887   return aRef.IsNull() ? Handle(TObj_Object)() : aRef->Get();
888 }
889
890 //=======================================================================
891 //function : setReference
892 //purpose  :
893 //=======================================================================
894
895 Standard_Boolean TObj_Object::setReference (const Handle(TObj_Object) & theObject,
896                                                 const Standard_Integer theRank1,
897                                                 const Standard_Integer theRank2)
898 {
899   TDF_Label aLabel = getReferenceLabel(theRank1,theRank2);
900
901   if ( theObject.IsNull() )
902     return aLabel.ForgetAttribute ( TObj_TReference::GetID() );
903   
904   // check that reference is actually changed
905   Handle(TObj_TReference) A;
906   if ( aLabel.FindAttribute(TObj_TReference::GetID(), A) &&
907        A->Get() == theObject ) return Standard_False;
908
909   // 27.07.05, PTv: remove reference attribute before create new reference (for Undo/Redo)
910   aLabel.ForgetAttribute( TObj_TReference::GetID() );
911
912   Handle(TObj_Object) me = this;
913   TObj_TReference::Set ( aLabel, theObject, me);
914   return Standard_True;
915 }
916
917 //=======================================================================
918 //function : addReference
919 //purpose  :
920 //=======================================================================
921
922 TDF_Label TObj_Object::addReference (const Standard_Integer theRank1,
923                                          const Handle(TObj_Object) & theObject)
924 {
925   TDF_Label aRefLabel = GetReferenceLabel();
926   if ( theRank1 > 0 )
927     aRefLabel = aRefLabel.FindChild ( theRank1, Standard_True );
928
929   TDF_TagSource aTag;
930   TDF_Label aLabel = aTag.NewChild(aRefLabel);
931
932   Handle(TObj_Object) me = this;
933   TObj_TReference::Set ( aLabel, theObject, me);
934   return aLabel;
935 }
936
937 //=======================================================================
938 //function : getRealArray
939 //purpose  : Returns an existing or create a new real array on theRank2-th
940 //           sublabel of theRank1-th sublabel of the Data label of the object.
941 //           If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel).
942 //           A newly created array has 1 and theLength bounds and is initialized
943 //           with zero
944 //WARNING  : call setArray() after array contents modification
945 //           in order to assure Undo work
946 //=======================================================================
947
948 Handle(TColStd_HArray1OfReal) TObj_Object::getRealArray
949                         (const Standard_Integer theLength,
950                          const Standard_Integer theRank1,
951                          const Standard_Integer theRank2,
952                          const Standard_Real    theInitialValue) const
953 {
954   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
955   Handle(TDataStd_RealArray) anArrAttribute;
956   if (!aLabel.FindAttribute(TDataStd_RealArray::GetID(), anArrAttribute))
957     if ( theLength > 0 )
958     {
959       anArrAttribute = TDataStd_RealArray::Set (aLabel, 1, theLength);
960       anArrAttribute->Array()->Init( theInitialValue );
961     }
962   Handle(TColStd_HArray1OfReal) anArr;
963   if ( !anArrAttribute.IsNull() )
964     anArr = anArrAttribute->Array();
965   return anArr;
966 }
967
968 //=======================================================================
969 //function : getIntegerArray
970 //purpose  : Returns an existing or create a new integer array on theRank2-th
971 //           sublabel of theRank1-th sublabel of the Data label of the object.
972 //           If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel).
973 //           A newly created array has 1 and theLength bounds and is initialized
974 //           with zero
975 //WARNING  : call setArray() after array contents modification
976 //           in order to assure Undo work
977 //=======================================================================
978
979 Handle(TColStd_HArray1OfInteger) TObj_Object::getIntegerArray
980                         (const Standard_Integer theLength,
981                          const Standard_Integer theRank1,
982                          const Standard_Integer theRank2,
983                          const Standard_Integer theInitialValue) const
984 {
985   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
986   Handle(TDataStd_IntegerArray) anArrAttribute;
987   if (!aLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anArrAttribute))
988     if ( theLength > 0 )
989     {
990       anArrAttribute = TDataStd_IntegerArray::Set (aLabel, 1, theLength);
991       anArrAttribute->Array()->Init( theInitialValue );
992     }
993   Handle(TColStd_HArray1OfInteger) anArr;
994   if ( !anArrAttribute.IsNull() )
995     anArr = anArrAttribute->Array();
996   return anArr;
997 }
998
999 //=======================================================================
1000 //function : getExtStringArray
1001 //purpose  : Returns an existing or create a new string array on theRank2-th
1002 //           sublabel of theRank1-th sublabel of the Data label of the object.
1003 //           If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel).
1004 //           A newly created array has 1 and theLength bounds
1005 //           NOTE: new created array is NOT initialized.
1006 //WARNING  : call setArray() after array contents modification
1007 //           in order to assure Undo work
1008 //=======================================================================
1009
1010 Handle(TColStd_HArray1OfExtendedString) TObj_Object::getExtStringArray
1011                         (const Standard_Integer theLength,
1012                          const Standard_Integer theRank1,
1013                          const Standard_Integer theRank2) const
1014 {
1015   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
1016   Handle(TDataStd_ExtStringArray) anArrAttribute;
1017   if (!aLabel.FindAttribute(TDataStd_ExtStringArray::GetID(), anArrAttribute))
1018     if ( theLength > 0 )
1019       anArrAttribute = TDataStd_ExtStringArray::Set (aLabel, 1, theLength);
1020
1021   Handle(TColStd_HArray1OfExtendedString) anArr;
1022   if ( !anArrAttribute.IsNull() )
1023     anArr = anArrAttribute->Array();
1024   return anArr;
1025 }
1026
1027 //=======================================================================
1028 //function : setArray
1029 //purpose  : Store theArray on theRank2-th sublabel of theRank1-th sublabel
1030 //           of the Data label of the object.
1031 //           If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel).
1032 //=======================================================================
1033
1034 void TObj_Object::setArray (const Handle(TColStd_HArray1OfReal)& theArray,
1035                                 const Standard_Integer theRank1,
1036                                 const Standard_Integer theRank2)
1037 {
1038   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
1039   Handle(TDataStd_RealArray) anArrAttribute;
1040   if (!aLabel.FindAttribute(TDataStd_RealArray::GetID(), anArrAttribute) &&
1041       !theArray.IsNull())
1042     anArrAttribute = TDataStd_RealArray::Set (aLabel, 1, 1);
1043
1044   if (theArray.IsNull()) {
1045     // deletion mode 
1046     if (!anArrAttribute.IsNull())
1047       aLabel.ForgetAttribute(anArrAttribute);
1048     return;
1049   }
1050
1051   if (anArrAttribute->Array() == theArray)
1052     // Backup wont happen but we want it
1053     anArrAttribute->Init(1,1);
1054
1055   anArrAttribute->ChangeArray( theArray );
1056 }
1057
1058 //=======================================================================
1059 //function : setArray
1060 //purpose  : Store theArray on theRank2-th sublabel of theRank1-th sublabel
1061 //           of the Data label of the object.
1062 //           If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel).
1063 //=======================================================================
1064
1065 void TObj_Object::setArray (const Handle(TColStd_HArray1OfInteger)& theArray,
1066                                 const Standard_Integer theRank1,
1067                                 const Standard_Integer theRank2)
1068 {
1069   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
1070   Handle(TDataStd_IntegerArray) anArrAttribute;
1071   if (!aLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anArrAttribute) &&
1072       !theArray.IsNull())
1073     anArrAttribute = TDataStd_IntegerArray::Set (aLabel, 1, 1);
1074
1075   if (theArray.IsNull()) {
1076     // deletion mode 
1077     if (!anArrAttribute.IsNull())
1078       aLabel.ForgetAttribute(anArrAttribute);
1079     return;
1080   }
1081
1082   if (anArrAttribute->Array() == theArray)
1083     // Backup wont happen but we want it
1084     anArrAttribute->Init(1,1);
1085
1086   anArrAttribute->ChangeArray( theArray );
1087 }
1088
1089 //=======================================================================
1090 //function : setArray
1091 //purpose  : Store theArray on theRank2-th sublabel of theRank1-th sublabel
1092 //           of the Data label of the object.
1093 //           If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel).
1094 //=======================================================================
1095
1096 void TObj_Object::setArray (const Handle(TColStd_HArray1OfExtendedString)& theArray,
1097                                 const Standard_Integer theRank1,
1098                                 const Standard_Integer theRank2)
1099 {
1100   TDF_Label aLabel = getDataLabel(theRank1,theRank2);
1101   Handle(TDataStd_ExtStringArray) anArrAttribute;
1102   if (!aLabel.FindAttribute(TDataStd_ExtStringArray::GetID(), anArrAttribute) &&
1103       !theArray.IsNull())
1104     anArrAttribute = TDataStd_ExtStringArray::Set (aLabel, 1, 1);
1105
1106   if (theArray.IsNull()) {
1107     // deletion mode 
1108     if (!anArrAttribute.IsNull())
1109       aLabel.ForgetAttribute(anArrAttribute);
1110     return;
1111   }
1112
1113   if (anArrAttribute->Array() == theArray)
1114     // Backup wont happen but we want it
1115     anArrAttribute->Init(1,1);
1116
1117   anArrAttribute->ChangeArray( theArray );
1118 }
1119
1120 //=======================================================================
1121 //function : copyTagSources
1122 //purpose  : copy TagSource attributes on label and its sublabels
1123 //=======================================================================
1124
1125 static void copyTagSources (const TDF_Label& theSourceLabel, const TDF_Label& theTargetLabel)
1126 {
1127   // copy tag source on current label
1128   Handle(TDF_Attribute) anAttr;
1129   if(theSourceLabel.FindAttribute(TDF_TagSource::GetID(), anAttr))
1130   {
1131     Handle(TDF_TagSource) aTagSource = Handle(TDF_TagSource)::DownCast(anAttr);
1132     Handle(TDF_TagSource) aTargetTagSource = TDF_TagSource::Set(theTargetLabel);
1133     aTargetTagSource->Set(aTagSource->Get());
1134   }
1135
1136   // copy recursively to sub-labels; note that iteration is made by target label,
1137   // to avoid copying tag sources where data are not copied
1138   TDF_ChildIterator aLI(theTargetLabel);
1139   for(; aLI.More(); aLI.Next())
1140   {
1141     TDF_Label aSourceLabel = theSourceLabel.FindChild(aLI.Value().Tag(), Standard_False);
1142     if (! aSourceLabel.IsNull())
1143       copyTagSources (aSourceLabel, aLI.Value());
1144   }
1145 }
1146
1147 //=======================================================================
1148 //function : Clone
1149 //purpose  :
1150 //=======================================================================
1151
1152 Handle(TObj_Object) TObj_Object::Clone
1153        (const TDF_Label&            theTargetLabel,
1154         Handle(TDF_RelocationTable) theRelocTable)
1155 {
1156   Handle(TDF_RelocationTable) aRelocTable = theRelocTable;
1157   if (theRelocTable.IsNull())
1158     aRelocTable = new TDF_RelocationTable;
1159   Handle(TObj_Object) aNewObj;
1160   // take current model for restoring it after creating object.
1161   const Handle(TObj_Model)& aCurrentModel = TObj_Assistant::GetCurrentModel();
1162
1163   // take target model
1164   Handle(TObj_Model) aTargetModel;
1165   TDF_Label aLabel = TDocStd_Document::Get(theTargetLabel)->Main();
1166   Handle(TObj_TModel) aModelAttr;
1167   if (aLabel.FindAttribute(TObj_TModel::GetID(), aModelAttr))
1168     aTargetModel = aModelAttr->Model();
1169
1170   if (aCurrentModel != aTargetModel)
1171     TObj_Assistant::SetCurrentModel (aTargetModel);
1172   // crete new object
1173   aNewObj = TObj_Persistence::CreateNewObject (DynamicType()->Name(), theTargetLabel);
1174
1175   if (!aNewObj.IsNull())
1176   {
1177     TObj_TObject::Set(theTargetLabel,aNewObj);
1178
1179     // adding a record to the reloation table
1180     aRelocTable->SetRelocation(GetLabel(), theTargetLabel);
1181
1182     // now set name of object.
1183     const Handle(TCollection_HExtendedString) aCloneName = GetNameForClone( aNewObj );
1184     if( !aCloneName.IsNull() && !aCloneName->IsEmpty() )
1185       aNewObj->SetName( new TCollection_HExtendedString( aCloneName ) );
1186
1187     // copy the data
1188     copyData (aNewObj);
1189
1190     // copy children
1191     TDF_Label aTargetLabel = aNewObj->GetChildLabel();
1192     CopyChildren(aTargetLabel, aRelocTable);
1193
1194     // copy TagSource for the children
1195     copyTagSources (GetChildLabel(), aTargetLabel);
1196
1197     // copy the references
1198     if(theRelocTable.IsNull())
1199       CopyReferences(aNewObj, aRelocTable);
1200   }
1201
1202   // restore the model for persistence.
1203   if (aCurrentModel != aTargetModel)
1204     TObj_Assistant::SetCurrentModel (aCurrentModel);
1205
1206   return aNewObj;
1207 }
1208
1209 //=======================================================================
1210 //function : copyData
1211 //purpose  : protected
1212 //=======================================================================
1213
1214 Standard_Boolean TObj_Object::copyData
1215                 (const Handle(TObj_Object)& theTargetObject)
1216 {
1217   Standard_Boolean IsDone = Standard_False;
1218   if ( !theTargetObject->DynamicType()->SubType( DynamicType() ) )
1219     return IsDone;
1220   // init the copier by labels.
1221   TDF_Label aDataLabel = GetDataLabel();
1222   TDF_Label aNewDataLabel = theTargetObject->GetDataLabel();
1223   // check if object has any data.
1224   if (aDataLabel.IsNull() || aNewDataLabel.IsNull())
1225     return IsDone;
1226
1227   TDF_CopyLabel aCopier(aDataLabel, aNewDataLabel);
1228   aCopier.Perform();
1229
1230   return aCopier.IsDone();
1231 }
1232
1233 //=======================================================================
1234 //function : CopyChildren
1235 //purpose  :
1236 //=======================================================================
1237
1238 void TObj_Object::CopyChildren
1239                 (TDF_Label&                         theTargetLabel,
1240                  const Handle(TDF_RelocationTable)& theRelocTable)
1241 {
1242   TDF_Label aSourceChildLabel = GetChildLabel();
1243   Handle(TObj_ObjectIterator) aChildren = // GetChildren();
1244     new TObj_OcafObjectIterator (aSourceChildLabel, NULL, Standard_True); // to support children on sublabels of child label
1245   for(;aChildren->More(); aChildren->Next())
1246   {
1247     Handle(TObj_Object) aChild = aChildren->Value();
1248     if(!aChild.IsNull())
1249     {
1250       // to support childs on sublabels of sublabel of child label
1251       TColStd_SequenceOfInteger aTags;
1252       TDF_Label aCurChildLab = aChild->GetLabel();
1253       while ( !aCurChildLab.IsNull() && aCurChildLab != aSourceChildLabel )
1254       {
1255         aTags.Append( aCurChildLab.Tag() );
1256         aCurChildLab = aCurChildLab.Father();
1257       }
1258       TDF_Label aChildLabel = theTargetLabel;
1259       for ( Standard_Integer i = aTags.Length(); i > 0 ; i-- )
1260         aChildLabel = aChildLabel.FindChild( aTags.Value( i ), Standard_True );
1261
1262       aChild->Clone(aChildLabel, theRelocTable);
1263     }
1264   }
1265 }
1266
1267 //=======================================================================
1268 //function : CopyReferences
1269 //purpose  :
1270 //=======================================================================
1271
1272 void TObj_Object::CopyReferences
1273                 (const Handle(TObj_Object)& theTargetObject,
1274                  const Handle(TDF_RelocationTable)& theRelocTable)
1275 {
1276   // recursive copy of references
1277   Handle(TObj_ObjectIterator) aSrcChildren = //GetChildren();
1278   // to support childs on sublabels of sublabel of child label
1279    new TObj_OcafObjectIterator(GetChildLabel(), NULL, Standard_True);
1280   for(; aSrcChildren->More(); aSrcChildren->Next())
1281   {
1282     Handle(TObj_Object) aSrcChild = aSrcChildren->Value();
1283     TDF_Label aSrcL = aSrcChild->GetLabel();
1284     TDF_Label aDestLabel;
1285     if( !theRelocTable->HasRelocation(aSrcL, aDestLabel) )
1286       continue;
1287     Handle(TObj_Object) aDstChild;
1288     if ( !TObj_Object::GetObj( aDestLabel, aDstChild ) )
1289       continue;
1290     if ( aDstChild.IsNull() || !aDstChild->IsAlive() || aSrcChild->DynamicType() != aDstChild->DynamicType() )
1291       continue; // should not be with relocation table
1292
1293     aSrcChild->CopyReferences(aDstChild, theRelocTable);
1294   }
1295   // copy of my references
1296   theTargetObject->GetReferenceLabel().ForgetAllAttributes(Standard_True);
1297
1298   TDF_Label aTargetLabel = theTargetObject->GetReferenceLabel();
1299   copyReferences(GetReferenceLabel(), aTargetLabel, theRelocTable);
1300 }
1301
1302 //=======================================================================
1303 //function : copyReferences
1304 //purpose  : protected
1305 //=======================================================================
1306
1307 void TObj_Object::copyReferences
1308                          (const TDF_Label&                   theSourceLabel,
1309                           TDF_Label&                         theTargetLabel,
1310                           const Handle(TDF_RelocationTable)& theRelocTable)
1311 {
1312   TDF_AttributeIterator anIter(theSourceLabel);
1313   for(; anIter.More(); anIter.Next())
1314   {
1315     Handle(TDF_Attribute) anAttr = anIter.Value()->NewEmpty();
1316     theTargetLabel.AddAttribute(anAttr);
1317     anIter.Value()->Paste(anAttr, theRelocTable);
1318
1319   }
1320   TDF_ChildIterator aLI(theSourceLabel);
1321   TDF_Label aTargetLabel;
1322   for(; aLI.More(); aLI.Next())
1323   {
1324     aTargetLabel = theTargetLabel.FindChild(aLI.Value().Tag(), Standard_True);
1325     copyReferences(aLI.Value(), aTargetLabel, theRelocTable);
1326   }
1327 }
1328
1329 //=======================================================================
1330 //function : ReplaceReference
1331 //purpose  :
1332 //=======================================================================
1333
1334 void TObj_Object::ReplaceReference (const Handle(TObj_Object)& theOldObject,
1335                                         const Handle(TObj_Object)& theNewObject)
1336 {
1337   Handle(TObj_LabelIterator) anItr =
1338     Handle(TObj_LabelIterator)::DownCast( GetReferences() );
1339   if (anItr.IsNull())
1340     return;
1341   // iterates on references.
1342   for (; anItr->More(); anItr->Next() )
1343   {
1344     Handle(TObj_Object) anObj = anItr->Value();
1345     if (anObj != theOldObject)
1346       continue;
1347
1348     TDF_Label aRefLabel = anItr->LabelValue();
1349     // if new object is null then simple remove reference.
1350     if (theNewObject.IsNull())
1351     {
1352       aRefLabel.ForgetAllAttributes();
1353       break;
1354     }
1355     // set reference to new object.
1356     Handle(TObj_Object) me = this;
1357     TObj_TReference::Set ( aRefLabel, theNewObject, me);
1358     break;
1359   }
1360 }
1361
1362 //=======================================================================
1363 //function : IsAlive
1364 //purpose  :
1365 //=======================================================================
1366
1367 Standard_Boolean TObj_Object::IsAlive() const
1368 {
1369   if (myLabel.IsNull())
1370     return Standard_False;
1371
1372   Handle(TObj_Object) anObj;
1373   if ( !GetObj( myLabel, anObj ) )
1374     return Standard_False;
1375
1376   return Standard_True;
1377 }
1378
1379 //=======================================================================
1380 //function : GetFlags
1381 //purpose  :
1382 //=======================================================================
1383
1384 Standard_Integer TObj_Object::GetFlags() const
1385 {
1386   return getInteger(DataTag_Flags);
1387 }
1388
1389 //=======================================================================
1390 //function : SetFlags
1391 //purpose  :
1392 //=======================================================================
1393
1394 void TObj_Object::SetFlags(const Standard_Integer theMask)
1395 {
1396   Standard_Integer aFlags = getInteger(DataTag_Flags);
1397   aFlags = aFlags | theMask;
1398   setInteger(aFlags, DataTag_Flags);
1399 }
1400
1401 //=======================================================================
1402 //function : TestFlags
1403 //purpose  :
1404 //=======================================================================
1405
1406 Standard_Boolean TObj_Object::TestFlags(const Standard_Integer theMask) const
1407 {
1408   Standard_Integer aFlags = getInteger(DataTag_Flags);
1409   return (aFlags & theMask) != 0;
1410 }
1411
1412 //=======================================================================
1413 //function : ClearFlags
1414 //purpose  :
1415 //=======================================================================
1416
1417 void TObj_Object::ClearFlags(const Standard_Integer theMask)
1418 {
1419   Standard_Integer aFlags = getInteger(DataTag_Flags);
1420   aFlags = aFlags & (~theMask);
1421   setInteger(aFlags, DataTag_Flags);
1422 }
1423
1424 //=======================================================================
1425 //function : RemoveBackReferences
1426 //purpose  :
1427 //=======================================================================
1428
1429 Standard_Boolean TObj_Object::RemoveBackReferences(const TObj_DeletingMode theMode)
1430 {
1431   Handle(TObj_ObjectIterator) aRefs = GetBackReferences();
1432
1433   // Free Object can be deleted in any Mode
1434   if ( aRefs.IsNull() || !aRefs->More()) return Standard_True;
1435
1436   if( theMode == TObj_FreeOnly) return Standard_False;
1437
1438   // Defining the sequence of objects which are referenced to this one. The
1439   // first sequence stores containers the second one object with strong
1440   // relation.
1441   TObj_SequenceOfObject aContainers;
1442   TObj_SequenceOfObject aStrongs;
1443   Handle(TObj_Object) aMe = this;
1444
1445   // Sorting the referencing objects
1446   for( ; aRefs->More() ; aRefs->Next())
1447   {
1448     Handle(TObj_Object) anObject = aRefs->Value();
1449     if ( anObject.IsNull() || !anObject->IsAlive() )
1450       continue;
1451     if ( anObject->CanRemoveReference(aMe) )
1452       aContainers.Append(anObject);
1453     else
1454       aStrongs.Append(anObject);
1455   }
1456   // Can not be removed without deletion of referenced objects mode
1457   if( theMode == TObj_KeepDepending && aStrongs.Length() > 0 )
1458     return Standard_False;
1459   // Delete or link off the referencing objects
1460   Standard_Integer i;
1461   Handle(TDF_Data) anOwnData = GetLabel().Data();
1462   for (i = 1; i <= aContainers.Length(); i++)
1463   {
1464     Handle(TObj_Object) anObj = aContainers(i);
1465     if ( anObj.IsNull() || anObj->GetLabel().IsNull() )
1466       continue; // undead object on dead label
1467     Handle(TDF_Data) aData = anObj->GetLabel().Data();
1468     Standard_Boolean aModifMode = aData->IsModificationAllowed();
1469     if ( anOwnData != aData )
1470       aData->AllowModification( Standard_True );
1471     anObj->RemoveReference(aMe);
1472     if ( anOwnData != aData )
1473       aData->AllowModification( aModifMode );
1474   }
1475   /* PTv 21.11.2006
1476   object from other document refers to current object and must be killed
1477   when current object become dead for just want to remove references to it
1478   if ( theMode != TObj_Forced ) // cause leads to exception when
1479     // try to remove objects during close document
1480   */
1481   for (i = 1; i <= aStrongs.Length(); i++)
1482   {
1483     Handle(TObj_Object) anObj = aStrongs(i);
1484     if ( anObj.IsNull() || anObj->GetLabel().IsNull() )
1485       continue; // undead object on dead label
1486     Handle(TDF_Data) aData = anObj->GetLabel().Data();
1487     Standard_Boolean aModifMode = aData->IsModificationAllowed();
1488     if ( anOwnData != aData )
1489       aData->AllowModification( Standard_True );
1490     anObj->Detach(theMode);
1491     if ( anOwnData != aData )
1492       aData->AllowModification( aModifMode );
1493   }
1494
1495   return Standard_True;
1496 }
1497
1498 //=======================================================================
1499 //function : RelocateReferences
1500 //purpose  : Make that each reference pointing to a descendant label of
1501 //           theFromRoot to point to an equivalent label under theToRoot.
1502 //           Return False if a resulting reference does not point to
1503 //           an TObj_Object
1504 //Example  :
1505 //           a referred object label = 0:3:24:7:2:7
1506 //           theFromRoot             = 0:3:24
1507 //           theToRoot               = 0:2
1508 //           a new referred label    = 0:2:7:2:7
1509 //=======================================================================
1510
1511 Standard_Boolean TObj_Object::RelocateReferences
1512                          (const TDF_Label&       theFromRoot,
1513                           const TDF_Label&       theToRoot,
1514                           const Standard_Boolean theUpdateBackRefs)
1515 {
1516   TDF_ChildIDIterator aRefIt (GetReferenceLabel(),
1517                               TObj_TReference::GetID(),
1518                               Standard_True );
1519   Handle(TObj_Object) anObj;
1520   for (  ; aRefIt.More(); aRefIt.Next() )
1521   {
1522     Handle(TObj_TReference) aRef =
1523       Handle(TObj_TReference)::DownCast( aRefIt.Value() );
1524
1525     TDF_Label aNewLabel, aLabel = aRef->GetLabel();
1526     if ( aLabel.Data() != theFromRoot.Data() ||
1527          aLabel.IsDescendant( theToRoot ))
1528       continue; // need not to relocate
1529
1530     TDF_Tool::RelocateLabel( aLabel, theFromRoot, theToRoot, aNewLabel );
1531     if ( aNewLabel.IsNull() || !TObj_Object::GetObj( aNewLabel, anObj ))
1532       return Standard_False;
1533
1534     // care of back references
1535     if (theUpdateBackRefs)
1536     {
1537       Handle(TObj_Object) me = this;
1538       // a new referred object
1539       anObj->AddBackReference( me );
1540       // an old object
1541       anObj = aRef->Get();
1542       if (!anObj.IsNull())
1543         anObj->RemoveBackReference( me );
1544     }
1545
1546     aRef->Set( aNewLabel, aRef->GetMasterLabel() );
1547   }
1548
1549   return Standard_True;
1550 }
1551
1552 //=======================================================================
1553 //function : GetBadReference
1554 //purpose  : 
1555 //=======================================================================
1556
1557 Standard_Boolean TObj_Object::GetBadReference
1558                          (const TDF_Label& theRoot,
1559                           TDF_Label&       theBadReference) const
1560 {
1561   TDF_ChildIDIterator aRefIt (GetReferenceLabel(),
1562                               TObj_TReference::GetID(),
1563                               Standard_True );
1564   Handle(TObj_Object) anObj;
1565   for (  ; aRefIt.More(); aRefIt.Next() )
1566   {
1567     Handle(TObj_TReference) aRef =
1568       Handle(TObj_TReference)::DownCast( aRefIt.Value() );
1569
1570     TDF_Label aLabel = aRef->GetLabel();
1571     if ( aLabel.Data() == theRoot.Data() &&
1572          !aLabel.IsDescendant( theRoot ))
1573     {
1574       theBadReference = aLabel;
1575       return Standard_True;
1576     }
1577   }
1578
1579   return Standard_False;
1580 }
1581
1582 //=======================================================================
1583 //function : TypeFlags
1584 //purpose  : 
1585 //=======================================================================
1586
1587 Standard_Integer TObj_Object::GetTypeFlags() const
1588 {
1589   return Visible;
1590 }
1591
1592 //=======================================================================
1593 //function : GetDictionary
1594 //purpose  : default implementation
1595 //=======================================================================
1596
1597 Handle(TObj_TNameContainer) TObj_Object::GetDictionary() const
1598 {
1599   Handle(TObj_Model) aModel = GetModel();
1600   if ( !aModel.IsNull() )
1601     return aModel->GetDictionary();
1602   return NULL; 
1603 }
1604
1605 //=======================================================================
1606 //function : SetOrder
1607 //purpose  :
1608 //=======================================================================
1609
1610 Standard_Boolean TObj_Object::SetOrder( const Standard_Integer& theIndx )
1611
1612   setInteger( theIndx, DataTag_Order );
1613   return Standard_True;
1614 }
1615
1616 //=======================================================================
1617 //function : GetOrder
1618 //purpose  :
1619 //=======================================================================
1620
1621 Standard_Integer TObj_Object::GetOrder() const
1622 {
1623   Standard_Integer order = getInteger( DataTag_Order );
1624   if ( !order )
1625     order = GetLabel().Tag();
1626   return order;
1627 }