0027104: DownCast() cannot return null for mismatched handle
[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,MMgt_TShared)
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 : Clone
1122 //purpose  : method.
1123 //=======================================================================
1124
1125 Handle(TObj_Object) TObj_Object::Clone
1126        (const TDF_Label&            theTargetLabel,
1127         Handle(TDF_RelocationTable) theRelocTable)
1128 {
1129   Handle(TDF_RelocationTable) aRelocTable = theRelocTable;
1130   if (theRelocTable.IsNull())
1131     aRelocTable = new TDF_RelocationTable;
1132   Handle(TObj_Object) aNewObj;
1133   // take current model for restoring it after creating object.
1134   const Handle(TObj_Model)& aCurrentModel = TObj_Assistant::GetCurrentModel();
1135
1136   // take target model
1137   Handle(TObj_Model) aTargetModel;
1138   TDF_Label aLabel = TDocStd_Document::Get(theTargetLabel)->Main();
1139   Handle(TObj_TModel) aModelAttr;
1140   if (aLabel.FindAttribute(TObj_TModel::GetID(), aModelAttr))
1141     aTargetModel = aModelAttr->Model();
1142
1143   if (aCurrentModel != aTargetModel)
1144     TObj_Assistant::SetCurrentModel (aTargetModel);
1145   // crete new object
1146   aNewObj = TObj_Persistence::CreateNewObject (DynamicType()->Name(), theTargetLabel);
1147
1148   if (!aNewObj.IsNull())
1149   {
1150     TObj_TObject::Set(theTargetLabel,aNewObj);
1151
1152     // adding a record to the reloation table
1153     aRelocTable->SetRelocation(GetLabel(), theTargetLabel);
1154
1155     // now set name of object.
1156     const Handle(TCollection_HExtendedString) aCloneName = GetNameForClone( aNewObj );
1157     if( !aCloneName.IsNull() && !aCloneName->IsEmpty() )
1158       aNewObj->SetName( new TCollection_HExtendedString( aCloneName ) );
1159
1160     // copy the data
1161     copyData (aNewObj);
1162
1163     // copy the references
1164     // changed by van // copyReferences (aNewObj);
1165     // references have to be coped after coping all objects and models
1166
1167     TDF_Label aTargetLabel = aNewObj->GetChildLabel();
1168     CopyChildren(aTargetLabel, aRelocTable);
1169
1170     // copy TagSource for the children
1171     TDF_Label aChildLabel = GetChildLabel();
1172     Handle(TDF_Attribute) anAttr;
1173     if(aChildLabel.FindAttribute(TDF_TagSource::GetID(), anAttr))
1174     {
1175       Handle(TDF_TagSource) aTagSource = Handle(TDF_TagSource)::DownCast(anAttr);
1176       Handle(TDF_TagSource) aTargetTagSource = TDF_TagSource::Set(aTargetLabel);
1177       aTargetTagSource->Set(aTagSource->Get());
1178     }
1179
1180     if(theRelocTable.IsNull())
1181       CopyReferences(aNewObj, aRelocTable);
1182   }
1183
1184   // restore the model for persistence.
1185   if (aCurrentModel != aTargetModel)
1186     TObj_Assistant::SetCurrentModel (aCurrentModel);
1187
1188   return aNewObj;
1189 }
1190
1191 //=======================================================================
1192 //function : copyData
1193 //purpose  : protected
1194 //=======================================================================
1195
1196 Standard_Boolean TObj_Object::copyData
1197                 (const Handle(TObj_Object)& theTargetObject)
1198 {
1199   Standard_Boolean IsDone = Standard_False;
1200   if ( !theTargetObject->DynamicType()->SubType( DynamicType() ) )
1201     return IsDone;
1202   // init the copier by labels.
1203   TDF_Label aDataLabel = GetDataLabel();
1204   TDF_Label aNewDataLabel = theTargetObject->GetDataLabel();
1205   // check if object has any data.
1206   if (aDataLabel.IsNull() || aNewDataLabel.IsNull())
1207     return IsDone;
1208
1209   TDF_CopyLabel aCopier(aDataLabel, aNewDataLabel);
1210   aCopier.Perform();
1211
1212   return aCopier.IsDone();
1213 }
1214
1215 //=======================================================================
1216 //function : CopyChildren
1217 //purpose  :
1218 //=======================================================================
1219
1220 void TObj_Object::CopyChildren
1221                 (TDF_Label&                         theTargetLabel,
1222                  const Handle(TDF_RelocationTable)& theRelocTable)
1223 {
1224   Handle(TObj_ObjectIterator) aChildren = /*TObj_Object::*/GetChildren();
1225   // to support childs on sublabels of sublabel of child label
1226   //new TObj_ObjectIterator(GetChildLabel(), NULL, Standard_True);
1227   TDF_Label aSourceChildLabel = GetChildLabel();
1228   for(;aChildren->More(); aChildren->Next())
1229   {
1230     Handle(TObj_Object) aChild = aChildren->Value();
1231     if(!aChild.IsNull())
1232     {
1233       /* only for one sub level of children 
1234       TDF_Label aChildLabel =
1235        theTargetLabel.FindChild(aChild->GetLabel().Tag(), Standard_True);
1236       aChild->Clone(aChildLabel, theRelocTable);
1237       // to support childs on sublabels of sublabel of child label
1238       */
1239       // to support childs on sublabels of sublabel of child label
1240       TColStd_SequenceOfInteger aTags;
1241       TDF_Label aCurChildLab = aChild->GetLabel();
1242       while ( !aCurChildLab.IsNull() && aCurChildLab != aSourceChildLabel )
1243       {
1244         aTags.Append( aCurChildLab.Tag() );
1245         aCurChildLab = aCurChildLab.Father();
1246       }
1247       TDF_Label aChildLabel = theTargetLabel;
1248       for ( Standard_Integer i = aTags.Length(); i > 0 ; i-- )
1249         aChildLabel = aChildLabel.FindChild( aTags.Value( i ), Standard_True );
1250
1251       aChild->Clone(aChildLabel, theRelocTable);
1252     }
1253   }
1254 }
1255
1256 //=======================================================================
1257 //function : CopyReferences
1258 //purpose  :
1259 //=======================================================================
1260
1261 void TObj_Object::CopyReferences
1262                 (const Handle(TObj_Object)& theTargetObject,
1263                  const Handle(TDF_RelocationTable)& theRelocTable)
1264 {
1265   // recursive copy of references
1266   Handle(TObj_ObjectIterator) aSrcChildren = //GetChildren();
1267   // to support childs on sublabels of sublabel of child label
1268    new TObj_OcafObjectIterator(GetChildLabel(), NULL, Standard_True);
1269   for(; aSrcChildren->More(); aSrcChildren->Next())
1270   {
1271     Handle(TObj_Object) aSrcChild = aSrcChildren->Value();
1272     TDF_Label aSrcL = aSrcChild->GetLabel();
1273     TDF_Label aDestLabel;
1274     if( !theRelocTable->HasRelocation(aSrcL, aDestLabel) )
1275       continue;
1276     Handle(TObj_Object) aDstChild;
1277     if ( !TObj_Object::GetObj( aDestLabel, aDstChild ) )
1278       continue;
1279     if ( aDstChild.IsNull() || !aDstChild->IsAlive() || aSrcChild->DynamicType() != aDstChild->DynamicType() )
1280       continue; // should not be with relocation table
1281
1282     aSrcChild->CopyReferences(aDstChild, theRelocTable);
1283   }
1284   // copy of my references
1285   theTargetObject->GetReferenceLabel().ForgetAllAttributes(Standard_True);
1286
1287   TDF_Label aTargetLabel = theTargetObject->GetReferenceLabel();
1288   copyReferences(GetReferenceLabel(), aTargetLabel, theRelocTable);
1289 }
1290
1291 //=======================================================================
1292 //function : copyReferences
1293 //purpose  : protected
1294 //=======================================================================
1295
1296 void TObj_Object::copyReferences
1297                          (const TDF_Label&                   theSourceLabel,
1298                           TDF_Label&                         theTargetLabel,
1299                           const Handle(TDF_RelocationTable)& theRelocTable)
1300 {
1301   TDF_AttributeIterator anIter(theSourceLabel);
1302   for(; anIter.More(); anIter.Next())
1303   {
1304     Handle(TDF_Attribute) anAttr = anIter.Value()->NewEmpty();
1305     theTargetLabel.AddAttribute(anAttr);
1306     anIter.Value()->Paste(anAttr, theRelocTable);
1307
1308   }
1309   TDF_ChildIterator aLI(theSourceLabel);
1310   TDF_Label aTargetLabel;
1311   for(; aLI.More(); aLI.Next())
1312   {
1313     aTargetLabel = theTargetLabel.FindChild(aLI.Value().Tag(), Standard_True);
1314     copyReferences(aLI.Value(), aTargetLabel, theRelocTable);
1315   }
1316 }
1317
1318 //=======================================================================
1319 //function : ReplaceReference
1320 //purpose  :
1321 //=======================================================================
1322
1323 void TObj_Object::ReplaceReference (const Handle(TObj_Object)& theOldObject,
1324                                         const Handle(TObj_Object)& theNewObject)
1325 {
1326   Handle(TObj_LabelIterator) anItr =
1327     Handle(TObj_LabelIterator)::DownCast( GetReferences() );
1328   if (anItr.IsNull())
1329     return;
1330   // iterates on references.
1331   for (; anItr->More(); anItr->Next() )
1332   {
1333     Handle(TObj_Object) anObj = anItr->Value();
1334     if (anObj != theOldObject)
1335       continue;
1336
1337     TDF_Label aRefLabel = anItr->LabelValue();
1338     // if new object is null then simple remove reference.
1339     if (theNewObject.IsNull())
1340     {
1341       aRefLabel.ForgetAllAttributes();
1342       break;
1343     }
1344     // set reference to new object.
1345     Handle(TObj_Object) me = this;
1346     TObj_TReference::Set ( aRefLabel, theNewObject, me);
1347     break;
1348   }
1349 }
1350
1351 //=======================================================================
1352 //function : IsAlive
1353 //purpose  :
1354 //=======================================================================
1355
1356 Standard_Boolean TObj_Object::IsAlive() const
1357 {
1358   if (myLabel.IsNull())
1359     return Standard_False;
1360
1361   Handle(TObj_Object) anObj;
1362   if ( !GetObj( myLabel, anObj ) )
1363     return Standard_False;
1364
1365   return Standard_True;
1366 }
1367
1368 //=======================================================================
1369 //function : GetFlags
1370 //purpose  :
1371 //=======================================================================
1372
1373 Standard_Integer TObj_Object::GetFlags() const
1374 {
1375   return getInteger(DataTag_Flags);
1376 }
1377
1378 //=======================================================================
1379 //function : SetFlags
1380 //purpose  :
1381 //=======================================================================
1382
1383 void TObj_Object::SetFlags(const Standard_Integer theMask)
1384 {
1385   Standard_Integer aFlags = getInteger(DataTag_Flags);
1386   aFlags = aFlags | theMask;
1387   setInteger(aFlags, DataTag_Flags);
1388 }
1389
1390 //=======================================================================
1391 //function : TestFlags
1392 //purpose  :
1393 //=======================================================================
1394
1395 Standard_Boolean TObj_Object::TestFlags(const Standard_Integer theMask) const
1396 {
1397   Standard_Integer aFlags = getInteger(DataTag_Flags);
1398   return aFlags & theMask;
1399 }
1400
1401 //=======================================================================
1402 //function : ClearFlags
1403 //purpose  :
1404 //=======================================================================
1405
1406 void TObj_Object::ClearFlags(const Standard_Integer theMask)
1407 {
1408   Standard_Integer aFlags = getInteger(DataTag_Flags);
1409   aFlags = aFlags & (~theMask);
1410   setInteger(aFlags, DataTag_Flags);
1411 }
1412
1413 //=======================================================================
1414 //function : RemoveBackReferences
1415 //purpose  :
1416 //=======================================================================
1417
1418 Standard_Boolean TObj_Object::RemoveBackReferences(const TObj_DeletingMode theMode)
1419 {
1420   Handle(TObj_ObjectIterator) aRefs = GetBackReferences();
1421
1422   // Free Object can be deleted in any Mode
1423   if ( aRefs.IsNull() || !aRefs->More()) return Standard_True;
1424
1425   if( theMode == TObj_FreeOnly) return Standard_False;
1426
1427   // Defining the sequence of objects which are referenced to this one. The
1428   // first sequence stores containers the second one object with strong
1429   // relation.
1430   TObj_SequenceOfObject aContainers;
1431   TObj_SequenceOfObject aStrongs;
1432   Handle(TObj_Object) aMe = this;
1433
1434   // Sorting the referencing objects
1435   for( ; aRefs->More() ; aRefs->Next())
1436   {
1437     Handle(TObj_Object) anObject = aRefs->Value();
1438     if ( anObject.IsNull() || !anObject->IsAlive() )
1439       continue;
1440     if ( anObject->CanRemoveReference(aMe) )
1441       aContainers.Append(anObject);
1442     else
1443       aStrongs.Append(anObject);
1444   }
1445   // Can not be removed without deletion of referenced objects mode
1446   if( theMode == TObj_KeepDepending && aStrongs.Length() > 0 )
1447     return Standard_False;
1448   // Delete or link off the referencing objects
1449   Standard_Integer i;
1450   Handle(TDF_Data) anOwnData = GetLabel().Data();
1451   for (i = 1; i <= aContainers.Length(); i++)
1452   {
1453     Handle(TObj_Object) anObj = aContainers(i);
1454     if ( anObj.IsNull() || anObj->GetLabel().IsNull() )
1455       continue; // undead object on dead label
1456     Handle(TDF_Data) aData = anObj->GetLabel().Data();
1457     Standard_Boolean aModifMode = aData->IsModificationAllowed();
1458     if ( anOwnData != aData )
1459       aData->AllowModification( Standard_True );
1460     anObj->RemoveReference(aMe);
1461     if ( anOwnData != aData )
1462       aData->AllowModification( aModifMode );
1463   }
1464   /* PTv 21.11.2006
1465   object from other document refers to current object and must be killed
1466   when current object become dead for just want to remove references to it
1467   if ( theMode != TObj_Forced ) // cause leads to exception when
1468     // try to remove objects during close document
1469   */
1470   for (i = 1; i <= aStrongs.Length(); i++)
1471   {
1472     Handle(TObj_Object) anObj = aStrongs(i);
1473     if ( anObj.IsNull() || anObj->GetLabel().IsNull() )
1474       continue; // undead object on dead label
1475     Handle(TDF_Data) aData = anObj->GetLabel().Data();
1476     Standard_Boolean aModifMode = aData->IsModificationAllowed();
1477     if ( anOwnData != aData )
1478       aData->AllowModification( Standard_True );
1479     anObj->Detach(theMode);
1480     if ( anOwnData != aData )
1481       aData->AllowModification( aModifMode );
1482   }
1483
1484   return Standard_True;
1485 }
1486
1487 //=======================================================================
1488 //function : RelocateReferences
1489 //purpose  : Make that each reference pointing to a descendant label of
1490 //           theFromRoot to point to an equivalent label under theToRoot.
1491 //           Return False if a resulting reference does not point to
1492 //           an TObj_Object
1493 //Example  :
1494 //           a referred object label = 0:3:24:7:2:7
1495 //           theFromRoot             = 0:3:24
1496 //           theToRoot               = 0:2
1497 //           a new referred label    = 0:2:7:2:7
1498 //=======================================================================
1499
1500 Standard_Boolean TObj_Object::RelocateReferences
1501                          (const TDF_Label&       theFromRoot,
1502                           const TDF_Label&       theToRoot,
1503                           const Standard_Boolean theUpdateBackRefs)
1504 {
1505   TDF_ChildIDIterator aRefIt (GetReferenceLabel(),
1506                               TObj_TReference::GetID(),
1507                               Standard_True );
1508   Handle(TObj_Object) anObj;
1509   for (  ; aRefIt.More(); aRefIt.Next() )
1510   {
1511     Handle(TObj_TReference) aRef =
1512       Handle(TObj_TReference)::DownCast( aRefIt.Value() );
1513
1514     TDF_Label aNewLabel, aLabel = aRef->GetLabel();
1515     if ( aLabel.Data() != theFromRoot.Data() ||
1516          aLabel.IsDescendant( theToRoot ))
1517       continue; // need not to relocate
1518
1519     TDF_Tool::RelocateLabel( aLabel, theFromRoot, theToRoot, aNewLabel );
1520     if ( aNewLabel.IsNull() || !TObj_Object::GetObj( aNewLabel, anObj ))
1521       return Standard_False;
1522
1523     // care of back references
1524     if (theUpdateBackRefs)
1525     {
1526       Handle(TObj_Object) me = this;
1527       // a new referred object
1528       anObj->AddBackReference( me );
1529       // an old object
1530       anObj = aRef->Get();
1531       if (!anObj.IsNull())
1532         anObj->RemoveBackReference( me );
1533     }
1534
1535     aRef->Set( aNewLabel, aRef->GetMasterLabel() );
1536   }
1537
1538   return Standard_True;
1539 }
1540
1541 //=======================================================================
1542 //function : GetBadReference
1543 //purpose  : 
1544 //=======================================================================
1545
1546 Standard_Boolean TObj_Object::GetBadReference
1547                          (const TDF_Label& theRoot,
1548                           TDF_Label&       theBadReference) const
1549 {
1550   TDF_ChildIDIterator aRefIt (GetReferenceLabel(),
1551                               TObj_TReference::GetID(),
1552                               Standard_True );
1553   Handle(TObj_Object) anObj;
1554   for (  ; aRefIt.More(); aRefIt.Next() )
1555   {
1556     Handle(TObj_TReference) aRef =
1557       Handle(TObj_TReference)::DownCast( aRefIt.Value() );
1558
1559     TDF_Label aLabel = aRef->GetLabel();
1560     if ( aLabel.Data() == theRoot.Data() &&
1561          !aLabel.IsDescendant( theRoot ))
1562     {
1563       theBadReference = aLabel;
1564       return Standard_True;
1565     }
1566   }
1567
1568   return Standard_False;
1569 }
1570
1571 //=======================================================================
1572 //function : TypeFlags
1573 //purpose  : 
1574 //=======================================================================
1575
1576 Standard_Integer TObj_Object::GetTypeFlags() const
1577 {
1578   return Visible;
1579 }
1580
1581 //=======================================================================
1582 //function : GetDictionary
1583 //purpose  : default implementation
1584 //=======================================================================
1585
1586 Handle(TObj_TNameContainer) TObj_Object::GetDictionary() const
1587 {
1588   Handle(TObj_Model) aModel = GetModel();
1589   if ( !aModel.IsNull() )
1590     return aModel->GetDictionary();
1591   return NULL; 
1592 }
1593
1594 //=======================================================================
1595 //function : SetOrder
1596 //purpose  :
1597 //=======================================================================
1598
1599 Standard_Boolean TObj_Object::SetOrder( const Standard_Integer& theIndx )
1600
1601   setInteger( theIndx, DataTag_Order );
1602   return Standard_True;
1603 }
1604
1605 //=======================================================================
1606 //function : GetOrder
1607 //purpose  :
1608 //=======================================================================
1609
1610 Standard_Integer TObj_Object::GetOrder() const
1611 {
1612   Standard_Integer order = getInteger( DataTag_Order );
1613   if ( !order )
1614     order = GetLabel().Tag();
1615   return order;
1616 }