/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef _DAI_ITERATOR_COLLECTION_H #define _DAI_ITERATOR_COLLECTION_H #include "daiIterator.h" #include "daiAggrMemberAccess.h" #define STL_USING_ALGORITHM #include "OdaSTL.h" #include "daiPrepareAggregateItem.h" #include "TD_PackPush.h" namespace OdDAI { /** \details Class that represents type-specified iterator. */ template class DAI_EXPORT IteratorCollection : public Iterator { public: /** \details Constructor for the IteratorCollection class. \param collection [in] Collection of aggregate instances. */ IteratorCollection(Aggr& collection); /** \details Moves an iterator to the beginning of the collection. */ void beginning() override; /** \details Moves an iterator to the next item in the collection. \returns true if the next element exists and the iterator was moved to it; otherwise, the method returns false. */ bool next() override; /** \details Moves an iterator to the previous item in the collection. \returns true if the previous element exists and the iterator was moved to it; otherwise, the method returns false. */ bool previous() override; /** \details Moves an iterator to the last element of the collection. */ void end() override; /** \details Creates an aggregate instance and adds it to the collection at the current index replacing current member. \returns Raw pointer to the created instance. */ Aggr* createAggrInstanceAsCurrentMember() override; /** \details Creates an aggregate instance and adds it to the collection at the index before current member. \returns Raw pointer to the created instance. */ Aggr* createAggrInstanceBeforeCurrentMember() override; /** \details Creates an aggregate instance and adds it to the collection at the index after current member. \returns Raw pointer to the created instance. */ Aggr* createAggrInstanceAfterCurrentMember() override; /** \details Retrieves the current element of an aggregate referred to by the iterator. \returns An instance of the OdRxValue class that represents the current element referred to by the iterator. */ OdRxValue getCurrentMember() const override; /** \details Retrieves the value of the current element of an aggregate referred to by the iterator. \returns An instance of the OdRxValue class that represents the value of the current element referred to by the iterator. */ OdRxValue getCurrentMemberValue() const override; /** \details Sets a new current element of an aggregate for the iterator. The new element replaces the previously current element. \param anItem [in] An instance of the OdRxValue class that represents the new element to be set as current. */ void putCurrentMember(const OdRxValue& anItem) override; /** \details Adds a new specified element to the list aggregate before the element referred to by the iterator. The new element is added before the current element; the current element that the iterator refers to is not changed. \param anItem [in] An instance of the OdRxValue class that represents the new element to be added. \remarks The method throws an exception with the AI_NVLD code value if the aggregate instance is not a list. */ void addBeforeCurrentMember(const OdRxValue& anItem) override; /** \details Adds a new specified element to the list aggregate after the element referred to by the iterator. The new element is added after the current element; the current element that the iterator refers to is not changed. \param anItem [in] An instance of the OdRxValue class that represents the new element to be added. \remarks The method throws an exception with the AI_NVLD code value if the aggregate instance is not a list. */ void addAfterCurrentMember(const OdRxValue& anItem) override; /** \details Removes the current element from an aggregate. \returns true if the element is successfully removed; otherwise, the method returns false. */ bool removeCurrentMember() override; /** \details Unset current element from an Array. \returns true if the element is successfully unset; otherwise, the method returns false. \remarks Applicable only for arrays. */ bool unsetCurrentMember() override; /** \details Retrieves the value bound of the current element referred to by the iterator. \returns An unsigned integer value that represents the value bound. */ int getValueBound() const override; /** \details Checks whether the value of the current array element referred to by the iterator is set. \returns true if the value of the current element is set; otherwise, the method returns false. \remarks Applicable only for arrays. */ bool testCurrentMember() const override; /** \details Retrieves the type of the current element referred to by the iterator. \returns An instance of the OdRxValueType class that contains information about the type of the current element. */ const OdRxValueType& type() const override; /** \details Checks whether the currently referenced index is not at collection bounds. \returns true if collection exists, current index is not at the beginning of the collection and current index is not at the end of the collection; otherwise the method returns false. */ bool checkCurrentBounds() const; private: typedef OdArray InternalArray; typename InternalArray::size_type m_index; TContainer& m_collection; bool m_isBegin; }; //DOM-IGNORE-BEGIN template class List; namespace IteratorImpl { #if defined _MSC_VER #pragma warning(push) #pragma warning(disable:4100) // unreferenced formal parameter #endif template class createAggrInstanceAsCurrentMember { public: static OdDAI::Aggr* Impl(TContainer& container, typename OdArray::size_type place) { throw DaiException(sdaiEX_NSUP, "Expression evaluation not supported", TD_FUNC); } }; template class createAggrInstanceBeforeCurrentMember { public: static OdDAI::Aggr* Impl(TContainer& container, typename OdArray::size_type place) { throw DaiException(sdaiEX_NSUP, "Expression evaluation not supported", TD_FUNC); } }; template class createAggrInstanceAfterCurrentMember { public: static OdDAI::Aggr* Impl(TContainer& container, typename OdArray::size_type place) { throw DaiException(sdaiEX_NSUP, "Expression evaluation not supported", TD_FUNC); } }; template class putCurrentMember { public: static void Impl(TContainer& container, typename OdArray::size_type place, const TType& anItem) { throw DaiException(sdaiEX_NSUP, "Expression evaluation not supported", TD_FUNC); } }; template class addBeforeCurrentMember { public: static void Impl(TContainer& container, typename OdArray::size_type place, const TType& anItem) { // Do nothing } }; template class addAfterCurrentMember { public: static void Impl(TContainer& container, typename OdArray::size_type place, const TType& anItem) { // Do nothing } }; template class removeCurrentMember { public: static bool Impl(TContainer& container, typename OdArray::size_type place) { throw DaiException(sdaiEX_NSUP, "Expression evaluation not supported", TD_FUNC); } }; template class unsetCurrentMember { public: static bool Impl(TContainer& container, typename OdArray::size_type place) { throw DaiException(sdaiEX_NSUP, "Expression evaluation not supported", TD_FUNC); } }; template class testCurrentMember { public: static bool Impl(TContainer& container, typename OdArray::size_type place) { return true; } }; template inline TType processPasteValue(IteratorCollection& iteratorToPaste, const OdRxValue& anItem, TContainer& collection) { TType valueProxy = collection.template generateAggrItem(); if (!(anItem >> valueProxy)) { throw DaiException(sdaiVT_NVLD, "Value type invalid ", TD_FUNC); } if (iteratorToPaste.getValueBound() == 0) { throw DaiException(sdaiAI_NSET, "Aggregate instance is empty", TD_FUNC); } if (!iteratorToPaste.checkCurrentBounds()) { throw DaiException(sdaiIR_NSET, "Current member is not defined", TD_FUNC); } return valueProxy; } template , TContainer>::value, bool>::type = true > inline TType processPasteValueList(IteratorCollection& iteratorToPaste, const OdRxValue& anItem, TContainer& collection) { throw DaiException(sdaiAI_NVLD, "The aggregate instance is not a list", TD_FUNC); } template , TContainer>::value, bool>::type = true > inline TType processPasteValueList(IteratorCollection& iteratorToPaste, const OdRxValue& anItem, TContainer& collection) { TType valueProxy = collection.template generateAggrItem(); if (!(anItem >> valueProxy)) { throw DaiException(sdaiVT_NVLD, "Value type invalid ", TD_FUNC); } return valueProxy; } #if defined _MSC_VER #pragma warning(pop) #endif } template IteratorCollection::IteratorCollection(Aggr& collection) : m_collection(*reinterpret_cast(&collection)) , m_isBegin(false) { beginning(); } template void IteratorCollection::beginning() { m_isBegin = true; m_index = 0; } template bool IteratorCollection::next() { const OdArray* internalArray = m_collection; if (!internalArray) { return false; } if (m_isBegin) { m_isBegin = false; return m_index != internalArray->size(); } if (m_index != internalArray->size()) { ++m_index; return m_index != internalArray->size(); } return false; } template bool IteratorCollection::previous() { if (m_isBegin) { return false; } if (m_index != 0) { --m_index; return true; } m_isBegin = true; return false; } template void IteratorCollection::end() { const OdArray* internalArray = m_collection; m_index = internalArray ? internalArray->size() : 0; } template Aggr* IteratorCollection::createAggrInstanceAsCurrentMember() { return IteratorImpl::createAggrInstanceAsCurrentMember::Impl(m_collection, m_index); } template Aggr* IteratorCollection::createAggrInstanceBeforeCurrentMember() { return IteratorImpl::createAggrInstanceBeforeCurrentMember::Impl(m_collection, m_index); } template Aggr* IteratorCollection::createAggrInstanceAfterCurrentMember() { return IteratorImpl::createAggrInstanceAfterCurrentMember::Impl(m_collection, m_index); } template bool IteratorCollection::checkCurrentBounds() const { const OdArray* internalArray = m_collection; return internalArray && m_index != internalArray->size() && !m_isBegin; } template OdRxValue IteratorCollection::getCurrentMemberValue() const { if (!checkCurrentBounds()) { throw DaiException(sdaiIR_NSET, "Current member is not defined", TD_FUNC); } const OdArray* internalArray = m_collection; ODA_ASSERT(internalArray && "can not be here cause checkCurrentBounds should exclude this situation?"); return *(internalArray->begin() + m_index); } template OdRxValue IteratorCollection::getCurrentMember() const { if (!checkCurrentBounds()) { throw DaiException(sdaiIR_NSET, "Current member is not defined", TD_FUNC); } const OdArray* internalArray = m_collection; ODA_ASSERT(internalArray && "can not be here cause checkCurrentBounds should exclude this situation?"); #ifdef _AGGR_RETURN_PTR return _getCurrentMemberTyped(const_cast* >(internalArray), m_index); #else return *(internalArray->begin() + m_index); #endif } template void IteratorCollection::putCurrentMember(const OdRxValue& anItem) { TType valueProxy = IteratorImpl::processPasteValue(*this, anItem, m_collection); IteratorImpl::putCurrentMember::Impl(m_collection, m_index, valueProxy); } template void IteratorCollection::addBeforeCurrentMember(const OdRxValue& anItem) { TType valueProxy = IteratorImpl::processPasteValueList(*this, anItem, m_collection); IteratorImpl::addBeforeCurrentMember::Impl(m_collection, m_index, valueProxy); next(); } template void IteratorCollection::addAfterCurrentMember(const OdRxValue& anItem) { TType valueProxy = IteratorImpl::processPasteValueList(*this, anItem, m_collection); IteratorImpl::addAfterCurrentMember::Impl(m_collection, m_index, valueProxy); } template bool IteratorCollection::removeCurrentMember() { bool wasDeleted = IteratorImpl::removeCurrentMember::Impl(m_collection, m_index); previous(); return wasDeleted; } template bool IteratorCollection::unsetCurrentMember() { return IteratorImpl::unsetCurrentMember::Impl(m_collection, m_index); } template int IteratorCollection::getValueBound() const { const OdArray* internalArray = m_collection; return internalArray ? internalArray->size() : 0; } template bool IteratorCollection::testCurrentMember() const { return checkCurrentBounds() && IteratorImpl::testCurrentMember::Impl(m_collection, m_index); } template const OdRxValueType& IteratorCollection::type() const { return OdRxValueType::Desc::value(); } } #include "TD_PackPop.h" //DOM-IGNORE-END #endif // _DAI_ITERATOR_H