--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: ModelAPI_AttributeRefAttrList.cxx
+// Created: 8 May 2014
+// Author: Mikhail PONIKAROV
+
+#include "Model_AttributeRefAttrList.h"
+#include "Model_Application.h"
+#include "Model_Data.h"
+#include "Model_Objects.h"
+#include <ModelAPI_Feature.h>
+#include <TDF_ListIteratorOfLabelList.hxx>
+#include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
+
+using namespace std;
+
+void Model_AttributeRefAttrList::append(ObjectPtr theObject)
+{
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
+ myRef->Append(aData->label().Father()); // store label of the object
+ myIDs->Append(""); // for the object store an empty string
+ // do it before the transaction finish to make just created/removed objects know dependencies
+ // and reference from composite feature is removed automatically
+ ADD_BACK_REF(theObject);
+
+ owner()->data()->sendAttributeUpdated(this);
+}
+
+void Model_AttributeRefAttrList::append(AttributePtr theAttr)
+{
+ std::shared_ptr<Model_Data> aData =
+ std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
+ myRef->Append(aData->label().Father()); // store label of the object
+ myIDs->Append(theAttr->id().c_str()); // store the ID of the referenced attribute
+ // do it before the transaction finish to make just created/removed objects know dependencies
+ // and reference from composite feature is removed automatically
+ ADD_BACK_REF(theAttr->owner());
+
+ owner()->data()->sendAttributeUpdated(this);
+}
+
+void Model_AttributeRefAttrList::remove(ObjectPtr theObject)
+{
+ TDF_Label aTheObjLab;
+ if (theObject.get() != NULL) {
+ aTheObjLab = std::dynamic_pointer_cast<Model_Data>(theObject->data())->label().Father();
+ }
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ // remove from the both lists by clearing the list and then appending one by one
+ // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
+ TDF_LabelList aRefList = myRef->List();
+ myRef->Clear();
+ TDataStd_ListOfExtendedString anIDList = myIDs->List();
+ myIDs->Clear();
+ bool aOneisDeleted = false;
+ TDF_ListIteratorOfLabelList aRefIter(aRefList);
+ TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
+ for (; aRefIter.More(); aRefIter.Next(), anIDIter.Next()) {
+ // append now only not removed
+ if (aOneisDeleted || aRefIter.Value() != aTheObjLab || !anIDIter.Value().IsEmpty() ||
+ (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL)) {
+ myRef->Append(aRefIter.Value());
+ myIDs->Append(anIDIter.Value());
+ } else if (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL) {
+ aOneisDeleted = true;
+ }
+ }
+ if (aOneisDeleted) {
+ REMOVE_BACK_REF(theObject);
+ owner()->data()->sendAttributeUpdated(this);
+ }
+}
+
+void Model_AttributeRefAttrList::remove(AttributePtr theAttr)
+{
+ TDF_Label aTheObjLab;
+ if (theAttr->owner().get() != NULL) {
+ aTheObjLab = std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data())->label().Father();
+ }
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ // remove from the both lists by clearing the list and then appending one by one
+ // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
+ TDF_LabelList aRefList = myRef->List();
+ myRef->Clear();
+ TDataStd_ListOfExtendedString anIDList = myIDs->List();
+ myIDs->Clear();
+ bool aOneisDeleted = false;
+ TDF_ListIteratorOfLabelList aRefIter(aRefList);
+ TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
+ for (; aRefIter.More(); aRefIter.Next(), anIDIter.Next()) {
+ if (aOneisDeleted || anIDIter.Value() != theAttr->id().c_str() || // append now only not removed
+ aRefIter.Value() != aTheObjLab || // append now only not removed
+ (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL)) {
+ myRef->Append(aRefIter.Value());
+ myIDs->Append(anIDIter.Value());
+ } else if (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL) {
+ aOneisDeleted = true;
+ }
+ }
+ if (aOneisDeleted) {
+ REMOVE_BACK_REF(theAttr->owner());
+ owner()->data()->sendAttributeUpdated(this);
+ }
+}
+
+void Model_AttributeRefAttrList::clear()
+{
+ std::list<std::pair<ObjectPtr, AttributePtr> > anOldList = list();
+ myRef->Clear();
+ myIDs->Clear();
+ std::list<std::pair<ObjectPtr, AttributePtr> >::iterator anOldIter = anOldList.begin();
+ for(; anOldIter != anOldList.end(); anOldIter++) {
+ REMOVE_BACK_REF((anOldIter->first));
+ }
+ owner()->data()->sendAttributeUpdated(this);
+}
+
+int Model_AttributeRefAttrList::size() const
+{
+ return myRef->Extent();
+}
+
+bool Model_AttributeRefAttrList::isInitialized()
+{
+ if (size() == 0) { // empty list is not initialized list: sketch will be not valid after add/undo
+ return false;
+ }
+ return ModelAPI_AttributeRefAttrList::isInitialized();
+}
+
+std::list<std::pair<ObjectPtr, AttributePtr> > Model_AttributeRefAttrList::list()
+{
+ std::list<std::pair<ObjectPtr, AttributePtr> > aResult;
+ std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
+ owner()->document());
+ if (aDoc) {
+ const TDF_LabelList& aList = myRef->List();
+ const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
+ TDF_ListIteratorOfLabelList aLIter(aList);
+ TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
+ for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
+ ObjectPtr anObj;
+ if (!aLIter.Value().IsNull())
+ anObj = aDoc->objects()->object(aLIter.Value());
+ aResult.push_back(std::pair<ObjectPtr, AttributePtr>(anObj,
+ anObj->data()->attribute(TCollection_AsciiString(anIDIter.Value()).ToCString())));
+ }
+ }
+ return aResult;
+}
+
+bool Model_AttributeRefAttrList::isInList(const ObjectPtr& theObj)
+{
+ if(!theObj.get()) {
+ return false;
+ }
+ std::list<ObjectPtr> aResult;
+ std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
+ owner()->document());
+ if (aDoc) {
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
+ if (aData.get() && aData->isValid()) {
+ TDF_Label anObjLab = aData->label().Father();
+ const TDF_LabelList& aList = myRef->List();
+ const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
+ TDF_ListIteratorOfLabelList aLIter(aList);
+ TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
+ for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
+ if (anIDIter.Value().IsEmpty() && aLIter.Value().IsEqual(anObjLab)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool Model_AttributeRefAttrList::isInList(const AttributePtr& theAttr)
+{
+ if (!theAttr->owner().get()) {
+ return false;
+ }
+ std::list<ObjectPtr> aResult;
+ std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
+ owner()->document());
+ if (aDoc) {
+ std::shared_ptr<Model_Data> aData =
+ std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
+ if (aData.get() && aData->isValid()) {
+ TDF_Label anObjLab = aData->label().Father();
+ const TDF_LabelList& aList = myRef->List();
+ const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
+ TDF_ListIteratorOfLabelList aLIter(aList);
+ TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
+ for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
+ if (anIDIter.Value() == theAttr->id().c_str() && aLIter.Value().IsEqual(anObjLab)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool Model_AttributeRefAttrList::isAttribute(const int theIndex) const
+{
+ const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
+ TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
+ int anIndex = -1;
+ for (; anIDIter.More(); anIDIter.Next()) {
+ anIndex++;
+ if (anIndex == theIndex) {
+ return !anIDIter.Value().IsEmpty();
+ }
+ }
+ return false;
+}
+
+ObjectPtr Model_AttributeRefAttrList::object(const int theIndex) const
+{
+ std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
+ owner()->document());
+ if (aDoc) {
+ const TDF_LabelList& aList = myRef->List();
+ int anIndex = -1;
+ for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
+ anIndex++;
+ if (anIndex == theIndex) {
+ if (aLIter.Value().IsNull()) { // null label => null sub
+ return ObjectPtr();
+ }
+ return aDoc->objects()->object(aLIter.Value());
+ }
+ }
+ }
+ return ObjectPtr();
+}
+
+AttributePtr Model_AttributeRefAttrList::attribute(const int theIndex) const
+{
+ std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
+ owner()->document());
+ if (aDoc) {
+ int anIndex = -1;
+ const TDF_LabelList& aList = myRef->List();
+ const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
+ TDF_ListIteratorOfLabelList aLIter(aList);
+ TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
+ for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
+ anIndex++;
+ if (anIndex == theIndex) {
+ if (aLIter.Value().IsNull()) { // null label => null sub
+ return AttributePtr();
+ }
+ return aDoc->objects()->object(aLIter.Value())->data()->
+ attribute(TCollection_AsciiString(anIDIter.Value().ToExtString()).ToCString());
+ }
+ }
+ }
+ return AttributePtr();
+}
+
+void Model_AttributeRefAttrList::removeLast()
+{
+ // remove from the both lists by clearing the list and then appending one by one
+ // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
+ std::set<int> aLastSet;
+ aLastSet.insert(size() - 1);
+ remove(aLastSet);
+}
+
+void Model_AttributeRefAttrList::remove(const std::set<int>& theIndices)
+{
+ std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
+ owner()->document());
+ if (aDoc && !myRef->IsEmpty()) {
+ // remove from the both lists by clearing the list and then appending one by one
+ // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
+ TDF_LabelList aRefList = myRef->List();
+ myRef->Clear();
+ TDataStd_ListOfExtendedString anIDList = myIDs->List();
+ myIDs->Clear();
+ bool aOneisDeleted = false;
+ TDF_ListIteratorOfLabelList aRefIter(aRefList);
+ TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
+ for (int anIndex = 0; aRefIter.More(); aRefIter.Next(), anIDIter.Next(), anIndex++) {
+ if (theIndices.find(anIndex) == theIndices.end()) { // not found
+ myRef->Append(aRefIter.Value());
+ myIDs->Append(anIDIter.Value());
+ } else { // found, so need to update the dependencies
+ aOneisDeleted = true;
+ ObjectPtr anObj = aDoc->objects()->object(aRefIter.Value());
+ if (anObj.get()) {
+ myRef->Remove(aRefIter.Value());
+ REMOVE_BACK_REF(anObj);
+ }
+ }
+ }
+ if (aOneisDeleted) {
+ owner()->data()->sendAttributeUpdated(this);
+ }
+ }
+}
+
+Model_AttributeRefAttrList::Model_AttributeRefAttrList(TDF_Label& theLabel)
+{
+ myIsInitialized = theLabel.FindAttribute(TDataStd_ReferenceList::GetID(), myRef) == Standard_True;
+ if (!myIsInitialized) {
+ myRef = TDataStd_ReferenceList::Set(theLabel);
+ myIDs = TDataStd_ExtStringList::Set(theLabel);
+ } else {
+ theLabel.FindAttribute(TDataStd_ExtStringList::GetID(), myIDs);
+ }
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: Model_AttributeRefAttrList.h
+// Created: 20 Jan 2016
+// Author: Mikhail PONIKAROV
+
+#ifndef Model_AttributeRefAttrList_H_
+#define Model_AttributeRefAttrList_H_
+
+#include "Model.h"
+#include "ModelAPI_AttributeRefAttrList.h"
+#include "ModelAPI_Feature.h"
+
+#include <TDataStd_ReferenceList.hxx>
+#include <TDataStd_ExtStringList.hxx>
+
+/**\class Model_AttributeRefAttrList
+ * \ingroup DataModel
+ * \brief Attribute that contains list of references to features (located in the same document)
+ * or references to attributes of the features (list of AttributeRefAttr)
+ */
+
+class Model_AttributeRefAttrList : public ModelAPI_AttributeRefAttrList
+{
+ Handle_TDataStd_ReferenceList myRef; ///< references to the features labels
+ Handle_TDataStd_ExtStringList myIDs; ///< the referenced attributes IDs (empty for just object)
+ public:
+ /// Appends the feature to the end of a list
+ MODEL_EXPORT virtual void append(ObjectPtr theObject);
+ /// Appends the attribute to the end of a list
+ MODEL_EXPORT virtual void append(AttributePtr theAttr);
+
+ /// Erases the first meet of the feature in the list
+ MODEL_EXPORT virtual void remove(ObjectPtr theObject);
+ /// Erases the first meet of the attribute in the list
+ MODEL_EXPORT virtual void remove(AttributePtr theAttr);
+
+ /// Removes all references from the list
+ MODEL_EXPORT virtual void clear();
+
+ /// Returns number of features in the list
+ MODEL_EXPORT virtual int size() const;
+
+ /// Returns the list of features and attributes (if it is reference to the attribute)
+ MODEL_EXPORT virtual std::list<std::pair<ObjectPtr, AttributePtr> > list();
+
+ /// Returns true if the object is in list
+ MODEL_EXPORT virtual bool isInList(const ObjectPtr& theObj);
+ /// Returns true if the attribute is in list
+ MODEL_EXPORT virtual bool isInList(const AttributePtr& theObj);
+
+ /// Returns true if this is reference to an attribute, not just object
+ MODEL_EXPORT virtual bool isAttribute(const int theIndex) const;
+
+ /// Returns the referenced object by the zero-based index
+ ///\param theIndex zero-based index in the list
+ MODEL_EXPORT virtual ObjectPtr object(const int theIndex) const;
+ /// Returns the referenced attribute by the zero-based index
+ ///\param theIndex zero-based index in the list
+ MODEL_EXPORT virtual AttributePtr attribute(const int theIndex) const;
+
+ /// Removes the last element in the list.
+ MODEL_EXPORT virtual void removeLast() = 0;
+
+ /// Removes the elements from the list.
+ /// \param theIndices a list of indices of elements to be removed
+ MODEL_EXPORT virtual void remove(const std::set<int>& theIndices);
+
+ /// Returns true if attribute was initialized by some value
+ MODEL_EXPORT virtual bool isInitialized();
+ protected:
+ /// Objects are created for features automatically
+ MODEL_EXPORT Model_AttributeRefAttrList(TDF_Label& theLabel);
+
+ friend class Model_Data;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: ModelAPI_AttributeRefAttrList.h
+// Created: 20 Jan 2016
+// Author: Mikhail PONIKAROV
+
+#ifndef ModelAPI_AttributeRefAttrList_H_
+#define ModelAPI_AttributeRefAttrList_H_
+
+#include "ModelAPI_Attribute.h"
+#include "ModelAPI_Feature.h"
+#include <list>
+
+/**\class ModelAPI_AttributeRefAttrList
+ * \ingroup DataModel
+ * \brief Attribute that contains list of references to features (located in the same document)
+ * or references to attributes of the features (list of AttributeRefAttr)
+ */
+
+class ModelAPI_AttributeRefAttrList : public ModelAPI_Attribute
+{
+ public:
+ /// Returns the type of this class of attributes
+ MODELAPI_EXPORT static std::string typeId()
+ {
+ return "RefAttrList";
+ }
+
+ /// Returns the type of this class of attributes, not static method
+ MODELAPI_EXPORT virtual std::string attributeType();
+
+ /// Appends the feature to the end of a list
+ virtual void append(ObjectPtr theObject) = 0;
+ /// Appends the attribute to the end of a list
+ virtual void append(AttributePtr theAttr) = 0;
+
+ /// Erases the first meet of the feature in the list
+ virtual void remove(ObjectPtr theObject) = 0;
+ /// Erases the first meet of the attribute in the list
+ virtual void remove(AttributePtr theAttr) = 0;
+
+ /// Removes all references from the list
+ virtual void clear() = 0;
+
+ /// Returns number of features in the list
+ ///\param theWithEmpty if it is false, returns the number of not-empty referenced objects
+ virtual int size(const bool theWithEmpty = true) const = 0;
+
+ /// Returns the list of features and attributes (if it is reference to the attribute)
+ virtual std::list<std::pair<ObjectPtr, AttributePtr> > list() = 0;
+
+ /// Returns true if the object is in list
+ virtual bool isInList(const ObjectPtr& theObj) = 0;
+ /// Returns true if the attribute is in list
+ virtual bool isInList(const AttributePtr& theObj) = 0;
+
+ /// Returns true if this is reference to an attribute, not just object
+ virtual bool isAttribute(const int theIndex) const = 0;
+
+ /// Returns the referenced object by the zero-based index
+ ///\param theIndex zero-based index in the list
+ virtual ObjectPtr object(const int theIndex) const = 0;
+ /// Returns the referenced attribute by the zero-based index
+ ///\param theIndex zero-based index in the list
+ virtual AttributePtr attribute(const int theIndex) const = 0;
+
+ /// Removes the last element in the list.
+ virtual void removeLast() = 0;
+
+ /// Removes the elements from the list.
+ /// \param theIndices a list of indices of elements to be removed
+ virtual void remove(const std::set<int>& theIndices) = 0;
+
+ MODELAPI_EXPORT virtual ~ModelAPI_AttributeRefAttrList();
+ protected:
+ /// Objects are created for features automatically
+ MODELAPI_EXPORT ModelAPI_AttributeRefAttrList();
+
+};
+
+typedef std::shared_ptr<ModelAPI_AttributeRefAttrList> AttributeRefAttrListPtr;
+
+#endif