-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: ModelAPI_AttributeRefList.cxx
-// Created: 8 May 2014
-// Author: Mikhail PONIKAROV
+// Copyright (C) 2014-2023 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
#include "Model_AttributeRefList.h"
#include "Model_Application.h"
#include <TDF_Tool.hxx>
#include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
-using namespace std;
-
void Model_AttributeRefList::append(ObjectPtr theObject)
{
if (owner()->document() == theObject->document()) {
myExtDocRef->Append(anEntry);
} else return; // something is wrong
+ if (myHashUsed) {
+ myHashObjects.insert(theObject);
+ myHashIndex[myRef->Extent() - 1] = theObject;
+ myHashIndexNoEmpty[int(myHashIndexNoEmpty.size())] = theObject;
+ }
+
// 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);
void Model_AttributeRefList::remove(ObjectPtr theObject)
{
+ eraseHash();
if (theObject.get() != NULL) {
if (owner()->document() == theObject->document()) {
std::shared_ptr<Model_Data> aData;
REMOVE_BACK_REF(theObject);
owner()->data()->sendAttributeUpdated(this);
} else {
+ // LCOV_EXCL_START
// create new lists because for the current moment remove one of the duplicated elements
// from the list is buggy
TDF_LabelList anOldList = myRef->List();
if (anExtIter.Value() == anIdString.str().c_str()) {
TDataStd_ListIteratorOfListOfExtendedString anExtIter2 = anExtIter;
anExtIter2.Next();
- if (anExtIter2.Value() == anEntry) { // fully maches, so, remove(don't copy)
+ if (anExtIter2.Value() == anEntry) { // fully matches, so, remove(don't copy)
aFound = true;
continue;
}
REMOVE_BACK_REF(theObject);
owner()->data()->sendAttributeUpdated(this);
}
+ // LCOV_EXCL_STOP
}
}
else { // in case of empty object remove, the first empty object is removed from the list
REMOVE_BACK_REF((*anOldIter));
}
myExtDocRef->Clear();
+ eraseHash();
owner()->data()->sendAttributeUpdated(this);
}
{
if (theWithEmpty)
return myRef->Extent();
+
+ if (myHashUsed)
+ return int(myHashIndexNoEmpty.size());
+
int aResult = 0;
const TDF_LabelList& aList = myRef->List();
for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
}
ObjectPtr Model_AttributeRefList::iteratedObject(TDF_ListIteratorOfLabelList& theLIter,
- TDataStd_ListIteratorOfListOfExtendedString& theExtIter,
+ TDataStd_ListIteratorOfListOfExtendedString& theExtIter,
std::shared_ptr<Model_Document> theDoc) const
{
ObjectPtr anObj;
}
theExtIter.Next();
} else { // internal document object
- anObj = theDoc->objects()->object(theLIter.Value());
+ TDF_Label aLab = theLIter.Value();
+ if (!aLab.IsNull())
+ anObj = theDoc->objects()->object(theLIter.Value());
}
}
return anObj;
}
-list<ObjectPtr> Model_AttributeRefList::list()
+std::list<ObjectPtr> Model_AttributeRefList::list()
{
+ createHash();
std::list<ObjectPtr> aResult;
- std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
- owner()->document());
- if (aDoc) {
- const TDF_LabelList& aList = myRef->List();
- TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List());
- for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
- aResult.push_back(iteratedObject(aLIter, anExtIter, aDoc));
- }
+ std::map<int, ObjectPtr>::iterator aHashIter = myHashIndex.begin();
+ for(; aHashIter != myHashIndex.end(); aHashIter++) {
+ aResult.push_back(aHashIter->second);
}
return aResult;
}
if(!theObj.get()) {
return false;
}
- if (theObj->document() == owner()->document()) { // this document object
- 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();
- for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
- if (aLIter.Value().IsEqual(anObjLab)) {
- return true;
- }
- }
- }
- }
- } else { // external document object
- // create new lists because for the current moment remove one of the duplicated elements
- // from the list is buggy
- std::ostringstream anIdString; // string with document Id
- anIdString<<theObj->document()->id();
- std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
- TCollection_AsciiString anEntry;
- TDF_Tool::Entry(aData->label().Father(), anEntry);
- bool aFound = false;
- TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List());
- for (; anExtIter.More(); anExtIter.Next()) {
- if (anExtIter.Value() == anIdString.str().c_str()) {
- anExtIter.Next();
- if (anExtIter.Value() == anEntry) { // fully maches
- return true;
- }
- } else {
- anExtIter.Next();
- }
- }
- }
- return false;
+ createHash();
+ return myHashObjects.count(theObj) != 0;
}
-ObjectPtr Model_AttributeRefList::object(const int theIndex, const bool theWithEmpty) const
+ObjectPtr Model_AttributeRefList::object(const int theIndex, const bool theWithEmpty)
{
- std::shared_ptr<Model_Document> aDoc =
- std::dynamic_pointer_cast<Model_Document>(owner()->document());
- if (aDoc) {
- int anIndex = -1;
- TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List());
- for (TDF_ListIteratorOfLabelList aLIter(myRef->List()); aLIter.More(); aLIter.Next()) {
- if (theWithEmpty || (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot()))
- anIndex++;
- if (anIndex == theIndex) {
- return iteratedObject(aLIter, anExtIter, aDoc);
- }
- if (aLIter.Value() == myRef->Label()) {
- anExtIter.Next();
- anExtIter.Next();
- }
- }
+ createHash();
+ std::map<int, ObjectPtr>::iterator aFind;
+ if (theWithEmpty) {
+ aFind = myHashIndex.find(theIndex);
+ if (aFind == myHashIndex.end())
+ return ObjectPtr();
+ } else {
+ aFind = myHashIndexNoEmpty.find(theIndex);
+ if (aFind == myHashIndexNoEmpty.end())
+ return ObjectPtr();
}
- return ObjectPtr();
+ return aFind->second;
}
void Model_AttributeRefList::substitute(const ObjectPtr& theCurrent, const ObjectPtr& theNew)
TDF_Label aCurrentLab = aData->label().Father();
TDF_Label aNewLab;
if (theNew.get() && theNew->data()->isValid()) { // the new may be null
- std::shared_ptr<Model_Data> aNewData =
+ std::shared_ptr<Model_Data> aNewData =
std::dynamic_pointer_cast<Model_Data>(theNew->data());
aNewLab = aNewData->label().Father();
} else {
aNewLab = aCurrentLab.Root(); // root means null object
}
// do the substitution
+ eraseHash();
ADD_BACK_REF(theNew);
if (myRef->InsertAfter(aNewLab, aCurrentLab)) {
myRef->Remove(aCurrentLab);
}
}
-void Model_AttributeRefList::exchange(const ObjectPtr& theObject1, const ObjectPtr& theObject2)
-{
- std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
- owner()->document());
- if (aDoc) {
- std::shared_ptr<Model_Data> aData1 = std::dynamic_pointer_cast<Model_Data>(theObject1->data());
- if (aData1.get() && aData1->isValid()) {
- TDF_Label aLab1 = aData1->label().Father();
- if (theObject2.get() && theObject2->data()->isValid()) { // the new may be null
- std::shared_ptr<Model_Data> aData2 =
- std::dynamic_pointer_cast<Model_Data>(theObject2->data());
- if (aData2.get() && aData2->isValid()) {
- TDF_Label aLab2 = aData2->label().Father();
- // do the substitution: use the temporary label, as usually in exchange
- TDF_Label aTmpLab = aLab1.Root();
- if (myRef->InsertAfter(aTmpLab, aLab1)) {
- myRef->Remove(aLab1);
- }
- if (myRef->InsertAfter(aLab1, aLab2)) {
- myRef->Remove(aLab2);
- }
- if (myRef->InsertAfter(aLab2, aTmpLab)) {
- myRef->Remove(aTmpLab);
- }
- owner()->data()->sendAttributeUpdated(this);
- }
- }
- }
- }
-}
-
void Model_AttributeRefList::removeLast()
{
std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
if (aDoc && !myRef->IsEmpty()) {
ObjectPtr anObj = aDoc->objects()->object(myRef->Last());
if (anObj.get()) {
+ eraseHash();
myRef->Remove(myRef->Last());
REMOVE_BACK_REF(anObj);
owner()->data()->sendAttributeUpdated(this);
std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
owner()->document());
if (aDoc && !myRef->IsEmpty()) {
- // collet labels that will be removed
+ // collect labels that will be removed
TDF_LabelList aLabelsToRemove;
TDF_ListIteratorOfLabelList aLabIter(myRef->List());
for(int aCurrent = 0; aLabIter.More(); aLabIter.Next(), aCurrent++) {
}
}
if (!aLabelsToRemove.IsEmpty()) {
+ eraseHash();
owner()->data()->sendAttributeUpdated(this);
}
}
if (!myLab.FindAttribute(TDataStd_ExtStringList::GetID(), myExtDocRef)) {
myExtDocRef = TDataStd_ExtStringList::Set(myLab);
}
+ eraseHash();
+}
+
+void Model_AttributeRefList::createHash()
+{
+ if (myHashUsed)
+ return;
+ eraseHash();
+ std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
+ owner()->document());
+ if (aDoc) {
+ const TDF_LabelList& aList = myRef->List();
+ TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List());
+ for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
+ ObjectPtr anObj = iteratedObject(aLIter, anExtIter, aDoc);
+ myHashIndex[int(myHashIndex.size())] = anObj;
+ if (anObj.get()) {
+ myHashIndexNoEmpty[int(myHashIndexNoEmpty.size())] = anObj;
+ myHashObjects.insert(anObj);
+ }
+ }
+ }
+ if (!myHashObjects.empty()) // on open document with multi-rotation referenced have no results
+ myHashUsed = true;
+}
+
+void Model_AttributeRefList::eraseHash()
+{
+ myHashObjects.clear();
+ myHashIndex.clear();
+ myHashIndexNoEmpty.clear();
+ myHashUsed = false;
}