HowToIntegrateNewDataEntityType

From user's Wiki!
Jump to: navigation, search

This page provides some tips and standards on how to integrate a new type of DataEntity.

Read more information in Extensible Data Component.

Create a class for storing your data type

First thing you need to do is to encapsulate your data in a single class with smart pointer support. For example, you can create an empty class, derived from Core::SmartPointerObject. In this example, we created a class called MyData that stores a width.

class MyData : public Core::SmartPointerObject
{
public:
	coreDeclareSmartPointerClassMacro(MyData, Core::SmartPointerObject);

	MyData( )
	{
		m_Width = 0;
	}

	void SetWidth( const float val )
	{
		m_Width = val;
	}

	float GetWidth( ) const
	{
		return m_Width;
	}

private:
	//! Width
	float m_Width;

};

Create a class derived from DataEntityImpl

In order to register your data into the Framework, you need to implement the interface DataEntityImpl. In this sample code, a new class MyDataImpl is created that stores a smart pointer to the previous created class MyData.

If the class MyData does not implement a copy function, you can just copy the smart pointer: m_Data = srcData;

There are two kinds of DataEntityImpl:

  • Single: Stores one time step. For example vktImageData
  • Multiple: Stores multiple time steps. For example mitk::Image

This example shows a new implementation for a single time step. If you don't know what to choose, use single, because it's the most common solution.

This example uses the type ImageTypeId. This tells the framework that the data contained in your DataEntity is an image. You need to choose your own type defined in the file: coreDataEntityTypes.h. This type will be used by the framework to convert between different data type representations (for example VTK image and ITK image) and to allow the user to select the data in your processor inputs, depending on the type.

Header file

class PLUGIN_EXPORT MyDataImpl : public DataEntityImpl
{
public:
	typedef MyData::Pointer DataType;

	coreDeclareSmartPointerClassMacro( Core::MyDataImpl, DataEntityImpl )
	
	coreDefineSingleDataFactory( Core::MyDataImpl, DataType, ImageTypeId )

	//@{ 
	/// \name Interface
public:
	boost::any GetDataPtr() const;

private:
	virtual void SetData( blTagMap::Pointer tagMap, ImportMemoryManagementType mem = gmCopyMemory );
	virtual void GetData( blTagMap::Pointer tagMap );
	virtual void SetAnyData( boost::any val );
	virtual void ResetData( );
	//@}

private:
	//!
	MyDataImpl( );

	//!
	virtual ~MyDataImpl( );

	//! Not implemented
	SignalImpl(const Self&);

	//! Not implemented
  	void operator=(const Self&);
	
private:

	DataType m_Data;

};

Implementation file

MyDataImpl::MyDataImpl( )
{
	ResetData();
}

MyDataImpl::~MyDataImpl()
{

}

boost::any MyDataImpl::GetDataPtr() const
{
	return m_Data;
}

void MyDataImpl::ResetData()
{
	m_Data = MyData::New( );
}

void MyDataImpl::SetAnyData( boost::any val )
{
	m_Data = boost::any_cast<DataType> ( val );
}

void MyDataImpl::SetData( 
	blTagMap::Pointer tagMap, ImportMemoryManagementType mem/* = gmCopyMemory*/ )
{
	blTag::Pointer tagDataPtr = tagMap->FindTagByName( "DataPtr" );
	if ( tagDataPtr.IsNotNull() )
	{
		DataType srcData;
		if ( tagDataPtr->GetValue<DataType>( srcData ) )
		{
			m_Data->Copy( srcData );
			return;
		}
	}

	// Throw exception
	DataEntityImpl::SetData( tagMap, mem );
}

void MyDataImpl::GetData( blTagMap::Pointer tagMap )
{
	tagMap->AddTag( "DataPtr", m_Data ); 
}

Register your new data type

To register/unregister your new data type to the framework, you need to call these lines in the constructor and destructor of ProcessorCollective:

ProcessorCollective::ProcessorCollective()
{
	Core::FactoryManager::Register( Core::DataEntityImpl::GetNameClass(), MyDataImpl::Factory::New() );
}

ProcessorCollective::~ProcessorCollective()
{
	Core::FactoryManager::UnRegisterByInstanceClassName( MyDataImpl::GetNameClass( ) );
}

Use your new data type in your Processor

In your processor, you can retrieve and create a new instance of your new data type: MyData. For example, to create a new instance:

void MyProcessor::Update( )
{
    // Create a new instance
    MyData::Pointer data = MyData::New( );
    data->SetWidth( 1 );

    UpdateOutput( 0, data, "MyData" );
}

When UpdateOutput() is called, the framework will:

  1. Search a registered DataEntityImpl factory that can manage the pointer to MyData. In this example, the class will be MyDataImpl
  2. myDataImplDst: Create a DataEntity and change the implementation to MyDataImpl
  3. myDataImplSrc: Create a temporal instance of MyDataImpl and set the pointer to MyData with the function SetDataPtr()
  4. Copy myDataImplSrc to myDataImplDst with the function DeepCopy()

Go back to Developers