]> SALOME platform Git repositories - modules/shaper.git/blob - src/Model/Model_AttributeRefList.cpp
Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[modules/shaper.git] / src / Model / Model_AttributeRefList.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
18 //
19
20 #include "Model_AttributeRefList.h"
21 #include "Model_Application.h"
22 #include "Model_Data.h"
23 #include "Model_Objects.h"
24 #include <ModelAPI_Feature.h>
25 #include <TDF_ListIteratorOfLabelList.hxx>
26 #include <TDF_Tool.hxx>
27 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
28
29 void Model_AttributeRefList::append(ObjectPtr theObject)
30 {
31   if (owner()->document() == theObject->document()) {
32     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
33     myRef->Append(aData->label().Father());  // store label of the object
34   } else if (theObject.get() && theObject->data()->isValid()) { // reference to the other document
35     myRef->Append(myRef->Label());
36     // if these attributes exist, the link is external: keep reference to access the label
37     std::ostringstream anIdString; // string with document Id
38     anIdString<<theObject->document()->id();
39     myExtDocRef->Append(anIdString.str().c_str());
40     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
41     TCollection_AsciiString anEntry;
42     TDF_Tool::Entry(aData->label().Father(), anEntry);
43     myExtDocRef->Append(anEntry);
44   } else return; // something is wrong
45
46   // do it before the transaction finish to make just created/removed objects know dependencies
47   // and reference from composite feature is removed automatically
48   ADD_BACK_REF(theObject);
49   owner()->data()->sendAttributeUpdated(this);
50 }
51
52 void Model_AttributeRefList::remove(ObjectPtr theObject)
53 {
54   if (theObject.get() != NULL) {
55     if (owner()->document() == theObject->document()) {
56       std::shared_ptr<Model_Data> aData;
57       aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
58       myRef->Remove(aData->label().Father());
59       REMOVE_BACK_REF(theObject);
60       owner()->data()->sendAttributeUpdated(this);
61     } else {
62       // create new lists because for the current moment remove one of the duplicated elements
63       // from the list is buggy
64       TDF_LabelList anOldList = myRef->List();
65       myRef->Clear();
66       TDataStd_ListOfExtendedString anOldExts = myExtDocRef->List();
67       myExtDocRef->Clear();
68
69       std::ostringstream anIdString; // string with document Id
70       anIdString<<theObject->document()->id();
71       std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
72       TCollection_AsciiString anEntry;
73       TDF_Tool::Entry(aData->label().Father(), anEntry);
74       bool aFound = false;
75       TDataStd_ListIteratorOfListOfExtendedString anExtIter(anOldExts);
76       for (TDF_ListIteratorOfLabelList aLIter(anOldList); aLIter.More(); aLIter.Next()) {
77         if (aLIter.Value() == myRef->Label()) {
78           if (anExtIter.Value() == anIdString.str().c_str()) {
79             TDataStd_ListIteratorOfListOfExtendedString anExtIter2 = anExtIter;
80             anExtIter2.Next();
81             if (anExtIter2.Value() == anEntry) { // fully maches, so, remove(don't copy)
82               aFound = true;
83               continue;
84             }
85           }
86           myExtDocRef->Append(anExtIter.Value());
87           anExtIter.Next();
88           myExtDocRef->Append(anExtIter.Value());
89           anExtIter.Next();
90         }
91         myRef->Append(aLIter.Value());
92       }
93       if (aFound) {
94         REMOVE_BACK_REF(theObject);
95         owner()->data()->sendAttributeUpdated(this);
96       }
97     }
98   }
99   else { // in case of empty object remove, the first empty object is removed from the list
100     std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
101         owner()->document());
102     if (aDoc) {
103       const TDF_LabelList& aList = myRef->List();
104       for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
105         ObjectPtr anObj = aDoc->objects()->object(aLIter.Value());
106         if (anObj.get() == NULL) {
107           myRef->Remove(aLIter.Value());
108           REMOVE_BACK_REF(theObject);
109           owner()->data()->sendAttributeUpdated(this);
110           break;
111         }
112       }
113     }
114   }
115 }
116
117 void Model_AttributeRefList::clear()
118 {
119   std::list<ObjectPtr> anOldList = list();
120   myRef->Clear();
121   std::list<ObjectPtr>::iterator anOldIter = anOldList.begin();
122   for(; anOldIter != anOldList.end(); anOldIter++) {
123     REMOVE_BACK_REF((*anOldIter));
124   }
125   myExtDocRef->Clear();
126   owner()->data()->sendAttributeUpdated(this);
127 }
128
129 int Model_AttributeRefList::size(const bool theWithEmpty) const
130 {
131   if (theWithEmpty)
132     return myRef->Extent();
133   int aResult = 0;
134   const TDF_LabelList& aList = myRef->List();
135   for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
136     if (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot()) aResult++;
137   }
138   return aResult;
139 }
140
141 bool Model_AttributeRefList::isInitialized()
142 {
143   if (size(false) == 0) {
144     // empty list is not initialized list: sketch will be not valid after add/undo
145     return false;
146   }
147   return ModelAPI_AttributeRefList::isInitialized();
148 }
149
150 ObjectPtr Model_AttributeRefList::iteratedObject(TDF_ListIteratorOfLabelList& theLIter,
151     TDataStd_ListIteratorOfListOfExtendedString& theExtIter,
152     std::shared_ptr<Model_Document> theDoc) const
153 {
154   ObjectPtr anObj;
155   if (!theLIter.Value().IsNull() && !theLIter.Value().IsRoot()) {
156     if (theLIter.Value() == myRef->Label()) { // external document object
157       int anID = atoi(TCollection_AsciiString(theExtIter.Value()).ToCString());
158       theExtIter.Next();
159       DocumentPtr aRefDoc = Model_Application::getApplication()->document(anID);
160       if (aRefDoc.get()) {
161         std::shared_ptr<Model_Document> aDR = std::dynamic_pointer_cast<Model_Document>(aRefDoc);
162         TDF_Label aRefLab;
163         TDF_Tool::Label(aDR->objects()->featuresLabel().Data(),
164           TCollection_AsciiString(theExtIter.Value()).ToCString(), aRefLab);
165         if (!aRefLab.IsNull()) {
166           anObj = aDR->objects()->object(aRefLab);
167         }
168       }
169       theExtIter.Next();
170     } else { // internal document object
171       anObj = theDoc->objects()->object(theLIter.Value());
172     }
173   }
174   return anObj;
175 }
176
177 std::list<ObjectPtr> Model_AttributeRefList::list()
178 {
179   std::list<ObjectPtr> aResult;
180   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
181       owner()->document());
182   if (aDoc) {
183     const TDF_LabelList& aList = myRef->List();
184     TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List());
185     for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
186       aResult.push_back(iteratedObject(aLIter, anExtIter, aDoc));
187     }
188   }
189   return aResult;
190 }
191
192 bool Model_AttributeRefList::isInList(const ObjectPtr& theObj)
193 {
194   if(!theObj.get()) {
195     return false;
196   }
197   if (theObj->document() == owner()->document()) { // this document object
198     std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
199         owner()->document());
200     if (aDoc) {
201       std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
202       if (aData.get() && aData->isValid()) {
203         TDF_Label anObjLab = aData->label().Father();
204         const TDF_LabelList& aList = myRef->List();
205         for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
206           if (aLIter.Value().IsEqual(anObjLab)) {
207             return true;
208           }
209         }
210       }
211     }
212   } else { // external document object
213     // create new lists because for the current moment remove one of the duplicated elements
214     // from the list is buggy
215     std::ostringstream anIdString; // string with document Id
216     anIdString<<theObj->document()->id();
217     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
218     TCollection_AsciiString anEntry;
219     TDF_Tool::Entry(aData->label().Father(), anEntry);
220     bool aFound = false;
221     TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List());
222     for (; anExtIter.More(); anExtIter.Next()) {
223       if (anExtIter.Value() == anIdString.str().c_str()) {
224         anExtIter.Next();
225         if (anExtIter.Value() == anEntry) { // fully maches
226           return true;
227         }
228       } else {
229         anExtIter.Next();
230       }
231     }
232   }
233   return false;
234 }
235
236 ObjectPtr Model_AttributeRefList::object(const int theIndex, const bool theWithEmpty) const
237 {
238   std::shared_ptr<Model_Document> aDoc =
239     std::dynamic_pointer_cast<Model_Document>(owner()->document());
240   if (aDoc) {
241     int anIndex = -1;
242     TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List());
243     for (TDF_ListIteratorOfLabelList aLIter(myRef->List()); aLIter.More(); aLIter.Next()) {
244       if (theWithEmpty || (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot()))
245         anIndex++;
246       if (anIndex == theIndex) {
247         return iteratedObject(aLIter, anExtIter, aDoc);
248       }
249       if (aLIter.Value() == myRef->Label()) {
250         anExtIter.Next();
251         anExtIter.Next();
252       }
253     }
254   }
255   return ObjectPtr();
256 }
257
258 void Model_AttributeRefList::substitute(const ObjectPtr& theCurrent, const ObjectPtr& theNew)
259 {
260   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
261       owner()->document());
262   if (aDoc) {
263     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theCurrent->data());
264     if (aData.get() && aData->isValid()) {
265       TDF_Label aCurrentLab = aData->label().Father();
266       TDF_Label aNewLab;
267       if (theNew.get() && theNew->data()->isValid()) { // the new may be null
268         std::shared_ptr<Model_Data> aNewData =
269           std::dynamic_pointer_cast<Model_Data>(theNew->data());
270         aNewLab = aNewData->label().Father();
271       } else {
272         aNewLab = aCurrentLab.Root(); // root means null object
273       }
274       // do the substitution
275       ADD_BACK_REF(theNew);
276       if (myRef->InsertAfter(aNewLab, aCurrentLab)) {
277         myRef->Remove(aCurrentLab);
278         REMOVE_BACK_REF(theCurrent);
279       }
280       owner()->data()->sendAttributeUpdated(this);
281     }
282   }
283 }
284
285 void Model_AttributeRefList::exchange(const ObjectPtr& theObject1, const ObjectPtr& theObject2)
286 {
287   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
288       owner()->document());
289   if (aDoc) {
290     std::shared_ptr<Model_Data> aData1 = std::dynamic_pointer_cast<Model_Data>(theObject1->data());
291     if (aData1.get() && aData1->isValid()) {
292       TDF_Label aLab1 = aData1->label().Father();
293       if (theObject2.get() && theObject2->data()->isValid()) { // the new may be null
294         std::shared_ptr<Model_Data> aData2 =
295           std::dynamic_pointer_cast<Model_Data>(theObject2->data());
296         if (aData2.get() && aData2->isValid()) {
297           TDF_Label aLab2 = aData2->label().Father();
298           // do the substitution: use the temporary label, as usually in exchange
299           TDF_Label aTmpLab = aLab1.Root();
300           if (myRef->InsertAfter(aTmpLab, aLab1)) {
301             myRef->Remove(aLab1);
302           }
303           if (myRef->InsertAfter(aLab1, aLab2)) {
304             myRef->Remove(aLab2);
305           }
306           if (myRef->InsertAfter(aLab2, aTmpLab)) {
307             myRef->Remove(aTmpLab);
308           }
309           owner()->data()->sendAttributeUpdated(this);
310         }
311       }
312     }
313   }
314 }
315
316 void Model_AttributeRefList::removeLast()
317 {
318   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
319       owner()->document());
320   if (aDoc && !myRef->IsEmpty()) {
321     ObjectPtr anObj = aDoc->objects()->object(myRef->Last());
322     if (anObj.get()) {
323       myRef->Remove(myRef->Last());
324       REMOVE_BACK_REF(anObj);
325       owner()->data()->sendAttributeUpdated(this);
326     }
327   }
328 }
329
330 void Model_AttributeRefList::remove(const std::set<int>& theIndices)
331 {
332   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
333       owner()->document());
334   if (aDoc && !myRef->IsEmpty()) {
335     // collet labels that will be removed
336     TDF_LabelList aLabelsToRemove;
337     TDF_ListIteratorOfLabelList aLabIter(myRef->List());
338     for(int aCurrent = 0; aLabIter.More(); aLabIter.Next(), aCurrent++) {
339       if (theIndices.find(aCurrent) != theIndices.end())
340         aLabelsToRemove.Append(aLabIter.Value());
341     }
342     // remove labels
343     for(aLabIter.Initialize(aLabelsToRemove); aLabIter.More(); aLabIter.Next()) {
344       ObjectPtr anObj = aDoc->objects()->object(aLabIter.Value());
345       if (anObj.get()) {
346         myRef->Remove(aLabIter.Value());
347         REMOVE_BACK_REF(anObj);
348       }
349     }
350     if (!aLabelsToRemove.IsEmpty()) {
351       owner()->data()->sendAttributeUpdated(this);
352     }
353   }
354 }
355
356 Model_AttributeRefList::Model_AttributeRefList(TDF_Label& theLabel)
357 {
358   myLab = theLabel;
359   reinit();
360 }
361
362 void Model_AttributeRefList::reinit()
363 {
364   myIsInitialized = myLab.FindAttribute(TDataStd_ReferenceList::GetID(), myRef) == Standard_True;
365   if (!myIsInitialized) {
366     myRef = TDataStd_ReferenceList::Set(myLab);
367   }
368   if (!myLab.FindAttribute(TDataStd_ExtStringList::GetID(), myExtDocRef)) {
369     myExtDocRef = TDataStd_ExtStringList::Set(myLab);
370   }
371 }