0031517: Data Exchange - wrong result of ShapeTool::UpdateAssemblies()
[occt.git] / src / XCAFDoc / XCAFDoc_ShapeTool.cxx
index ea7aae8..1d6677f 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <XCAFDoc_ShapeTool.ixx>
-#include <XCAFDoc.hxx>
+#include <XCAFDoc_ShapeTool.hxx>
 
-#include <TDF_Tool.hxx>
+#include <BRep_Builder.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Trsf.hxx>
+#include <Standard_GUID.hxx>
+#include <Standard_Type.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_ExtendedString.hxx>
+#include <TCollection_HAsciiString.hxx>
+#include <TColStd_SequenceOfHAsciiString.hxx>
+#include <TDataStd_ChildNodeIterator.hxx>
+#include <TDataStd_Name.hxx>
+#include <TDataStd_TreeNode.hxx>
+#include <TDataStd_UAttribute.hxx>
+#include <TDF_Attribute.hxx>
+#include <TDF_ChildIDIterator.hxx>
+#include <TDF_ChildIterator.hxx>
 #include <TDF_Label.hxx>
 #include <TDF_LabelMap.hxx>
 #include <TDF_LabelSequence.hxx>
-#include <TDF_ChildIterator.hxx>
-#include <TDF_ChildIDIterator.hxx>
 #include <TDF_MapIteratorOfLabelMap.hxx>
-
-#include <TDataStd_Name.hxx>
-#include <TDataStd_TreeNode.hxx>
-#include <TDataStd_ChildNodeIterator.hxx>
-#include <TDataStd_UAttribute.hxx>
-
+#include <TDF_RelocationTable.hxx>
+#include <TDF_Tool.hxx>
 #include <TDocStd_Document.hxx>
-
 #include <TNaming_Builder.hxx>
 #include <TNaming_NamedShape.hxx>
 #include <TNaming_Tool.hxx>
-
+#include <TopLoc_IndexedMapOfLocation.hxx>
 #include <TopLoc_Location.hxx>
+#include <TopoDS_Compound.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <TopoDS_Shape.hxx>
-#include <TopoDS_Compound.hxx>
-#include <BRep_Builder.hxx>
-#include <XCAFDoc_Location.hxx>
-
-#include <TCollection_AsciiString.hxx>
-#include <TCollection_HAsciiString.hxx>
-#include <TCollection_ExtendedString.hxx>
-#include <TColStd_SequenceOfHAsciiString.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapOfOrientedShape.hxx>
+#include <XCAFDoc.hxx>
 #include <XCAFDoc_GraphNode.hxx>
-#include <TopLoc_IndexedMapOfLocation.hxx>
-#include <gp_Trsf.hxx>
-#include <gp_Pnt.hxx>
+#include <XCAFDoc_Location.hxx>
 #include <XCAFDoc_ShapeMapTool.hxx>
 
+IMPLEMENT_STANDARD_RTTIEXT(XCAFDoc_ShapeTool,TDF_Attribute)
+
 static Standard_Boolean theAutoNaming = Standard_True;
 
 // attribute methods //////////////////////////////////////////////////
@@ -146,7 +149,9 @@ static void SetLabelNameByLink(const TDF_Label L)
   Handle(TDataStd_TreeNode) Node;
   if (! L.FindAttribute(XCAFDoc::ShapeRefGUID(), Node) ||
       ! Node->HasFather()) {
-    cout<<"Error: XCAFDoc_ShapeTool, SetLabelNameByLink(): NO NODE"<<endl;
+#ifdef OCCT_DEBUG
+    std::cout<<"Error: XCAFDoc_ShapeTool, SetLabelNameByLink(): NO NODE"<<std::endl;
+#endif
     return;
   }
   TCollection_AsciiString Entry;
@@ -299,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;
 }
 
@@ -325,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();
 }
 
 //=======================================================================
@@ -412,13 +424,6 @@ void XCAFDoc_ShapeTool::SetShape (const TDF_Label& L, const TopoDS_Shape& S)
   if(!myShapeLabels.IsBound(S)) {
     myShapeLabels.Bind(S,L);
   }
-  
-  //:abv 31.10.01: update assemblies that refer a shape
-  TDF_LabelSequence Labels;
-  if ( GetUsers ( L, Labels, Standard_True ) ) {
-    for ( Standard_Integer i=Labels.Length(); i >=1; i-- ) 
-      UpdateAssembly ( Labels(i) );
-  }
 }
 
 //=======================================================================
@@ -934,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;
   
@@ -951,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;
 }
 
@@ -983,34 +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 : UpdateAssembly
+//function : UpdateAssemblies
 //purpose  : 
 //=======================================================================
 
-void XCAFDoc_ShapeTool::UpdateAssembly (const TDF_Label& L) const
+void XCAFDoc_ShapeTool::UpdateAssemblies()
 {
-  if ( ! IsAssembly(L) ) return;
-
-  TopoDS_Compound newassembly;
-  BRep_Builder b;
-  b.MakeCompound(newassembly);
+  // We start from the free shapes (roots in the assembly structure)
+  TDF_LabelSequence aRootLabels;
+  GetFreeShapes(aRootLabels);
 
-  TDF_ChildIterator chldLabIt(L);
-  for (; chldLabIt.More(); chldLabIt.Next() ) {
-    TDF_Label subLabel = chldLabIt.Value();
-    if ( IsComponent ( subLabel ) ) {
-      b.Add(newassembly, 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);
   }
-  TNaming_Builder tnBuild(L);
-  tnBuild.Generated(newassembly);
 }
 
 //=======================================================================
@@ -1039,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);
 }
@@ -1057,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;
 }
 
@@ -1087,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);
@@ -1097,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
@@ -1132,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;
@@ -1170,44 +1231,63 @@ TDF_Label XCAFDoc_ShapeTool::BaseLabel () const
 //purpose  : recursive part of Dump()
 //=======================================================================
 
-static void DumpAssembly(const TDF_Label L,
+static void DumpAssembly(Standard_OStream& theDumpLog,
+                        const TDF_Label L,
                         const Standard_Integer level,
                         const Standard_Boolean deep)
 {
+  TopoDS_Shape S;
+  XCAFDoc_ShapeTool::GetShape(L, S);
+  if(S.IsNull())
+    return;
   for (Standard_Integer i=0; i<level; i++)
-    cout<<"\t";
+    theDumpLog<<"\t";
   
   TCollection_AsciiString Entry;
   TDF_Tool::Entry(L, Entry);
+  
+  if(XCAFDoc_ShapeTool::IsAssembly(L))
+  {
+    theDumpLog<<"ASSEMBLY ";
+  }
+  else if (XCAFDoc_ShapeTool::IsSimpleShape(L))
+  {
+    if(L.Father().Father().Father().IsRoot())
+      theDumpLog<<"PART ";
+  }
+  else
+  {
+    theDumpLog<<"INSTANCE ";
+  }
+  TopAbs::Print(S.ShapeType(), theDumpLog);
 
-  cout<<"ASSEMBLY "<<Entry;
+  theDumpLog<<" "<<Entry;
+  if(XCAFDoc_ShapeTool::IsReference(L))
+  {
+    Handle(TDataStd_TreeNode) aRef;
+    L.FindAttribute(XCAFDoc::ShapeRefGUID(), aRef);
+    TDF_Tool::Entry(aRef->Father()->Label(), Entry);
+    theDumpLog<<" (refers to "<<Entry<<")";
+  }
   Handle(TDataStd_Name) Name;
   if (L.FindAttribute(TDataStd_Name::GetID(), Name))
-    cout<<" "<<Name->Get();
+    theDumpLog<<" \""<<Name->Get()<<"\" ";
   
   if (deep) {
-    TopoDS_Shape S;
-    XCAFDoc_ShapeTool::GetShape(L, S);
-    cout<<"("<<*(void**)&S.TShape();
+    theDumpLog<<"("<<*(void**)&S.TShape();
     if (! S.Location().IsIdentity())
-      cout<<", "<< *(void**)&S.Location();
-    cout<<") ";
+      theDumpLog<<", "<< *(void**)&S.Location();
+    theDumpLog<<") ";
   }
-  cout<<endl;
+  theDumpLog<<std::endl;
   
   Handle(TDataStd_TreeNode) Node;
-  TDF_ChildIDIterator NodeIterator(L, XCAFDoc::ShapeRefGUID());
+  TDF_ChildIterator NodeIterator(L);
   for (; NodeIterator.More(); NodeIterator.Next()) {
-    Node = Handle(TDataStd_TreeNode)::DownCast(NodeIterator.Value());
-    if (Node->HasFather()) {
-      if (Node->Father()->Label().HasChild())
-       DumpAssembly(Node->Father()->Label(), level+1, deep);
-      else {
-       XCAFDoc_ShapeTool::DumpShape(Node->Father()->Label(), level+1, deep);
-         cout<<endl;
-       }
-    }
+    DumpAssembly(theDumpLog, NodeIterator.Value(), level+1, deep);
   }
+  if(level == 0)
+    theDumpLog<<std::endl;
 }
 
 //=======================================================================
@@ -1215,26 +1295,39 @@ static void DumpAssembly(const TDF_Label L,
 //purpose  : 
 //=======================================================================
 
-void XCAFDoc_ShapeTool::Dump(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) cout<<endl;
+  if (SeqLabels.Length()>0) theDumpLog<<std::endl;
   Standard_Integer i;
   for (i=1; i<=SeqLabels.Length(); i++) {
-    DumpAssembly(SeqLabels.Value(i), level, deep);
+    DumpAssembly(theDumpLog, SeqLabels.Value(i), level, deep);
   }
 
   SeqLabels.Clear();
   GetFreeShapes(SeqLabels);
-  cout<<endl<<"Free Shapes: "<<SeqLabels.Length()<<endl;
+  theDumpLog<<std::endl<<"Free Shapes: "<<SeqLabels.Length()<<std::endl;
   for (i = 1; i<=SeqLabels.Length(); i++) {
-    DumpShape(SeqLabels.Value(i), level, deep);
-    cout<<endl;
+    DumpShape(theDumpLog, SeqLabels.Value(i), level, deep);
+    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;
 }
 
 //=======================================================================
@@ -1242,29 +1335,48 @@ void XCAFDoc_ShapeTool::Dump(const Standard_Boolean deep) const
 //purpose  : 
 //=======================================================================
 
-void XCAFDoc_ShapeTool::DumpShape(const TDF_Label& L,const Standard_Integer level,const Standard_Boolean deep) 
+void XCAFDoc_ShapeTool::DumpShape(Standard_OStream& theDumpLog, const TDF_Label& L,const Standard_Integer level,const Standard_Boolean deep)
 {
   TopoDS_Shape S;
   if(! XCAFDoc_ShapeTool::GetShape(L, S) ) return;
   for (Standard_Integer i=0; i<level; i++)
-    cout<<"\t";
+    theDumpLog<<"\t";
   
-  if (S.ShapeType() == TopAbs_COMPOUND) cout<<"ASSEMBLY";
-  else TopAbs::Print(S.ShapeType(), cout);
+  if(XCAFDoc_ShapeTool::IsAssembly(L))
+  {
+    theDumpLog<<"ASSEMBLY ";
+  }
+  else if (XCAFDoc_ShapeTool::IsSimpleShape(L))
+  {
+    if(L.Father().Father().Father().IsRoot())
+      theDumpLog<<"PART ";
+  }
+  else
+  {
+    theDumpLog<<"INSTANCE ";
+  }  
+  TopAbs::Print(S.ShapeType(), theDumpLog);
   
   TCollection_AsciiString Entry;
   TDF_Tool::Entry(L, Entry);
-  cout<<"  "<<Entry;
-  //cout<<endl;
+  theDumpLog<<"  "<<Entry;
+  if(XCAFDoc_ShapeTool::IsReference(L))
+  {
+    Handle(TDataStd_TreeNode) aRef;
+    L.FindAttribute(XCAFDoc::ShapeRefGUID(), aRef);
+    TDF_Tool::Entry(aRef->Father()->Label(), Entry);
+    theDumpLog<<" (refers to "<<Entry<<")";
+  }
+  //std::cout<<std::endl;
   Handle(TDataStd_Name) Name;
   if (L.FindAttribute(TDataStd_Name::GetID(),Name)) 
-    cout<<" "<<Name->Get();
+    theDumpLog<<" \""<<Name->Get()<<"\" ";
   
   if (deep) {
-    cout<<"("<<*(void**)&S.TShape();
+    theDumpLog<<"("<<*(void**)&S.TShape();
     if (! S.Location().IsIdentity())
-      cout<<", "<< *(void**)&S.Location();
-    cout<<") ";
+      theDumpLog<<", "<< *(void**)&S.Location();
+    theDumpLog<<") ";
   }
 }
 
@@ -1749,3 +1861,335 @@ Standard_Boolean XCAFDoc_ShapeTool::FindSHUO (const TDF_LabelSequence& theLabels
   }
   return ( !theSHUOAttr.IsNull() );
 }
+
+//=======================================================================
+//function : Expand
+//purpose  : 
+//=======================================================================
+Standard_Boolean XCAFDoc_ShapeTool::Expand (const TDF_Label& theShapeL)
+{
+  if (theShapeL.IsNull() || IsAssembly(theShapeL))
+    return Standard_False;
+
+  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())
+    {
+      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 child (if color isn't set or if it is compound)
+      if (aChild.IsNull()) {
+        aChild = AddSubShape(theShapeL, aChildShape);
+      }
+      else {
+        //get name
+        aChild.FindAttribute(TDataStd_Name::GetID(), anAttr);
+      }
+
+      // 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);
+      }
+      // 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 {
+        Standard_SStream Stream;
+        TopAbs::Print(aChildShape.ShapeType(), Stream);
+        TCollection_AsciiString aName(Stream.str().c_str());
+        TDataStd_Name::Set(aPart, TCollection_ExtendedString(aName));
+      }
+      MakeReference(aChild, aPart, aChildShape.Location());
+      makeSubShape(theShapeL, aPart, aChildShape, aChildShape.Location());
+    }
+    //set assembly attribute
+    TDataStd_UAttribute::Set(theShapeL, XCAFDoc::AssemblyGUID());
+    return Standard_True;
+  }
+  return Standard_False;
+}
+
+//=======================================================================
+//function : makeSubShape
+//purpose  : 
+//=======================================================================
+
+void XCAFDoc_ShapeTool::makeSubShape (const TDF_Label& theMainShapeL,
+                                      const TDF_Label& thePart,
+                                      const TopoDS_Shape& theShape,
+                                      const TopLoc_Location& theLoc)
+{
+  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 aSubLoc;
+      // Calculate location for subshapes of compound parts
+      aSubLoc = aChildShape.Location();
+      if (isCompoundPart) 
+        aSubLoc = theLoc.Inverted() * aSubLoc;
+      //make subshape
+      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) )
+      {
+        isModified = Standard_True;
+        aComponentShape.Location(aComponentLoc); // Apply placement
+      }
+    }
+    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)
+      {
+        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;
+        }
+      }
+    }
+
+    // Fill the list of shapes composing a new compound for the assembly
+    aComponentShapes.Append(aComponentShape);
+  }
+
+  // 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)
+}