0031517: Data Exchange - wrong result of ShapeTool::UpdateAssemblies()
[occt.git] / src / XCAFDoc / XCAFDoc_ShapeTool.cxx
index 3a1d416..1d6677f 100644 (file)
@@ -13,6 +13,7 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <XCAFDoc_ShapeTool.hxx>
 
 #include <BRep_Builder.hxx>
 #include <gp_Pnt.hxx>
 #include <TopoDS_Compound.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <TopoDS_Shape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapOfOrientedShape.hxx>
 #include <XCAFDoc.hxx>
 #include <XCAFDoc_GraphNode.hxx>
 #include <XCAFDoc_Location.hxx>
 #include <XCAFDoc_ShapeMapTool.hxx>
-#include <XCAFDoc_ShapeTool.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(XCAFDoc_ShapeTool,TDF_Attribute)
 
@@ -148,7 +150,7 @@ static void SetLabelNameByLink(const TDF_Label L)
   if (! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ||
       ! Node->HasFather()) {
 #ifdef OCCT_DEBUG
-    cout<<"Error: XCAFDoc_ShapeTool, SetLabelNameByLink(): NO NODE"<<endl;
+    std::cout<<"Error: XCAFDoc_ShapeTool, SetLabelNameByLink(): NO NODE"<<std::endl;
 #endif
     return;
   }
@@ -302,20 +304,26 @@ Standard_Boolean XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S,
   if (TNaming_Tool::HasLabel(Label(), S0)) {
     int TransDef = 0;
     L = TNaming_Tool::Label(Label(), S0, TransDef);
-    return Standard_True;
   }
-/*
-  TDF_ChildIDIterator it(myLabel,TNaming_NamedShape::GetID());
+  else
+    return Standard_False;
+
+  if (IsTopLevel(L))
+    return Standard_True;
+
+  // Try to find shape manually
+  TDF_ChildIDIterator it(Label(), TNaming_NamedShape::GetID());
   for (; it.More(); it.Next()) {
     TDF_Label aLabel = it.Value()->Label();
     Handle(TNaming_NamedShape) NS;
     if ( aLabel.FindAttribute(TNaming_NamedShape::GetID(), NS) &&
-        S0.IsSame ( TNaming_Tool::GetShape(NS) ) ) {
+      S0.IsSame ( TNaming_Tool::GetShape(NS) ) ) {
       L = aLabel;
       return Standard_True;
     }
   }
-*/
+
+  L = TDF_Label();
   return Standard_False;
 }
 
@@ -328,8 +336,9 @@ TDF_Label XCAFDoc_ShapeTool::FindShape (const TopoDS_Shape& S,
                                     const Standard_Boolean findInstance) const
 {
   TDF_Label L;
-  FindShape ( S, L, findInstance );
-  return L;
+  if (FindShape(S, L, findInstance))
+    return L;
+  return TDF_Label();
 }
 
 //=======================================================================
@@ -402,32 +411,19 @@ TDF_Label XCAFDoc_ShapeTool::NewShape() const
 //=======================================================================
 
 void XCAFDoc_ShapeTool::SetShape (const TDF_Label& L, const TopoDS_Shape& S)
-{ 
-  if(IsReference(L) || !IsTopLevel(L) || /*IsAssembly(L) ||*/ !S.Location().IsIdentity())
-    return;
-
-  TDF_LabelSequence aSubShapes;
-  GetSubShapes(L, aSubShapes);
-
+{
   TNaming_Builder tnBuild(L);
   tnBuild.Generated(S);
   Handle(XCAFDoc_ShapeMapTool) A = XCAFDoc_ShapeMapTool::Set(L);
+//  if ( ! L.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) ) {
+//    A = XCAFDoc_ShapeMapTool::Set(L);
+//    L.AddAttribute(A);
+//  }
   A->SetShape(S);
 
-  for(Standard_Integer i = 1; i<=aSubShapes.Length(); i++)
-  {
-    TDF_Label aSubLabel = aSubShapes(i);
-    if (!IsSubShape(L, GetShape(aSubLabel)))
-    {
-      aSubLabel.ForgetAllAttributes();
-    }
-  }
-
   if(!myShapeLabels.IsBound(S)) {
     myShapeLabels.Bind(S,L);
   }
-
-  UpdateAssociatedAssembly(L);
 }
 
 //=======================================================================
@@ -943,7 +939,7 @@ Standard_Boolean XCAFDoc_ShapeTool::GetReferredShape (const TDF_Label& L,
 
 TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly, 
                                           const TDF_Label& compL, 
-                                          const TopLoc_Location &Loc) const
+                                          const TopLoc_Location &Loc)
 {
   TDF_Label L;
   
@@ -960,8 +956,14 @@ TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly,
   L = aTag.NewChild(assembly);
   MakeReference ( L, compL, Loc );
 
-  // update assembly`s TopoDS_Shape
-  UpdateAssembly ( assembly );
+  // map shape to label
+  TopoDS_Shape aShape;
+  if (GetShape(L, aShape))
+  {
+    if (!myShapeLabels.IsBound(aShape))
+      myShapeLabels.Bind(aShape, L);
+  }
+
   return L;
 }
 
@@ -992,73 +994,36 @@ TDF_Label XCAFDoc_ShapeTool::AddComponent (const TDF_Label& assembly,
 
 void XCAFDoc_ShapeTool::RemoveComponent (const TDF_Label& comp) const
 {
-  if ( IsComponent(comp) ) {
+  if ( IsComponent(comp) )
+  {
     comp.ForgetAllAttributes();
-    UpdateAssembly(comp.Father());
-  }
-}
-
-//=======================================================================
-//function : UpdateAssociatedAssembly
-//purpose  : 
-//=======================================================================
-
-void XCAFDoc_ShapeTool::UpdateAssociatedAssembly (const TDF_Label& L) const
-{
-  TDF_LabelSequence Labels;
-  if ( GetUsers ( L, Labels ) ) {
-    for ( Standard_Integer i=Labels.Length(); i >=1; i-- ) 
-    {
-      TDF_Label anAssemblyLabel = Labels(i).Father();
-      if(!anAssemblyLabel.IsNull())
-      {
-        UpdateAssembly(anAssemblyLabel);
-      }
-    }
   }
 }
 
 //=======================================================================
-//function : UpdateAssembly
+//function : UpdateAssemblies
 //purpose  : 
 //=======================================================================
 
-void XCAFDoc_ShapeTool::UpdateAssembly (const TDF_Label& L) const
+void XCAFDoc_ShapeTool::UpdateAssemblies()
 {
-  if ( ! IsAssembly(L) ) return;
+  // We start from the free shapes (roots in the assembly structure)
+  TDF_LabelSequence aRootLabels;
+  GetFreeShapes(aRootLabels);
 
-  BRep_Builder b;
-  TopoDS_Shape aShape = GetShape(L);
-  Standard_Boolean isFree = aShape.Free();
-  if (!isFree)
-    aShape.Free(Standard_True);
-
-  TopTools_SequenceOfShape aSubShapeSeq;
-  TopoDS_Iterator Iterator(aShape);
-  for (; Iterator.More(); Iterator.Next())
-    aSubShapeSeq.Append(Iterator.Value());
-
-  for (Standard_Integer i = 1; i <= aSubShapeSeq.Length(); i++) 
-    b.Remove(aShape, aSubShapeSeq.Value(i));
-
-  TDF_ChildIterator chldLabIt(L);
-  for (; chldLabIt.More(); chldLabIt.Next() ) {
-    TDF_Label subLabel = chldLabIt.Value();
-    if ( IsComponent ( subLabel ) ) {
-      b.Add(aShape, GetShape(subLabel));
+  // Iterate over the free shapes
+  TDF_LabelMap anUpdated;
+  for ( TDF_LabelSequence::Iterator anIt(aRootLabels); anIt.More(); anIt.Next() )
+  {
+    TDF_Label aRefLabel = anIt.Value();
+    if (IsReference(aRefLabel))
+    {
+      GetReferredShape(aRefLabel, aRefLabel);
     }
+    const TDF_Label& aRootLab = aRefLabel;
+    TopoDS_Shape anAssemblyShape;
+    updateComponent(aRootLab, anAssemblyShape, anUpdated);
   }
-
-  if (!isFree)
-    aShape.Free(Standard_False);
-
-  TNaming_Builder tnBuild(L);
-  tnBuild.Generated(aShape);
-
-  Handle(XCAFDoc_ShapeMapTool) A = XCAFDoc_ShapeMapTool::Set(L);
-  A->SetShape(aShape);
-
-  UpdateAssociatedAssembly(L);
 }
 
 //=======================================================================
@@ -1087,11 +1052,14 @@ Standard_Boolean XCAFDoc_ShapeTool::IsSubShape (const TDF_Label &shapeL,
                                             const TopoDS_Shape &sub) const
 {
   Handle(XCAFDoc_ShapeMapTool) A;
-  if ( ! shapeL.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A) )
-    return Standard_False;
-  
-  //TopoDS_Shape S = GetShape ( shapeL );
-  //return ! S.IsNull() && CheckSubShape ( S, sub );
+  if (!shapeL.FindAttribute(XCAFDoc_ShapeMapTool::GetID(), A))
+  {
+    TopoDS_Shape aShape = GetShape(shapeL);
+    if (aShape.IsNull())
+      return Standard_False;
+    A = XCAFDoc_ShapeMapTool::Set(shapeL);
+    A->SetShape(aShape);
+  }
   
   return A->IsSubShape(sub);
 }
@@ -1105,24 +1073,38 @@ Standard_Boolean XCAFDoc_ShapeTool::FindSubShape (const TDF_Label &shapeL,
                                                   const TopoDS_Shape &sub,
                                                   TDF_Label &L) const
 {
-  // this code is used instead of the following for performance reasons
-  if ( TNaming_Tool::HasLabel(Label(), sub) ) {
+  if (sub.IsNull())
+    return Standard_False;
+
+  if (TNaming_Tool::HasLabel(Label(), sub)) {
     int TransDef = 0;
     L = TNaming_Tool::Label(Label(), sub, TransDef);
-    return ( ! L.IsNull() && L.Father() == shapeL );
+    if (L.IsNull())
+      return Standard_False;
+    if (L.Father() == shapeL)
+      return Standard_True;
+  }
+  else
+  {
+    return Standard_False;
   }
 
-/*
-  TDF_ChildIterator chldLabIt(shapeL);
-  for (; chldLabIt.More(); chldLabIt.Next() ) {
-    TDF_Label subLabel = chldLabIt.Value();
-    TopoDS_Shape S;
-    if ( GetShape ( subLabel, S ) && S.IsSame ( sub ) ) {
-      L = subLabel;
+  // if subshape was found wrong, try to do it manually
+  // it can be possible if several part shapes has the same subshapes
+  L = TDF_Label();
+  TDF_ChildIterator aChldLabIt(shapeL);
+  for (; aChldLabIt.More(); aChldLabIt.Next() ) {
+    TDF_Label aSubLabel = aChldLabIt.Value();
+    Handle(TNaming_NamedShape) NS;
+    if (!aSubLabel.FindAttribute(TNaming_NamedShape::GetID(), NS))
+      continue;
+    TopoDS_Shape aSubShape = TNaming_Tool::GetShape(NS);
+    if (!aSubShape.IsNull() && aSubShape.IsSame(sub)) {
+      L = aSubLabel;
       return Standard_True;
     }
   }
-*/
+
   return Standard_False;
 }
 
@@ -1135,9 +1117,13 @@ TDF_Label XCAFDoc_ShapeTool::AddSubShape (const TDF_Label &shapeL,
                                           const TopoDS_Shape &sub) const
 {
   TDF_Label L;
+  if (!IsSimpleShape(shapeL) || !IsTopLevel(shapeL))
+    return L;
+
   if ( FindSubShape ( shapeL, sub, L ) ) return L;
   
-  if ( ! IsSubShape ( shapeL, sub ) ) return L;
+  if (!IsSubShape(shapeL, sub))
+    return TDF_Label();
   
   TDF_TagSource aTag;
   L = aTag.NewChild(shapeL);
@@ -1145,12 +1131,38 @@ TDF_Label XCAFDoc_ShapeTool::AddSubShape (const TDF_Label &shapeL,
   TNaming_Builder tnBuild(L);
   tnBuild.Generated(sub);
 
-//  if(!mySubShapes.IsBound(sub))
-//    mySubShapes.Bind(sub,L);
-   
   return L;
 }
 
+//=======================================================================
+//function : AddSubShape
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean XCAFDoc_ShapeTool::AddSubShape(const TDF_Label &shapeL,
+                                                const TopoDS_Shape &sub,
+                                                TDF_Label &addedSubShapeL) const
+{
+  addedSubShapeL = TDF_Label();
+  // Check if adding subshape is possible
+  if (!IsSimpleShape(shapeL) || !IsTopLevel(shapeL))
+    return Standard_False;
+
+  // Try to find already existed subshape
+  if (FindSubShape(shapeL, sub, addedSubShapeL))
+    return Standard_False;
+
+  if (!IsSubShape(shapeL, sub))
+    return Standard_False;
+
+  TDF_TagSource aTag;
+  addedSubShapeL = aTag.NewChild(shapeL);
+  TNaming_Builder tnBuild(addedSubShapeL);
+  tnBuild.Generated(sub);
+
+  return Standard_True;
+}
+
 
 //=======================================================================
 //function : FindMainShapeUsingMap
@@ -1180,7 +1192,8 @@ TDF_Label XCAFDoc_ShapeTool::FindMainShape (const TopoDS_Shape &sub) const
   TDF_ChildIterator it(Label());
   for (; it.More(); it.Next()) {
     TDF_Label L = it.Value();
-    if ( ! IsAssembly ( L ) && IsSubShape ( L, sub ) ) return L;
+
+    if ( IsSimpleShape( L ) && IsSubShape ( L, sub ) ) return L;
   }
   TDF_Label L0;
   return L0;
@@ -1266,7 +1279,7 @@ static void DumpAssembly(Standard_OStream& theDumpLog,
       theDumpLog<<", "<< *(void**)&S.Location();
     theDumpLog<<") ";
   }
-  theDumpLog<<endl;
+  theDumpLog<<std::endl;
   
   Handle(TDataStd_TreeNode) Node;
   TDF_ChildIterator NodeIterator(L);
@@ -1274,7 +1287,7 @@ static void DumpAssembly(Standard_OStream& theDumpLog,
     DumpAssembly(theDumpLog, NodeIterator.Value(), level+1, deep);
   }
   if(level == 0)
-    theDumpLog<<endl;
+    theDumpLog<<std::endl;
 }
 
 //=======================================================================
@@ -1282,14 +1295,14 @@ static void DumpAssembly(Standard_OStream& theDumpLog,
 //purpose  : 
 //=======================================================================
 
-void XCAFDoc_ShapeTool::Dump(Standard_OStream& theDumpLog, const Standard_Boolean deep) const
+Standard_OStream& XCAFDoc_ShapeTool::Dump(Standard_OStream& theDumpLog, const Standard_Boolean deep) const
 {
   Standard_Integer level = 0;
 //   TopTools_SequenceOfShape SeqShapes;
   TDF_LabelSequence SeqLabels;
   GetShapes( SeqLabels);
 
-  if (SeqLabels.Length()>0) theDumpLog<<endl;
+  if (SeqLabels.Length()>0) theDumpLog<<std::endl;
   Standard_Integer i;
   for (i=1; i<=SeqLabels.Length(); i++) {
     DumpAssembly(theDumpLog, SeqLabels.Value(i), level, deep);
@@ -1297,11 +1310,24 @@ void XCAFDoc_ShapeTool::Dump(Standard_OStream& theDumpLog, const Standard_Boolea
 
   SeqLabels.Clear();
   GetFreeShapes(SeqLabels);
-  theDumpLog<<endl<<"Free Shapes: "<<SeqLabels.Length()<<endl;
+  theDumpLog<<std::endl<<"Free Shapes: "<<SeqLabels.Length()<<std::endl;
   for (i = 1; i<=SeqLabels.Length(); i++) {
     DumpShape(theDumpLog, SeqLabels.Value(i), level, deep);
-    theDumpLog<<endl;
+    theDumpLog<<std::endl;
   }
+  return theDumpLog;
+}
+
+//=======================================================================
+//function : Dump
+//purpose  : override
+//=======================================================================
+
+Standard_OStream& XCAFDoc_ShapeTool::Dump(Standard_OStream& theDumpLog) const
+{
+  TDF_Attribute::Dump (theDumpLog);
+  Dump (theDumpLog, Standard_False);
+  return theDumpLog;
 }
 
 //=======================================================================
@@ -1341,7 +1367,7 @@ void XCAFDoc_ShapeTool::DumpShape(Standard_OStream& theDumpLog, const TDF_Label&
     TDF_Tool::Entry(aRef->Father()->Label(), Entry);
     theDumpLog<<" (refers to "<<Entry<<")";
   }
-  //cout<<endl;
+  //std::cout<<std::endl;
   Handle(TDataStd_Name) Name;
   if (L.FindAttribute(TDataStd_Name::GetID(),Name)) 
     theDumpLog<<" \""<<Name->Get()<<"\" ";
@@ -1840,61 +1866,68 @@ Standard_Boolean XCAFDoc_ShapeTool::FindSHUO (const TDF_LabelSequence& theLabels
 //function : Expand
 //purpose  : 
 //=======================================================================
-
-Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& Shape)
+Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& theShapeL)
 {
-  if(Shape.IsNull())
+  if (theShapeL.IsNull() || IsAssembly(theShapeL))
     return Standard_False;
 
-  TopoDS_Shape aShape = GetShape(Shape);
-  if(!aShape.IsNull() && aShape.ShapeType() == TopAbs_COMPOUND && !IsAssembly(Shape))
-  {
-    //set assembly attribute
-    TDataStd_UAttribute::Set ( Shape, XCAFDoc::AssemblyGUID() );
+  TopoDS_Shape aShape = GetShape(theShapeL);
+  if (aShape.IsNull())
+    return Standard_False;
 
+  TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
+  Standard_Boolean isExpandedType = aShapeType == TopAbs_COMPOUND || aShapeType == TopAbs_COMPSOLID ||
+                                    aShapeType == TopAbs_SHELL || aShapeType == TopAbs_WIRE;
+  if (isExpandedType)
+  {
     TopoDS_Iterator anIter(aShape);
     for(; anIter.More(); anIter.Next())
     {
-      TopoDS_Shape aChildShape = anIter.Value();
-      TDF_Label aChild = FindShape(aChildShape, Standard_True);
-      
-      TDF_TagSource aTag;
+      const TopoDS_Shape& aChildShape = anIter.Value();
+      TDF_Label aChild, aPart;
+
+      // Find child shape as subshape of expanded shape
+      FindSubShape(theShapeL, aChildShape, aChild);
       Handle(TDataStd_Name) anAttr;
-      //make part for child
-      TDF_Label aPart = aTag.NewChild(Label());
       //make child (if color isn't set or if it is compound)
-      if(aChild.IsNull())
-      {
-        TopLoc_Location nulloc;
-        aChild = aTag.NewChild(Shape);
-        SetShape(aChild, aChildShape);
-        SetShape(aPart, aChildShape.Located(nulloc));
+      if (aChild.IsNull()) {
+        aChild = AddSubShape(theShapeL, aChildShape);
       }
-      else
-      {
+      else {
         //get name
         aChild.FindAttribute(TDataStd_Name::GetID(), anAttr);
-        TopLoc_Location nulloc;
-        SetShape(aPart, aChildShape.Located(nulloc));
+      }
 
+      // Try to find child shape as already existed part
+      aPart = FindShape(aChildShape.Located(TopLoc_Location()));
+      if (aPart.IsNull()) {
+        // Create new part to link child shape
+        aPart = AddShape(aChildShape.Located(TopLoc_Location()), Standard_False, Standard_False);
       }
-      //set name to part
-      if(!anAttr.IsNull())
-      {
+      // Add shape manually, if already existed subshape found instead of creation of new part
+      if (!aPart.IsNull() && !IsTopLevel(aPart)) {
+        if (!GetReferredShape(aPart, aPart)) {
+          TDF_TagSource aTag;
+          aPart = aTag.NewChild(Label());
+          SetShape(aPart, aChildShape.Located(TopLoc_Location()));
+        }
+      }
+
+      // set name to part
+      if (!anAttr.IsNull()) {
         TDataStd_Name::Set(aPart, anAttr->Get());
       }
-      else
-      {
+      else {
         Standard_SStream Stream;
         TopAbs::Print(aChildShape.ShapeType(), Stream);
-        TCollection_AsciiString aName (Stream.str().c_str());
+        TCollection_AsciiString aName(Stream.str().c_str());
         TDataStd_Name::Set(aPart, TCollection_ExtendedString(aName));
       }
-
       MakeReference(aChild, aPart, aChildShape.Location());
-      
-      makeSubShape(aPart, aChildShape);
+      makeSubShape(theShapeL, aPart, aChildShape, aChildShape.Location());
     }
+    //set assembly attribute
+    TDataStd_UAttribute::Set(theShapeL, XCAFDoc::AssemblyGUID());
     return Standard_True;
   }
   return Standard_False;
@@ -1905,37 +1938,258 @@ Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& Shape)
 //purpose  : 
 //=======================================================================
 
-void XCAFDoc_ShapeTool::makeSubShape (const TDF_Label& Part, const TopoDS_Shape& Shape)
+void XCAFDoc_ShapeTool::makeSubShape (const TDF_Label& theMainShapeL,
+                                      const TDF_Label& thePart,
+                                      const TopoDS_Shape& theShape,
+                                      const TopLoc_Location& theLoc)
 {
-  TDF_TagSource aTag;
-  TopoDS_Iterator anIter(Shape);
-  for(; anIter.More(); anIter.Next())
-  {
-    TopoDS_Shape aChildShape = anIter.Value();
-    TDF_Label aChildLabel = FindShape(aChildShape,Standard_True);
-    if(!aChildLabel.IsNull())
-    { 
+  TopoDS_Iterator anIter(theShape);
+  Standard_Boolean isCompoundPart = (GetShape(thePart).ShapeType() == TopAbs_COMPOUND);
+  Standard_Boolean isAssembly = IsAssembly(thePart);
+
+  for(; anIter.More(); anIter.Next()) {
+    const TopoDS_Shape& aChildShape = anIter.Value();
+    TDF_Label aChildLabel;
+    FindSubShape(theMainShapeL, aChildShape, aChildLabel);
+    if(!aChildLabel.IsNull()) {
+      if (isAssembly) {
+        aChildLabel.ForgetAllAttributes();
+        makeSubShape(theMainShapeL, thePart, aChildShape, theLoc);
+        continue;
+      }
       //get name
       Handle(TDataStd_Name) anAttr;
       aChildLabel.FindAttribute(TDataStd_Name::GetID(), anAttr);
-      TopLoc_Location nulloc;
+      TopLoc_Location aSubLoc;
+      // Calculate location for subshapes of compound parts
+      aSubLoc = aChildShape.Location();
+      if (isCompoundPart) 
+        aSubLoc = theLoc.Inverted() * aSubLoc;
       //make subshape
-      TDF_Label aSubLabel = aTag.NewChild(Part);
-      SetShape(aSubLabel, aChildShape.Located(nulloc));
-      //set name to sub shape
-      if(!anAttr.IsNull())
+      TDF_Label aSubLabel;
+      // Identical location and empty location are not the same for ShapeTool, so try to process both
+      // in case of aSubLoc is not identical, the second Add try will not affect algorithm.
+      Standard_Boolean isNewSubL;
+      isNewSubL = AddSubShape(thePart, aChildShape.Located(aSubLoc), aSubLabel);
+      if (aSubLabel.IsNull())
+      {
+        isNewSubL = AddSubShape(thePart, aChildShape.Located(TopLoc_Location()), aSubLabel);
+      }
+      if (isNewSubL){
+        //set name to sub shape
+        if (!anAttr.IsNull()) {
+          TDataStd_Name::Set(aSubLabel, anAttr->Get());
+        }
+        else {
+          Standard_SStream Stream;
+          TopAbs::Print(aChildShape.ShapeType(), Stream);
+          TCollection_AsciiString aName(Stream.str().c_str());
+          TDataStd_Name::Set(aSubLabel, TCollection_ExtendedString(aName));
+        }
+        // Create auxiliary link, it will be removed during moving attributes
+        MakeReference(aSubLabel, aChildLabel, aChildShape.Location());
+      }
+      else {
+        aChildLabel.ForgetAllAttributes();
+      }
+    }
+
+    makeSubShape(theMainShapeL, thePart, aChildShape, theLoc);
+  }
+}
+
+//=======================================================================
+//function : updateComponent
+//purpose  :
+//=======================================================================
+
+Standard_Boolean XCAFDoc_ShapeTool::updateComponent(const TDF_Label& theItemLabel,
+                                                    TopoDS_Shape&    theUpdatedShape,
+                                                    TDF_LabelMap&    theUpdated) const
+{
+  if ( !IsAssembly(theItemLabel) )
+    return Standard_False; // Do nothing for non-assemblies
+
+  // Get the currently stored compound for the assembly
+  TopoDS_Shape aCurrentRootShape;
+  GetShape(theItemLabel, aCurrentRootShape);
+
+  // Check if the given assembly is already updated
+  if (theUpdated.Contains(theItemLabel)) {
+    theUpdatedShape = aCurrentRootShape;
+    return Standard_True;
+  }
+  
+  TopTools_MapOfOrientedShape aCurrentRootShapeMap (aCurrentRootShape.NbChildren());
+
+  // Get components of the assembly
+  TDF_LabelSequence aComponentLabs;
+  GetComponents(theItemLabel, aComponentLabs);
+
+  // This flag indicates whether to update the compound of the assembly
+  Standard_Boolean isModified = Standard_False;
+
+  // Compare the number of components in XDE structure with the number of
+  // components in topological structure. A component may happen to be removed,
+  // so we have to update the assembly compound
+  const Standard_Integer aNumTopoComponents = aCurrentRootShape.NbChildren();
+  //
+  if ( aNumTopoComponents != aComponentLabs.Length() )
+    isModified = Standard_True;
+
+  // Iterate over the assembly components. If at least one component is
+  // modified (this is the recursive check), then the actually stored
+  // compound has to be updated
+  TopTools_ListOfShape aComponentShapes;
+  //
+  for ( TDF_LabelSequence::Iterator aCompIt(aComponentLabs); aCompIt.More(); aCompIt.Next() )
+  {
+    const TDF_Label& aComponentLab = aCompIt.Value();
+
+    // Take the referred assembly item (ultimately, a part for an instance)
+    TDF_Label aComponentRefLab;
+    GetReferredShape(aComponentLab, aComponentRefLab);
+
+    // Shape comes with some placement transformation here
+    TopoDS_Shape aComponentShape;
+    GetShape(aComponentLab, aComponentShape);
+    TopLoc_Location aComponentLoc = aComponentShape.Location();
+
+    // If the component is a sub-assembly, then its associated compound
+    // has to be processed in the same manner
+    if ( IsAssembly(aComponentRefLab) )
+    {
+      // Recursive call
+      if ( updateComponent(aComponentRefLab, aComponentShape, theUpdated) )
       {
-        TDataStd_Name::Set(aSubLabel, anAttr->Get());
+        isModified = Standard_True;
+        aComponentShape.Location(aComponentLoc); // Apply placement
       }
-      else
+    }
+    else
+    {
+      // Search for a part in the actual compound of the ultimate assembly.
+      // If the part is there, then the compound is up-to-date, so it does not require rebuilding
+      if (!isModified)
       {
-        Standard_SStream Stream;
-        TopAbs::Print(aChildShape.ShapeType(), Stream);
-        TCollection_AsciiString aName (Stream.str().c_str());
-        TDataStd_Name::Set(aSubLabel, TCollection_ExtendedString(aName));
+        if (aCurrentRootShapeMap.IsEmpty())
+        {
+          // optimize search for next labels in aComponentLabs
+          for (TopoDS_Iterator aTopoIt(aCurrentRootShape); aTopoIt.More(); aTopoIt.Next())
+          {
+            aCurrentRootShapeMap.Add (aTopoIt.Value());
+          }
+        }
+        if (!aCurrentRootShapeMap.Contains (aComponentShape))
+        {
+          // Part has been modified somewhere, so the compound has to be rebuilt
+          isModified = Standard_True;
+        }
       }
-      MakeReference(aChildLabel, aSubLabel, aChildShape.Location());
     }
-    makeSubShape(Part, aChildShape);
+
+    // Fill the list of shapes composing a new compound for the assembly
+    aComponentShapes.Append(aComponentShape);
   }
-}
\ No newline at end of file
+
+  // If any component is modified, we update the currently stored shape
+  if ( isModified )
+  {
+    TopoDS_Compound anUpdatedCompound;
+    BRep_Builder aBB;
+    aBB.MakeCompound(anUpdatedCompound);
+
+    // Compose new compound
+    for ( TopTools_ListIteratorOfListOfShape aShapeIt(aComponentShapes); aShapeIt.More(); aShapeIt.Next() )
+    {
+      aBB.Add( anUpdatedCompound, aShapeIt.Value() );
+    }
+
+    // Store the updated shape as an output
+    theUpdatedShape = anUpdatedCompound;
+
+    // Use topological naming services to store the updated shape in XDE
+    TNaming_Builder NB(theItemLabel);
+    NB.Generated(theUpdatedShape);
+  }
+
+  if (isModified)
+    theUpdated.Add(theItemLabel);
+
+  return isModified;
+}
+
+//=======================================================================
+//function : GetNamedProperties
+//purpose  :
+//=======================================================================
+
+Handle(TDataStd_NamedData) XCAFDoc_ShapeTool::GetNamedProperties (const TDF_Label& theLabel,
+                                                                  const Standard_Boolean theToCreate) const
+{
+  Handle(TDataStd_NamedData) aNamedProperty;
+  if (!theLabel.FindAttribute(TDataStd_NamedData::GetID(), aNamedProperty) && theToCreate)
+  {
+    aNamedProperty = TDataStd_NamedData::Set(theLabel);
+  }
+
+  return aNamedProperty;
+}
+
+//=======================================================================
+//function : GetNamedProperties
+//purpose  :
+//=======================================================================
+
+Handle(TDataStd_NamedData) XCAFDoc_ShapeTool::GetNamedProperties (const TopoDS_Shape& theShape,
+                                                                  const Standard_Boolean theToCreate) const
+{
+  Handle(TDataStd_NamedData) aNamedProperty;
+  TDF_Label aLabel;
+  if (!Search (theShape, aLabel))
+    return aNamedProperty;
+
+  aNamedProperty = GetNamedProperties (aLabel, theToCreate);
+
+  return aNamedProperty;
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose  : 
+//=======================================================================
+void XCAFDoc_ShapeTool::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
+{
+  OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+  OCCT_DUMP_BASE_CLASS (theOStream, theDepth, TDF_Attribute)
+
+  for (XCAFDoc_DataMapOfShapeLabel::Iterator aShapeLabelIt (myShapeLabels); aShapeLabelIt.More(); aShapeLabelIt.Next())
+  {
+    OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &aShapeLabelIt.Key())
+
+    TCollection_AsciiString aShapeLabel;
+    TDF_Tool::Entry (aShapeLabelIt.Value(), aShapeLabel);
+    OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aShapeLabel)
+  }
+  
+  for (XCAFDoc_DataMapOfShapeLabel::Iterator aSubShapeIt (mySubShapes); aSubShapeIt.More(); aSubShapeIt.Next())
+  {
+    OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &aSubShapeIt.Key())
+
+    TCollection_AsciiString aSubShape;
+    TDF_Tool::Entry (aSubShapeIt.Value(), aSubShape);
+    OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aSubShape)
+  }
+  
+  for (XCAFDoc_DataMapOfShapeLabel::Iterator aSimpleShapeIt (mySimpleShapes); aSimpleShapeIt.More(); aSimpleShapeIt.Next())
+  {
+    OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &aSimpleShapeIt.Key())
+
+    TCollection_AsciiString aSimpleShape;
+    TDF_Tool::Entry (aSimpleShapeIt.Value(), aSimpleShape);
+    OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aSimpleShape)
+  }
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, hasSimpleShapes)
+}