#pragma once #include "cafClassTypeName.h" #include "cafPdmObjectHandle.h" namespace caf { //================================================================================================== /// Implementation of PdmPtrArrayField<> //================================================================================================== //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template PdmPtrArrayField::~PdmPtrArrayField() { this->removeThisAsReferencingPtrField(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::setValue( const std::vector>& fieldValue ) { this->clearWithoutDelete(); this->insert( 0, fieldValue ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template const std::vector>& PdmPtrArrayField::value() const { return m_pointers; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::setValue( const std::vector& fieldValue ) { this->clearWithoutDelete(); for ( DataType* rawPtr : fieldValue ) { this->push_back( PdmPointer( rawPtr ) ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template DataType* PdmPtrArrayField::operator[]( size_t index ) const { return m_pointers[index]; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::push_back( DataType* pointer ) { CAF_ASSERT( isInitializedByInitFieldMacro() ); m_pointers.push_back( pointer ); if ( pointer ) pointer->addReferencingPtrField( this ); } //-------------------------------------------------------------------------------------------------- /// Set the value at position index to pointer, overwriting any pointer already present at that /// position without deleting the object pointed to. //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::set( size_t index, DataType* pointer ) { CAF_ASSERT( isInitializedByInitFieldMacro() ); if ( m_pointers[index] ) m_pointers[index]->removeReferencingPtrField( this ); m_pointers[index] = pointer; if ( m_pointers[index] ) pointer->addReferencingPtrField( this ); } //-------------------------------------------------------------------------------------------------- /// Insert pointer at position index, pushing the value previously at that position and all /// the preceding values backwards //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::insert( size_t index, DataType* pointer ) { CAF_ASSERT( isInitializedByInitFieldMacro() ); m_pointers.insert( m_pointers.begin() + index, pointer ); if ( pointer ) pointer->addReferencingPtrField( this ); } //-------------------------------------------------------------------------------------------------- /// Insert the pointers at position index, pushing the value previously at that position and all /// the preceding values backwards //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::insert( size_t index, const std::vector>& objects ) { CAF_ASSERT( isInitializedByInitFieldMacro() ); m_pointers.insert( m_pointers.begin() + index, objects.begin(), objects.end() ); typename std::vector>::iterator it; for ( it = m_pointers.begin() + index; it != m_pointers.end(); ++it ) { if ( !it->isNull() ) { ( *it )->addReferencingPtrField( this ); } } } //-------------------------------------------------------------------------------------------------- /// Returns the number of times pointer is referenced from the container. //-------------------------------------------------------------------------------------------------- template size_t PdmPtrArrayField::count( const DataType* pointer ) const { size_t itemCount = 0; typename std::vector>::const_iterator it; for ( it = m_pointers.begin(); it != m_pointers.end(); ++it ) { if ( *it == pointer ) { itemCount++; } } return itemCount; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template size_t PdmPtrArrayField::indexOf( const PdmObjectHandle* obj ) const { for ( size_t i = 0; i < m_pointers.size(); ++i ) { if ( obj == m_pointers[i].rawPtr() ) { return i; } } return (size_t)( -1 ); // Undefined size_t > m_pointers.size(); } //-------------------------------------------------------------------------------------------------- /// Empty the container without deleting the objects pointed to. //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::clearWithoutDelete() { CAF_ASSERT( isInitializedByInitFieldMacro() ); this->removeThisAsReferencingPtrField(); m_pointers.clear(); } //-------------------------------------------------------------------------------------------------- /// Removes the pointer at index from the container. Does not delete the object pointed to. /// Todo: This implementation can't be necessary in the new regime. Should be to just remove /// the item at index (shrinking the array) //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::erase( size_t index ) { CAF_ASSERT( isInitializedByInitFieldMacro() ); if ( m_pointers[index].rawPtr() ) { m_pointers[index].rawPtr()->removeReferencingPtrField( this ); } m_pointers.erase( m_pointers.begin() + index ); } //-------------------------------------------------------------------------------------------------- /// Removes all instances of object pointer from the container without deleting the object. //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::removePtr( PdmObjectHandle* object ) { CAF_ASSERT( isInitializedByInitFieldMacro() ); std::vector> tempPointers; tempPointers = m_pointers; m_pointers.clear(); for ( size_t index = 0; index < tempPointers.size(); ++index ) { if ( tempPointers[index].rawPtr() != object ) { m_pointers.push_back( tempPointers[index] ); } else { if ( tempPointers[index].rawPtr() ) { tempPointers[index].rawPtr()->removeReferencingPtrField( this ); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template std::vector PdmPtrArrayField::ptrReferencedObjectsByType() const { std::vector objects; size_t i; for ( i = 0; i < m_pointers.size(); ++i ) { objects.push_back( m_pointers[i].p() ); } return objects; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template std::vector PdmPtrArrayField::ptrReferencedObjects() const { std::vector objects; size_t i; for ( i = 0; i < m_pointers.size(); ++i ) { objects.push_back( m_pointers[i].rawPtr() ); } return objects; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::insertAt( int indexAfter, PdmObjectHandle* obj ) { CAF_ASSERT( isInitializedByInitFieldMacro() ); // This method should CAF_ASSERT( if obj to insert is not castable to the container type, but since this // is a virtual method, its implementation is always created and that makes a dyn_cast add the need for // #include of the header file "everywhere" typename std::vector>::iterator it; if ( indexAfter == -1 ) { m_pointers.push_back( PdmPointer() ); it = m_pointers.end() - 1; } else { m_pointers.insert( m_pointers.begin() + indexAfter, PdmPointer() ); it = m_pointers.begin() + indexAfter; } it->setRawPtr( obj ); obj->addReferencingPtrField( this ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template PdmObjectHandle* PdmPtrArrayField::at( size_t index ) { return m_pointers[index].rawPtr(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::removeThisAsReferencingPtrField() { typename std::vector>::iterator it; for ( it = m_pointers.begin(); it != m_pointers.end(); ++it ) { if ( !it->isNull() ) { it->rawPtr()->removeReferencingPtrField( this ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void PdmPtrArrayField::addThisAsReferencingPtrField() { typename std::vector>::iterator it; for ( it = m_pointers.begin(); it != m_pointers.end(); ++it ) { if ( !it->isNull() ) { ( *it )->addReferencingPtrField( this ); } } } } // End of namespace caf