Skip to content
Snippets Groups Projects
Commit 203f9089 authored by Floris Berendsen's avatar Floris Berendsen
Browse files

Merge branches 'ELASTIX-24-Component-Interface-Handshake' and

'ELASTIX-12-implement-componentdatabase' into develop

Conflicts:
	Modules/Core/elxModuleCore.cmake
	Testing/Unit/CMakeLists.txt
parents 393060f9 a961c042
No related branches found
No related tags found
No related merge requests found
#include "SSDMetric4thPartyComponent.h"
namespace elx
{
SSDMetric4thPartyComponent::SSDMetric4thPartyComponent()
{
this->theImplementation = new Example4thParty::SSDMetric4thParty();
}
SSDMetric4thPartyComponent::~SSDMetric4thPartyComponent()
{
delete this->theImplementation;
}
int SSDMetric4thPartyComponent::GetValue()
{
return this->theImplementation->GetCost(); // translate method name
};
} //end namespace elx
\ No newline at end of file
#include <iostream>
// test case: Assume there are two (slightly) incompatible codebases (i.e. 3rd party and 4th! party), each with an optimizer object and a metric object. The example classes of 3rd and 4th party code bases cannot be changed, but the wrapping is in our control.
// goal: make elastix components of all objects and define a handshake that checks if connections can be made.
#include "SSDMetric3rdPartyComponent.h"
#include "GDOptimizer3rdPartyComponent.h"
#include "SSDMetric4thPartyComponent.h"
#include "GDOptimizer4thPartyComponent.h"
using namespace elx;
int main() {
{
std::cout << InterfaceName<MetricValueInterface>::Get() << std::endl;
std::cout << AcceptorInterfaceName<InterfaceAcceptor<MetricValueInterface> >::Get() << std::endl;
std::cout << InterfaceName<InterfaceAcceptor<MetricValueInterface> >::Get() << std::endl;
std::cout << InterfaceName<InterfaceProvider<MetricValueInterface> >::Get() << std::endl;
}
{
/************ testing interface casts ***********
* expected: ok
*/
SSDMetric3rdPartyComponent* tempmetric3p = new SSDMetric3rdPartyComponent();
ComponentBase* metric3p = tempmetric3p;
MetricValueInterface* valIF = dynamic_cast<MetricValueInterface*> (metric3p);
std::cout << valIF->GetValue() << std::endl;
MetricDerivativeInterface* derIF = dynamic_cast<MetricDerivativeInterface*> (metric3p);
std::cout << derIF->GetDerivative() << std::endl;
}
/************ Connect metric4p to optimizer4p ***********
* expected: ok
*/
{
SSDMetric4thPartyComponent* tempmetric4p = new SSDMetric4thPartyComponent();
ComponentBase* metric4p = tempmetric4p; // type returned by our component factory
GDOptimizer4thPartyComponent* tempOptimizer4p = new GDOptimizer4thPartyComponent();
ComponentBase* optimizer4p = tempOptimizer4p; // type returned by our component factory
interfaceStatus IFstatus = optimizer4p->ConnectFrom("MetricValueInterface", metric4p);
InterfaceAcceptor<MetricValueInterface>* opValIF = dynamic_cast<InterfaceAcceptor<MetricValueInterface>*> (optimizer4p);
if (!opValIF)
{
std::cout << "optimizer4p has no OptimizerValueInterface" << std::endl;
}
// connect value interfaces
opValIF->Connect(metric4p);
OptimizerUpdateInterface* opUpdIF = dynamic_cast<OptimizerUpdateInterface*> (optimizer4p);
if (!opValIF)
{
std::cout << "optimizer4p has no OptimizerUpdateInterface" << std::endl;
}
// Update the optimizer component
opUpdIF->Update();
}
/************ Connect metric3p to optimizer4p ***********
* expected: ok
* optimizer4p will only use/have access to the GetValue interface of metric3p
*/
{
SSDMetric3rdPartyComponent* tempmetric3p = new SSDMetric3rdPartyComponent();
ComponentBase* metric3p = tempmetric3p; // type returned by our component factory
GDOptimizer4thPartyComponent* tempOptimizer4p = new GDOptimizer4thPartyComponent();
ComponentBase* optimizer4p = tempOptimizer4p; // type returned by our component factory
InterfaceAcceptor<MetricValueInterface>* opValIF = dynamic_cast<InterfaceAcceptor<MetricValueInterface>*> (optimizer4p);
if (!opValIF)
{
std::cout << "optimizer4p has no OptimizerValueInterface" << std::endl;
}
// connect value interfaces
if (!opValIF->Connect(metric3p))
{
std::cout << "metric3p cannot connect to optimizer4p by ValueInterface" << std::endl;
}
OptimizerUpdateInterface* opUpdIF = dynamic_cast<OptimizerUpdateInterface*> (optimizer4p);
if (!opValIF)
{
std::cout << "optimizer4p has no OptimizerUpdateInterface" << std::endl;
}
// Update the optimizer component
opUpdIF->Update();
}
/************ Connect metric4p to optimizer3p ***********
* expected: fail
* optimizer3p needs a metric with GetDerivative which metric4p doesn't have
*/
{
SSDMetric4thPartyComponent* tempmetric4p = new SSDMetric4thPartyComponent();
ComponentBase* metric4p = tempmetric4p; // type returned by our component factory
GDOptimizer3rdPartyComponent* tempOptimizer3p = new GDOptimizer3rdPartyComponent();
ComponentBase* optimizer3p = tempOptimizer3p; // type returned by our component factory
InterfaceAcceptor<MetricValueInterface>* opValIF = dynamic_cast<InterfaceAcceptor<MetricValueInterface>*> (optimizer3p);
if (!opValIF)
{
std::cout << "optimizer3p has no OptimizerValueInterface" << std::endl;
}
// connect value interfaces
if (!opValIF->Connect(metric4p))
{
std::cout << "metric4p cannot connect to optimizer3p by ValueInterface" << std::endl;
}
//opValIF->Set(tempmetric4p);
InterfaceAcceptor<MetricDerivativeInterface>* opDerivIF = dynamic_cast<InterfaceAcceptor<MetricDerivativeInterface>*> (optimizer3p);
if (!opDerivIF)
{
std::cout << "optimizer3p has no OptimizerDerivativeInterface" << std::endl;
}
// connect derivative interfaces
if (!opDerivIF->Connect(metric4p))
{
std::cout << "metric4p cannot connect to optimizer3p by DerivativeInterface" << std::endl;
}
OptimizerUpdateInterface* opUpdIF = dynamic_cast<OptimizerUpdateInterface*> (optimizer3p);
if (!opValIF)
{
std::cout << "optimizer3p has no OptimizerUpdateInterface" << std::endl;
}
// Update the optimizer component
// opUpdIF->Update(); // will fail since the metric does'nt have GetDerivative()
}
return 0;
}
......@@ -5,6 +5,7 @@ set( ${MODULE}_INCLUDE_DIRS
${${MODULE}_SOURCE_DIR}/Common/include
${${MODULE}_SOURCE_DIR}/Blueprints/include
${${MODULE}_SOURCE_DIR}/Install/include
${${MODULE}_SOURCE_DIR}/ComponentInterface/include
)
# Export libraries
......@@ -15,8 +16,17 @@ set( ${MODULE}_LIBRARIES
# Module source files
set( ${MODULE}_SOURCE_FILES
${${MODULE}_SOURCE_DIR}/Blueprints/src/elxBlueprint.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/Example3rdPartyCode.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/Example4thPartyCode.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/GDOptimizer3rdPartyComponent.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/GDOptimizer4thPartyComponent.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/Metric3rdPartyWrapper.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/Metric4thPartyWrapper.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/SSDMetric3rdPartyComponent.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/SSDMetric4thPartyComponent.cxx
)
# Compile library
add_library( ${MODULE} STATIC "${${MODULE}_SOURCE_FILES}" )
......
......@@ -7,6 +7,7 @@ set( ElastixUnitTestFilenames
elxExampleUnitTest.cxx
elxBlueprintTest.cxx
elxComponentFactoryTest.cxx
elxComponentInterfaceTest.cxx
)
......
#include "SSDMetric3rdPartyComponent.h"
#include "GDOptimizer3rdPartyComponent.h"
#include "SSDMetric4thPartyComponent.h"
#include "GDOptimizer4thPartyComponent.h"
#include "gtest/gtest.h"
namespace elx {
class InterfaceTest : public ::testing::Test {
public:
virtual void SetUp() {
metric3p = new SSDMetric3rdPartyComponent();
optimizer3p = new GDOptimizer3rdPartyComponent();
metric4p = new SSDMetric4thPartyComponent();
optimizer4p = new GDOptimizer4thPartyComponent();
}
virtual void TearDown() {
delete metric3p;
delete optimizer3p;
delete metric4p;
delete optimizer4p;
}
// types as if returned by our component factory
ComponentBase* metric3p;
ComponentBase* optimizer3p;
ComponentBase* metric4p;
ComponentBase* optimizer4p;
};
TEST_F( InterfaceTest, InterfaceNameTraits )
{
EXPECT_STREQ(InterfaceName<MetricValueInterface>::Get(), "MetricValueInterface");
EXPECT_STREQ(InterfaceName<InterfaceAcceptor<MetricValueInterface> >::Get(), "MetricValueInterface");
}
TEST_F( InterfaceTest, DynamicCast )
{
int returnval;
//metric3p should have a MetricValueInterface
MetricValueInterface* valueIF = dynamic_cast<MetricValueInterface*> (metric3p);
ASSERT_NE(valueIF, nullptr);
EXPECT_NO_THROW(returnval = valueIF->GetValue());
//metric3p should have a MetricDerivativeInterface
MetricDerivativeInterface* derivativeIF = dynamic_cast<MetricDerivativeInterface*> (metric3p);
ASSERT_NE(derivativeIF, nullptr);
EXPECT_NO_THROW(returnval = derivativeIF->GetDerivative());
//optimizer3p should have a OptimizerUpdateInterface
OptimizerUpdateInterface* updateIF = dynamic_cast<OptimizerUpdateInterface*> (optimizer3p);
ASSERT_NE(updateIF, nullptr);
//EXPECT_NO_THROW(returnval = updateIF->Update()); // Update can only be called if metric and optimizer are connected
//optimizer3p should have a InterfaceAcceptor<MetricValueInterface>
InterfaceAcceptor<MetricValueInterface>* valueAcceptorIF = dynamic_cast<InterfaceAcceptor<MetricValueInterface>*> (optimizer3p);
ASSERT_NE(valueAcceptorIF, nullptr);
//optimizer3p should have a InterfaceAcceptor<MetricDerivativeInterface>
InterfaceAcceptor<MetricDerivativeInterface>* derivativeAcceptorIF = dynamic_cast<InterfaceAcceptor<MetricDerivativeInterface>*> (optimizer3p);
ASSERT_NE(derivativeAcceptorIF, nullptr);
}
TEST_F( InterfaceTest, ConnectByName )
{
interfaceStatus IFstatus;
EXPECT_NO_THROW(IFstatus = optimizer3p->ConnectFrom("MetricValueInterface", metric3p));
EXPECT_EQ(IFstatus, interfaceStatus::success);
EXPECT_NO_THROW(IFstatus = optimizer3p->ConnectFrom("MetricValueInterface", metric4p));
EXPECT_EQ(IFstatus, interfaceStatus::success);
EXPECT_NO_THROW(IFstatus = optimizer4p->ConnectFrom("MetricValueInterface", metric3p));
EXPECT_EQ(IFstatus, interfaceStatus::success);
EXPECT_NO_THROW(IFstatus = optimizer4p->ConnectFrom("MetricValueInterface", metric4p));
EXPECT_EQ(IFstatus, interfaceStatus::success);
EXPECT_NO_THROW(IFstatus = optimizer3p->ConnectFrom("MetricDerivativeInterface", metric3p));
EXPECT_EQ(IFstatus, interfaceStatus::success);
EXPECT_NO_THROW(IFstatus = optimizer3p->ConnectFrom("MetricDerivativeInterface", metric4p));
EXPECT_EQ(IFstatus, interfaceStatus::noprovider);
EXPECT_NO_THROW(IFstatus = optimizer4p->ConnectFrom("MetricDerivativeInterface", metric3p));
EXPECT_EQ(IFstatus, interfaceStatus::noaccepter);
}
TEST_F(InterfaceTest, ConnectAll)
{
int connectionCount = 0;
EXPECT_NO_THROW(connectionCount = optimizer3p->ConnectFrom(metric3p));
EXPECT_EQ(connectionCount, 2); // both MetricValueInterface and MetricDerivativeInterface are connected
EXPECT_NO_THROW(connectionCount = optimizer3p->ConnectFrom(metric4p));
EXPECT_EQ(connectionCount, 1); // only MetricValueInterface is connected
EXPECT_NO_THROW(connectionCount = optimizer4p->ConnectFrom(metric3p));
EXPECT_EQ(connectionCount, 1); // only MetricValueInterface is connected
EXPECT_NO_THROW(connectionCount = optimizer4p->ConnectFrom(metric4p));
EXPECT_EQ(connectionCount, 1); // only MetricValueInterface is connected
EXPECT_NO_THROW(connectionCount = metric4p->ConnectFrom(optimizer4p));
EXPECT_EQ(connectionCount, 0); // cannot connect in this direction
}
} // namespace elx
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment