Salome HOME
Fix for the issue #1103
[modules/shaper.git] / src / Model / Model_Data.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        Model_Data.hxx
4 // Created:     21 Mar 2014
5 // Author:      Mikhail PONIKAROV
6
7 #include <Model_Data.h>
8 #include <Model_AttributeDocRef.h>
9 #include <Model_AttributeInteger.h>
10 #include <Model_AttributeDouble.h>
11 #include <Model_AttributeReference.h>
12 #include <Model_AttributeRefAttr.h>
13 #include <Model_AttributeRefList.h>
14 #include <Model_AttributeBoolean.h>
15 #include <Model_AttributeString.h>
16 #include <Model_AttributeSelection.h>
17 #include <Model_AttributeSelectionList.h>
18 #include <Model_AttributeIntArray.h>
19 #include <Model_Events.h>
20 #include <Model_Expression.h>
21 #include <ModelAPI_Feature.h>
22 #include <ModelAPI_Result.h>
23 #include <ModelAPI_ResultParameter.h>
24 #include <ModelAPI_Validator.h>
25 #include <ModelAPI_Session.h>
26 #include <ModelAPI_ResultPart.h>
27 #include <ModelAPI_ResultCompSolid.h>
28 #include <ModelAPI_Tools.h>
29 #include <Model_Validator.h>
30
31 #include <GeomDataAPI_Point.h>
32 #include <GeomDataAPI_Point2D.h>
33
34 #include <GeomData_Point.h>
35 #include <GeomData_Point2D.h>
36 #include <GeomData_Dir.h>
37 #include <Events_Loop.h>
38 #include <Events_Error.h>
39
40 #include <TDataStd_Name.hxx>
41 #include <TDataStd_AsciiString.hxx>
42 #include <TDataStd_IntegerArray.hxx>
43 #include <TDF_AttributeIterator.hxx>
44 #include <TDF_ChildIterator.hxx>
45 #include <TDF_RelocationTable.hxx>
46 #include <TColStd_HArray1OfByte.hxx>
47
48 #include <string>
49
50 // myLab contains:
51 // TDataStd_Name - name of the object
52 // TDataStd_IntegerArray - state of the object execution, transaction ID of update
53 // TDataStd_BooleanArray - array of flags of this data:
54 //                             0 - is in history or not
55 static const int kFlagInHistory = 0;
56 //                             1 - is displayed or not
57 static const int kFlagDisplayed = 1;
58 //                             2 - is deleted (for results) or not
59 static const int kFlagDeleted = 2;
60
61 // invalid data
62 const static std::shared_ptr<ModelAPI_Data> kInvalid(new Model_Data());
63
64 Model_Data::Model_Data() : mySendAttributeUpdated(true)
65 {
66 }
67
68 void Model_Data::setLabel(TDF_Label theLab)
69 {
70   myLab = theLab;
71   // set or get the default flags
72   if (!myLab.FindAttribute(TDataStd_BooleanArray::GetID(), myFlags)) {
73     // set default values if not found
74     myFlags = TDataStd_BooleanArray::Set(myLab, 0, 2);
75     myFlags->SetValue(kFlagInHistory, Standard_True); // is in history by default is true
76     myFlags->SetValue(kFlagDisplayed, Standard_True); // is displayed by default is true
77     myFlags->SetValue(kFlagDeleted, Standard_False); // is deleted by default is false
78   } else if (myFlags->Length() != 3) { // for old formats support
79     Standard_Boolean aFlag0 = myFlags->Upper() >= 0 ? myFlags->Value(0) : Standard_True;
80     Standard_Boolean aFlag1 = myFlags->Upper() >= 1 ? myFlags->Value(1) : Standard_True;
81     Standard_Boolean aFlag2 = myFlags->Upper() >= 2 ? myFlags->Value(2) : Standard_True;
82     Handle(TColStd_HArray1OfByte) aNewArray = new TColStd_HArray1OfByte(0, 2);
83     myFlags->SetInternalArray(aNewArray);
84     myFlags->SetValue(0, aFlag0); 
85     myFlags->SetValue(1, aFlag1); 
86     myFlags->SetValue(2, aFlag2); 
87   }
88 }
89
90 std::string Model_Data::name()
91 {
92   Handle(TDataStd_Name) aName;
93   if (myLab.FindAttribute(TDataStd_Name::GetID(), aName))
94     return std::string(TCollection_AsciiString(aName->Get()).ToCString());
95   return "";  // not defined
96 }
97
98 void Model_Data::setName(const std::string& theName)
99 {
100   bool isModified = false;
101   std::string anOldName = name();
102   Handle(TDataStd_Name) aName;
103   if (!myLab.FindAttribute(TDataStd_Name::GetID(), aName)) {
104     TDataStd_Name::Set(myLab, theName.c_str());
105     isModified = true;
106   } else {
107     isModified = !aName->Get().IsEqual(theName.c_str());
108     if (isModified)
109       aName->Set(theName.c_str());
110   }
111   if (mySendAttributeUpdated && isModified)
112     ModelAPI_ObjectRenamedMessage::send(myObject, anOldName, theName, this);
113 }
114
115 AttributePtr Model_Data::addAttribute(const std::string& theID, const std::string theAttrType)
116 {
117   AttributePtr aResult;
118   TDF_Label anAttrLab = myLab.FindChild(myAttrs.size() + 1);
119   ModelAPI_Attribute* anAttr = 0;
120   if (theAttrType == ModelAPI_AttributeDocRef::typeId()) {
121     anAttr = new Model_AttributeDocRef(anAttrLab);
122   } else if (theAttrType == Model_AttributeInteger::typeId()) {
123     anAttr = new Model_AttributeInteger(anAttrLab);
124   } else if (theAttrType == ModelAPI_AttributeDouble::typeId()) {
125     Model_AttributeDouble* anAttribute = new Model_AttributeDouble(anAttrLab);
126     TDF_Label anExpressionLab = anAttrLab.FindChild(1);
127     anAttribute->myExpression.reset(new Model_Expression(anExpressionLab));
128     anAttribute->myIsInitialized = anAttribute->myIsInitialized && anAttribute->myExpression->isInitialized(); 
129     anAttr = anAttribute;
130   } else if (theAttrType == Model_AttributeBoolean::typeId()) {
131     anAttr = new Model_AttributeBoolean(anAttrLab);
132   } else if (theAttrType == Model_AttributeString::typeId()) {
133     anAttr = new Model_AttributeString(anAttrLab);
134   } else if (theAttrType == ModelAPI_AttributeReference::typeId()) {
135     anAttr = new Model_AttributeReference(anAttrLab);
136   } else if (theAttrType == ModelAPI_AttributeSelection::typeId()) {
137     anAttr = new Model_AttributeSelection(anAttrLab);
138   } else if (theAttrType == ModelAPI_AttributeSelectionList::typeId()) {
139     anAttr = new Model_AttributeSelectionList(anAttrLab);
140   } else if (theAttrType == ModelAPI_AttributeRefAttr::typeId()) {
141     anAttr = new Model_AttributeRefAttr(anAttrLab);
142   } else if (theAttrType == ModelAPI_AttributeRefList::typeId()) {
143     anAttr = new Model_AttributeRefList(anAttrLab);
144   } else if (theAttrType == ModelAPI_AttributeIntArray::typeId()) {
145     anAttr = new Model_AttributeIntArray(anAttrLab);
146   } 
147   // create also GeomData attributes here because only here the OCAF structure is known
148   else if (theAttrType == GeomData_Point::typeId()) {
149     GeomData_Point* anAttribute = new GeomData_Point(anAttrLab);
150     for (int aComponent = 0; aComponent < GeomData_Point::NUM_COMPONENTS; ++aComponent) {
151       TDF_Label anExpressionLab = anAttrLab.FindChild(aComponent + 1);
152       anAttribute->myExpression[aComponent].reset(new Model_Expression(anExpressionLab));
153       anAttribute->myIsInitialized = anAttribute->myIsInitialized && anAttribute->myExpression[aComponent]->isInitialized(); 
154     }
155     anAttr = anAttribute;
156   } else if (theAttrType == GeomData_Dir::typeId()) {
157     anAttr = new GeomData_Dir(anAttrLab);
158   } else if (theAttrType == GeomData_Point2D::typeId()) {
159     GeomData_Point2D* anAttribute = new GeomData_Point2D(anAttrLab);
160     for (int aComponent = 0; aComponent < GeomData_Point2D::NUM_COMPONENTS; ++aComponent) {
161       TDF_Label anExpressionLab = anAttrLab.FindChild(aComponent + 1);
162       anAttribute->myExpression[aComponent].reset(new Model_Expression(anExpressionLab));
163       anAttribute->myIsInitialized = anAttribute->myIsInitialized && anAttribute->myExpression[aComponent]->isInitialized(); 
164     }
165     anAttr = anAttribute;
166   }
167   if (anAttr) {
168     aResult = std::shared_ptr<ModelAPI_Attribute>(anAttr);
169     myAttrs[theID] = aResult;
170     anAttr->setObject(myObject);
171     anAttr->setID(theID);
172   } else {
173     Events_Error::send("Can not create unknown type of attribute " + theAttrType);
174   }
175   return aResult;
176 }
177
178 // macro for gthe generic returning of the attribute by the ID
179 #define GET_ATTRIBUTE_BY_ID(ATTR_TYPE, METHOD_NAME) \
180   std::shared_ptr<ATTR_TYPE> Model_Data::METHOD_NAME(const std::string& theID) { \
181     std::shared_ptr<ATTR_TYPE> aRes; \
182     std::map<std::string, AttributePtr >::iterator aFound = \
183       myAttrs.find(theID); \
184     if (aFound != myAttrs.end()) { \
185       aRes = std::dynamic_pointer_cast<ATTR_TYPE>(aFound->second); \
186     } \
187     return aRes; \
188   }
189 // implement nice getting methods for all ModelAPI attributes
190 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeDocRef, document);
191 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeDouble, real);
192 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeInteger, integer);
193 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeBoolean, boolean);
194 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeString, string);
195 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeReference, reference);
196 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeSelection, selection);
197 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeSelectionList, selectionList);
198 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeRefAttr, refattr);
199 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeRefList, reflist);
200 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeIntArray, intArray);
201
202 std::shared_ptr<ModelAPI_Attribute> Model_Data::attribute(const std::string& theID)
203 {
204   std::shared_ptr<ModelAPI_Attribute> aResult;
205   if (myAttrs.find(theID) == myAttrs.end())  // no such attribute
206     return aResult;
207   return myAttrs[theID];
208 }
209
210 const std::string& Model_Data::id(const std::shared_ptr<ModelAPI_Attribute>& theAttr)
211 {
212   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = 
213     myAttrs.begin();
214   for (; anAttr != myAttrs.end(); anAttr++) {
215     if (anAttr->second == theAttr)
216       return anAttr->first;
217   }
218   // not found
219   static std::string anEmpty;
220   return anEmpty;
221 }
222
223 bool Model_Data::isEqual(const std::shared_ptr<ModelAPI_Data>& theData)
224 {
225   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theData);
226   if (aData)
227     return myLab.IsEqual(aData->myLab) == Standard_True ;
228   return false;
229 }
230
231 bool Model_Data::isValid()
232 {
233   return !myLab.IsNull() && myLab.HasAttribute();
234 }
235
236 std::list<std::shared_ptr<ModelAPI_Attribute> > Model_Data::attributes(const std::string& theType)
237 {
238   std::list<std::shared_ptr<ModelAPI_Attribute> > aResult;
239   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrsIter = 
240     myAttrs.begin();
241   for (; anAttrsIter != myAttrs.end(); anAttrsIter++) {
242     if (theType.empty() || anAttrsIter->second->attributeType() == theType) {
243       aResult.push_back(anAttrsIter->second);
244     }
245   }
246   return aResult;
247 }
248
249 std::list<std::string> Model_Data::attributesIDs(const std::string& theType) 
250 {
251   std::list<std::string> aResult;
252   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrsIter = 
253     myAttrs.begin();
254   for (; anAttrsIter != myAttrs.end(); anAttrsIter++) {
255     if (theType.empty() || anAttrsIter->second->attributeType() == theType) {
256       aResult.push_back(anAttrsIter->first);
257     }
258   }
259   return aResult;
260 }
261
262 void Model_Data::sendAttributeUpdated(ModelAPI_Attribute* theAttr)
263 {
264   theAttr->setInitialized();
265   if (theAttr->isArgument()) {
266     static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
267     ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent);
268     if (mySendAttributeUpdated && myObject) {
269       myObject->attributeChanged(theAttr->id());
270     }
271   }
272 }
273
274 void Model_Data::blockSendAttributeUpdated(const bool theBlock)
275 {
276   mySendAttributeUpdated = !theBlock;
277 }
278
279 void Model_Data::erase()
280 {
281   if (!myLab.IsNull())
282     myLab.ForgetAllAttributes();
283 }
284
285 // indexes in the state array
286 enum StatesIndexes {
287   STATE_INDEX_STATE = 1, // the state type itself
288   STATE_INDEX_TRANSACTION = 2, // transaction ID
289 };
290
291 /// Returns the label array, initialises it by default values if not exists
292 static Handle(TDataStd_IntegerArray) stateArray(TDF_Label& theLab)
293 {
294   Handle(TDataStd_IntegerArray) aStateArray;
295   if (!theLab.FindAttribute(TDataStd_IntegerArray::GetID(), aStateArray)) {
296     aStateArray = TDataStd_IntegerArray::Set(theLab, 1, 2);
297     aStateArray->SetValue(STATE_INDEX_STATE, ModelAPI_StateMustBeUpdated); // default state
298     aStateArray->SetValue(STATE_INDEX_TRANSACTION, 0); // default transaction ID (not existing)
299   }
300   return aStateArray;
301 }
302
303 void Model_Data::execState(const ModelAPI_ExecState theState)
304 {
305   if (theState != ModelAPI_StateNothing) {
306     if (stateArray(myLab)->Value(STATE_INDEX_STATE) != (int)theState) {
307       stateArray(myLab)->SetValue(STATE_INDEX_STATE, (int)theState);
308     }
309     // send signal even if the new value corresponds to the one in data model: undo issue 980
310     static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_ERROR_CHANGED);
311     ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent, false);
312   }
313 }
314
315 ModelAPI_ExecState Model_Data::execState()
316 {
317   return ModelAPI_ExecState(stateArray(myLab)->Value(STATE_INDEX_STATE));
318 }
319
320 int Model_Data::updateID()
321 {
322   return stateArray(myLab)->Value(STATE_INDEX_TRANSACTION);
323 }
324
325 void Model_Data::setUpdateID(const int theID)
326 {
327   stateArray(myLab)->SetValue(STATE_INDEX_TRANSACTION, theID);
328 }
329
330 void Model_Data::setError(const std::string& theError, bool theSend)
331 {
332   execState(ModelAPI_StateExecFailed);
333   if (theSend) {
334     Events_Error::send(theError);
335   }
336   TDataStd_AsciiString::Set(myLab, theError.c_str());
337   static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_ERROR_CHANGED);
338   ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent, false);
339 }
340
341 void Model_Data::eraseErrorString()
342 {
343   myLab.ForgetAttribute(TDataStd_AsciiString::GetID());
344 }
345
346 std::string Model_Data::error() const
347 {
348   Handle(TDataStd_AsciiString) anErrorAttr;
349   if (myLab.FindAttribute(TDataStd_AsciiString::GetID(), anErrorAttr)) {
350     return std::string(anErrorAttr->Get().ToCString());
351   }
352   return std::string();
353 }
354
355 int Model_Data::featureId() const
356 {
357   return myLab.Father().Tag(); // tag of the feature label
358 }
359
360 void Model_Data::eraseBackReferences()
361 {
362   myRefsToMe.clear();
363   std::shared_ptr<ModelAPI_Result> aRes = 
364     std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
365   if (aRes)
366     aRes->setIsConcealed(false);
367 }
368
369 void Model_Data::removeBackReference(FeaturePtr theFeature, std::string theAttrID)
370 {
371   AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
372   removeBackReference(anAttribute);
373 }
374
375 void Model_Data::removeBackReference(AttributePtr theAttr)
376 {
377   if (myRefsToMe.find(theAttr) == myRefsToMe.end())
378     return;
379
380   myRefsToMe.erase(theAttr);
381
382   // remove concealment immideately: on deselection it must be posible to reselect in GUI the same
383   FeaturePtr aFeatureOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttr->owner());
384   if (aFeatureOwner.get() &&
385     ModelAPI_Session::get()->validators()->isConcealed(aFeatureOwner->getKind(), theAttr->id())) {
386     updateConcealmentFlag();
387   }
388 }
389
390 void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID, 
391    const bool theApplyConcealment)
392 {
393   // it is possible to add the same attribute twice: may be last time the owner was not Stable...
394   AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
395   if (myRefsToMe.find(anAttribute) == myRefsToMe.end())
396     myRefsToMe.insert(theFeature->data()->attribute(theAttrID));
397
398   if (theApplyConcealment &&  theFeature->isStable() && 
399       ModelAPI_Session::get()->validators()->isConcealed(theFeature->getKind(), theAttrID)) {
400     std::shared_ptr<ModelAPI_Result> aRes = 
401       std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
402     // the second condition is for history upper than concealment causer, so the feature result may
403     // be displayed and previewed; also for avoiding of quick show/hide on history
404     // moving deep down
405     if (aRes && !theFeature->isDisabled()) {
406       aRes->setIsConcealed(true);
407     }
408   }
409 }
410
411 void Model_Data::updateConcealmentFlag()
412 {
413   std::set<AttributePtr>::iterator aRefsIter = myRefsToMe.begin();
414   for(; aRefsIter != myRefsToMe.end(); aRefsIter++) {
415     if (aRefsIter->get()) {
416       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefsIter)->owner());
417       if (aFeature.get() && !aFeature->isDisabled() && aFeature->isStable()) {
418         if (ModelAPI_Session::get()->validators()->isConcealed(
419               aFeature->getKind(), (*aRefsIter)->id())) {
420           std::shared_ptr<ModelAPI_Result> aRes = 
421             std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
422           if (aRes.get()) {
423             aRes->setIsConcealed(true); // set concealed
424           }
425           return;
426         }
427       }
428     }
429   }
430   std::shared_ptr<ModelAPI_Result> aRes = 
431     std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
432   if (aRes.get()) {
433     aRes->setIsConcealed(false);
434   }
435 }
436
437 std::set<std::string> set_union(const std::set<std::string>& theLeft, 
438                                 const std::set<std::string>& theRight)
439 {
440   std::set<std::string> aResult;
441   aResult.insert(theLeft.begin(), theLeft.end());
442   aResult.insert(theRight.begin(), theRight.end());
443   return aResult;
444 }
445
446 std::set<std::string> usedParameters(const AttributePointPtr& theAttribute)
447 {
448   std::set<std::string> anUsedParameters;
449   for (int aComponent = 0; aComponent < 3; ++aComponent)
450     anUsedParameters = set_union(anUsedParameters, theAttribute->usedParameters(aComponent));
451   return anUsedParameters;
452 }
453
454 std::set<std::string> usedParameters(const AttributePoint2DPtr& theAttribute)
455 {
456   std::set<std::string> anUsedParameters;
457   for (int aComponent = 0; aComponent < 2; ++aComponent)
458     anUsedParameters = set_union(anUsedParameters, theAttribute->usedParameters(aComponent));
459   return anUsedParameters;
460 }
461
462 std::list<ResultParameterPtr> findVariables(const std::set<std::string>& theParameters, 
463                                             const DocumentPtr& theDocument)
464 {
465   std::list<ResultParameterPtr> aResult;
466   std::set<std::string>::const_iterator aParamIt = theParameters.cbegin();
467   for (; aParamIt != theParameters.cend(); ++aParamIt) {
468     const std::string& aName = *aParamIt;
469     double aValue;
470     ResultParameterPtr aParam;
471     if (ModelAPI_Tools::findVariable(aName, aValue, aParam, theDocument))
472       aResult.push_back(aParam);
473   }
474   return aResult;
475 }
476
477 void Model_Data::referencesToObjects(
478   std::list<std::pair<std::string, std::list<ObjectPtr> > >& theRefs)
479 {
480   static Model_ValidatorsFactory* aValidators = 
481     static_cast<Model_ValidatorsFactory*>(ModelAPI_Session::get()->validators());
482   FeaturePtr aMyFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(myObject);
483
484   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = myAttrs.begin();
485   std::list<ObjectPtr> aReferenced; // not inside of cycle to avoid excess memory management
486   for(; anAttr != myAttrs.end(); anAttr++) {
487     // skip not-case attributes, that really may refer to anything not-used (issue 671)
488     if (aMyFeature.get() && !aValidators->isCase(aMyFeature, anAttr->second->id()))
489       continue;
490
491     std::string aType = anAttr->second->attributeType();
492     if (aType == ModelAPI_AttributeReference::typeId()) { // reference to object
493       std::shared_ptr<ModelAPI_AttributeReference> aRef = std::dynamic_pointer_cast<
494           ModelAPI_AttributeReference>(anAttr->second);
495       aReferenced.push_back(aRef->value());
496     } else if (aType == ModelAPI_AttributeRefAttr::typeId()) { // reference to attribute or object
497       std::shared_ptr<ModelAPI_AttributeRefAttr> aRef = std::dynamic_pointer_cast<
498           ModelAPI_AttributeRefAttr>(anAttr->second);
499       aReferenced.push_back(aRef->isObject() ? aRef->object() : aRef->attr()->owner());
500     } else if (aType == ModelAPI_AttributeRefList::typeId()) { // list of references
501       aReferenced = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(anAttr->second)->list();
502     } else if (aType == ModelAPI_AttributeSelection::typeId()) { // selection attribute
503       std::shared_ptr<ModelAPI_AttributeSelection> aRef = std::dynamic_pointer_cast<
504           ModelAPI_AttributeSelection>(anAttr->second);
505       aReferenced.push_back(aRef->context());
506     } else if (aType == ModelAPI_AttributeSelectionList::typeId()) { // list of selection attributes
507       std::shared_ptr<ModelAPI_AttributeSelectionList> aRef = std::dynamic_pointer_cast<
508           ModelAPI_AttributeSelectionList>(anAttr->second);
509       for(int a = aRef->size() - 1; a >= 0; a--) {
510         aReferenced.push_back(aRef->value(a)->context());
511       }
512     } else if (aType == ModelAPI_AttributeDouble::typeId()) { // double attribute
513       AttributeDoublePtr anAttribute =
514           std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr->second);
515       std::set<std::string> anUsedParameters = anAttribute->usedParameters();
516       std::list<ResultParameterPtr> aParameters = findVariables(anUsedParameters, aMyFeature->document());
517       aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end());
518     } else if (aType == GeomDataAPI_Point::typeId()) { // point attribute
519       AttributePointPtr anAttribute =
520         std::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr->second);
521       std::set<std::string> anUsedParameters = usedParameters(anAttribute);
522       std::list<ResultParameterPtr> aParameters = findVariables(anUsedParameters, aMyFeature->document());
523       aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end());
524     } else if (aType == GeomDataAPI_Point2D::typeId()) { // point attribute
525       AttributePoint2DPtr anAttribute =
526         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->second);
527       std::set<std::string> anUsedParameters = usedParameters(anAttribute);
528       std::list<ResultParameterPtr> aParameters = findVariables(anUsedParameters, aMyFeature->document());
529       aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end());
530     } else
531       continue; // nothing to do, not reference
532
533     if (!aReferenced.empty()) {
534       theRefs.push_back(std::pair<std::string, std::list<ObjectPtr> >(anAttr->first, aReferenced));
535       aReferenced.clear();
536     }
537   }
538 }
539
540 /// makes copy of all attributes on the given label and all sub-labels
541 static void copyAttrs(TDF_Label theSource, TDF_Label theDestination) {
542   TDF_AttributeIterator anAttrIter(theSource);
543   for(; anAttrIter.More(); anAttrIter.Next()) {
544     Handle(TDF_Attribute) aTargetAttr;
545     if (!theDestination.FindAttribute(anAttrIter.Value()->ID(), aTargetAttr)) {
546       // create a new attribute if not yet exists in the destination
547             aTargetAttr = anAttrIter.Value()->NewEmpty();
548       theDestination.AddAttribute(aTargetAttr);
549     }
550     Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable(); // no relocation, empty map
551     anAttrIter.Value()->Paste(aTargetAttr, aRelocTable);
552   }
553   // copy the sub-labels content
554   TDF_ChildIterator aSubLabsIter(theSource);
555   for(; aSubLabsIter.More(); aSubLabsIter.Next()) {
556     copyAttrs(aSubLabsIter.Value(), theDestination.FindChild(aSubLabsIter.Value().Tag()));
557   }
558 }
559
560 void Model_Data::copyTo(std::shared_ptr<ModelAPI_Data> theTarget)
561 {
562   TDF_Label aTargetRoot = std::dynamic_pointer_cast<Model_Data>(theTarget)->label();
563   copyAttrs(myLab, aTargetRoot);
564   // make initialized the initialized attributes
565   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator aMyIter = myAttrs.begin();
566   for(; aMyIter != myAttrs.end(); aMyIter++) {
567     if (aMyIter->second->isInitialized()) {
568       theTarget->attribute(aMyIter->first)->setInitialized();
569     }
570   }
571 }
572
573 bool Model_Data::isInHistory()
574 {
575   return myFlags->Value(kFlagInHistory) == Standard_True;
576 }
577
578 void Model_Data::setIsInHistory(const bool theFlag)
579 {
580   return myFlags->SetValue(kFlagInHistory, theFlag);
581 }
582
583 bool Model_Data::isDeleted()
584 {
585   return myFlags->Value(kFlagDeleted) == Standard_True;
586 }
587
588 void Model_Data::setIsDeleted(const bool theFlag)
589 {
590   return myFlags->SetValue(kFlagDeleted, theFlag);
591 }
592
593 bool Model_Data::isDisplayed()
594 {
595   if (!myObject.get() || !myObject->document().get() || // object is in valid
596       myFlags->Value(kFlagDisplayed) != Standard_True) // or it was not displayed before
597     return false;
598   if (myObject->document()->isActive()) // for active documents it must be ok anyway
599     return true;
600   // any object from the root document except part result may be displayed
601   if (myObject->document() == ModelAPI_Session::get()->moduleDocument() &&
602       myObject->groupName() != ModelAPI_ResultPart::group())
603     return true;
604   return false;
605 }
606
607 void Model_Data::setDisplayed(const bool theDisplay)
608 {
609   if (theDisplay != isDisplayed()) {
610     myFlags->SetValue(kFlagDisplayed, theDisplay);
611     static Events_Loop* aLoop = Events_Loop::loop();
612     static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
613     static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
614     aECreator->sendUpdated(myObject, EVENT_DISP);
615   }
616 }
617
618 std::shared_ptr<ModelAPI_Data> Model_Data::invalidPtr()
619 {
620   return kInvalid;
621 }
622
623 std::shared_ptr<ModelAPI_Data> Model_Data::invalidData()
624 {
625   return kInvalid;
626 }
627
628 std::shared_ptr<ModelAPI_Object> Model_Data::owner()
629 {
630   return myObject;
631 }