0028908: Improvement on attachment of attributes to the label
[occt.git] / src / TDF / TDF_CopyTool.cxx
1 // Created by: DAUTRY Philippe
2 // Copyright (c) 1997-1999 Matra Datavision
3 // Copyright (c) 1999-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 //              ---------------------
17 // Version:     0.0
18 //Version       Date            Purpose
19 //              0.0     Mar 11 1997     Creation
20
21 #include <Standard_TypeMismatch.hxx>
22 #include <TDF_Attribute.hxx>
23 #include <TDF_AttributeDataMap.hxx>
24 #include <TDF_AttributeIterator.hxx>
25 #include <TDF_AttributeMap.hxx>
26 #include <TDF_ChildIterator.hxx>
27 #include <TDF_ClosureTool.hxx>
28 #include <TDF_CopyTool.hxx>
29 #include <TDF_DataMapIteratorOfAttributeDataMap.hxx>
30 #include <TDF_DataMapIteratorOfLabelDataMap.hxx>
31 #include <TDF_DataSet.hxx>
32 #include <TDF_IDFilter.hxx>
33 #include <TDF_Label.hxx>
34 #include <TDF_LabelDataMap.hxx>
35 #include <TDF_LabelMap.hxx>
36 #include <TDF_ListIteratorOfLabelList.hxx>
37 #include <TDF_MapIteratorOfAttributeMap.hxx>
38 #include <TDF_MapIteratorOfLabelMap.hxx>
39 #include <TDF_RelocationTable.hxx>
40
41 //=======================================================================
42 //function : Copy
43 //purpose  : 
44 //=======================================================================
45
46 void TDF_CopyTool::Copy
47 (const Handle(TDF_DataSet)& aSourceDataSet,
48  const Handle(TDF_RelocationTable)& aRelocationTable) 
49 {
50   TDF_IDFilter privilegeFilter; // Ignore the target attribute's privilege!
51   TDF_IDFilter refFilter; // Will not be used.
52   TDF_CopyTool::Copy
53     (aSourceDataSet, aRelocationTable, privilegeFilter,
54      refFilter, Standard_False);
55 }
56
57
58 //=======================================================================
59 //function : Copy
60 //purpose  : 
61 //=======================================================================
62
63 void TDF_CopyTool::Copy
64 (const Handle(TDF_DataSet)& aSourceDataSet,
65  const Handle(TDF_RelocationTable)& aRelocationTable,
66  const TDF_IDFilter& aPrivilegeFilter) 
67 {
68   TDF_IDFilter refFilter; // Will not be used.
69   TDF_CopyTool::Copy
70     (aSourceDataSet, aRelocationTable, aPrivilegeFilter,
71      refFilter, Standard_False);
72
73 }
74
75 //=======================================================================
76 //function : Copy
77 //purpose  : 
78 //=======================================================================
79
80 void TDF_CopyTool::Copy
81 (const Handle(TDF_DataSet)&             aSourceDataSet,
82  const Handle(TDF_RelocationTable)&     aRelocationTable,
83  const TDF_IDFilter&                    aPrivilegeFilter,
84  const TDF_IDFilter&                    /* aRefFilter */,
85  const Standard_Boolean                 /* setSelfContained */) 
86 {
87   if (aSourceDataSet->IsEmpty()) return;
88
89   TDF_LabelMap&        srcLabs = aSourceDataSet->Labels();
90   TDF_AttributeMap&    srcAtts = aSourceDataSet->Attributes();
91   TDF_LabelList&       rootLst = aSourceDataSet->Roots();
92
93   TDF_LabelDataMap&     theLabMap  = aRelocationTable->LabelTable();
94   TDF_AttributeDataMap& theAttMap  = aRelocationTable->AttributeTable();
95
96   // Parallel exploration of the root label structures:
97   // * builds the target labels not found;
98   // * binds the source attributes with the target ones;
99   // * binds the source attributes with new target ones if there is none.
100
101   // Label pre-binding is tested before paste.
102   // For it is possible to copy the roots at another place with OTHER TAGS,
103   // we first ask <theLabMap> if each source root label is already bound.
104
105   for (TDF_ListIteratorOfLabelList labLItr(rootLst);
106        labLItr.More(); labLItr.Next()) {
107     const TDF_Label& sLab = labLItr.Value();
108     if (theLabMap.IsBound(sLab)) {
109       TDF_Label tIns(theLabMap.Find(sLab));
110       TDF_CopyTool::CopyLabels(sLab,tIns,
111         theLabMap,theAttMap,srcLabs,srcAtts);
112     }
113     // if not bound : do nothing!
114   }
115
116   // The relocation attribute table is now ready,
117   // except for the label unattached attributes,
118   // but everybody can update the relocation table...
119
120   // Now: the paste phasis!
121   TDF_DataMapIteratorOfAttributeDataMap attItr2(theAttMap);
122   for (;attItr2.More(); attItr2.Next()) {
123     const Handle(TDF_Attribute)& sAtt = attItr2.Key();
124     if (!sAtt.IsNull()) { // This condition looks superfluous; and below also.
125       const Handle(TDF_Attribute)& tAtt = attItr2.Value();
126       // 1 - No copy on itself.
127       // 2 - The target attribute is present BUT its privilege over the
128       // source one must be ignored. The source attribute can be copied.
129       if ((sAtt != tAtt) && aPrivilegeFilter.IsIgnored(tAtt->ID()))
130         sAtt->Paste(tAtt,aRelocationTable);
131     }
132   }
133 }
134
135
136
137 //=======================================================================
138 //function : CopyLabels
139 //purpose  : Internal root label copy recursive method.
140 //=======================================================================
141
142 void TDF_CopyTool::CopyLabels
143 (const TDF_Label& aSLabel,
144  TDF_Label& aTargetLabel,
145  TDF_LabelDataMap& aLabMap,
146  TDF_AttributeDataMap& aAttMap,
147  const TDF_LabelMap& aSrcLabelMap,
148  const TDF_AttributeMap& aSrcAttributeMap)
149 {
150   TDF_CopyTool::CopyAttributes(aSLabel,aTargetLabel,
151     aAttMap,aSrcAttributeMap);
152
153   // Does the same for the children.
154   for (TDF_ChildIterator childItr(aSLabel); childItr.More(); childItr.Next()){
155     const TDF_Label& childSLab = childItr.Value();
156     if (aSrcLabelMap.Contains(childSLab)) {
157       TDF_Label childTIns = aTargetLabel.FindChild(childSLab.Tag());
158       aLabMap.Bind(childSLab,childTIns);
159       TDF_CopyTool::CopyLabels(childSLab,childTIns,
160         aLabMap,aAttMap,
161         aSrcLabelMap,aSrcAttributeMap);
162     }
163   }
164 }
165
166 //=======================================================================
167 //function : CopyAttributes
168 //purpose  : Internal attribute copy method.
169 //=======================================================================
170
171 void TDF_CopyTool::CopyAttributes
172 (const TDF_Label& aSLabel,
173  TDF_Label& aTargetLabel,
174  TDF_AttributeDataMap& aAttMap,
175  const TDF_AttributeMap& aSrcAttributeMap)
176 {
177   Handle(TDF_Attribute) tAtt;
178
179   // Finds the target attributes or creates them empty.
180   for (TDF_AttributeIterator attItr(aSLabel);
181        attItr.More(); attItr.Next()) {
182     const Handle(TDF_Attribute) sAtt = attItr.Value();
183     if (aSrcAttributeMap.Contains(sAtt)) {
184       const Standard_GUID& id = sAtt->ID();
185       if (!aTargetLabel.FindAttribute(id,tAtt)) {
186         tAtt = sAtt->NewEmpty();
187         if(tAtt->ID() != id) 
188           tAtt->SetID(id);//
189         aTargetLabel.AddAttribute(tAtt, Standard_True);
190         aAttMap.Bind(sAtt,tAtt);
191       }
192       else {
193         // Some attributes have the same ID, but are different and
194         // exclusive. This obliged to test the dynamic type identity.
195         if (tAtt->IsInstance(sAtt->DynamicType()))
196           aAttMap.Bind(sAtt,tAtt);
197         else
198           throw Standard_TypeMismatch("TDF_CopyTool: Cannot paste to a different type attribute.");
199       }
200     }
201   }
202 }