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