Commit 0cfbed64 authored by Floris Berendsen's avatar Floris Berendsen
Browse files

ENH: ConnectFrom functionality outside of component implementations

parent d57de45a
......@@ -3,9 +3,11 @@
namespace elx
{
enum interfaceStatus { success, noaccepter, noprovider };
class ComponentBase {
public:
virtual int ConnectFrom(const char *, ComponentBase*) { return 0; }; //= 0;
virtual interfaceStatus ConnectFrom(const char *, ComponentBase*) = 0;
protected:
virtual ~ComponentBase(){};
};
......
......@@ -14,36 +14,6 @@ GDOptimizer3rdPartyComponent::~GDOptimizer3rdPartyComponent()
}
int GDOptimizer3rdPartyComponent::ConnectFrom(const char * interfacename, ComponentBase* other)
{
//TODO write out as templated functionality:
if (std::strcmp(InterfaceName<InterfaceAcceptor<MetricValueInterface>>::Get(), interfacename) == 0)
{
InterfaceAcceptor<MetricValueInterface>* acceptIF = static_cast<InterfaceAcceptor<MetricValueInterface>*> (this);
// static_cast always succeeds since we know via the template arguments of the component what InterfaceAcceptors are base classes.
// connect value interfaces
if (1 == acceptIF->Connect(other))
{
return 1; //success, assume only one interface listens interfacename
}
else
{
if (std::strcmp(InterfaceName<InterfaceAcceptor<MetricDerivativeInterface>>::Get(), interfacename) == 0)
{
InterfaceAcceptor<MetricDerivativeInterface>* acceptIF = static_cast<InterfaceAcceptor<MetricDerivativeInterface>*> (this);
if (!acceptIF)
{
std::cout << InterfaceName<InterfaceAcceptor<MetricDerivativeInterface>>::Get() << " optimizer has no OptimizerValueInterface" << std::endl;
}
// connect value interfaces
acceptIF->Connect(other);
return 1; //success, assume only one interface listens interfacename
}
return 0;
}
}
}
int GDOptimizer3rdPartyComponent::Set(MetricValueInterface* component)
{
this->MetricObject->SetMetricValueComponent(component);
......
......@@ -13,7 +13,6 @@ namespace elx
class GDOptimizer3rdPartyComponent :
public Implements<
Accepting< MetricValueInterface, MetricDerivativeInterface >,
//Accepting< InterfaceAcceptor<MetricValueInterface>, InterfaceAcceptor<MetricDerivativeInterface> >,
Providing< OptimizerUpdateInterface>
>
{
......@@ -22,7 +21,7 @@ namespace elx
~GDOptimizer3rdPartyComponent();
Example3rdParty::GDOptimizer3rdParty* theImplementation;
Metric3rdPartyWrapper* MetricObject;
virtual int ConnectFrom(const char *, ComponentBase*);
//virtual int ConnectFrom(const char *, ComponentBase*);
int Set(MetricValueInterface*);
int Set(MetricDerivativeInterface*);
int Update();
......
......@@ -15,22 +15,6 @@ GDOptimizer4thPartyComponent::~GDOptimizer4thPartyComponent()
delete this->MetricObject;
}
int GDOptimizer4thPartyComponent::ConnectFrom(const char * interfacename, ComponentBase* other)
{
//TODO write out as templated functionality:
if (std::strcmp(InterfaceName<InterfaceAcceptor<MetricValueInterface>>::Get(), interfacename) == 0)
{
InterfaceAcceptor<MetricValueInterface>* acceptIF = static_cast<InterfaceAcceptor<MetricValueInterface>*> (this);
if (!acceptIF)
{
std::cout << InterfaceName<InterfaceAcceptor<MetricValueInterface>>::Get() << " optimizer has no OptimizerValueInterface" << std::endl;
}
// connect value interfaces
acceptIF->Connect(other);
return 1; //success, assume only one interface listens interfacename
}
return 0;
}
int GDOptimizer4thPartyComponent::Set(MetricValueInterface* component)
{
......
......@@ -9,14 +9,19 @@
namespace elx
{
// wrapping into components:
class GDOptimizer4thPartyComponent : public ComponentBase, public InterfaceAcceptor<MetricValueInterface>, public OptimizerUpdateInterface
class GDOptimizer4thPartyComponent :
public Implements <
Accepting< MetricValueInterface >,
Providing < OptimizerUpdateInterface >
>
{
public:
GDOptimizer4thPartyComponent();
~GDOptimizer4thPartyComponent();
Example4thParty::GDOptimizer4thParty* theImplementation;
Metric4thPartyWrapper* MetricObject;
virtual int ConnectFrom(const char *, ComponentBase*);
//virtual int ConnectFrom(const char *, ComponentBase*);
int Set(MetricValueInterface*);
int Update();
};
......
......@@ -26,92 +26,53 @@ public:
template<class InterfaceT>
class InterfaceAcceptor {
public:
virtual int Set(InterfaceT*) = 0;
// Set() is called by a succesfull Connect()
// The implementation of Set() must be provided by component developers.
virtual int Set(InterfaceT*) = 0;
// Connect tries to connect this accepting interface with all interfaces of the provider component.
int Connect(ComponentBase*);
private:
bool isSet;
};
template<class InterfaceT>
int InterfaceAcceptor<InterfaceT>::Connect(ComponentBase* providerComponent){
InterfaceT* providerInterface = dynamic_cast<InterfaceT*> (providerComponent);
if (!providerInterface)
{
std::cout << "providerComponent does not have required " << InterfaceName < InterfaceT >::Get() << std::endl;
return 0;
}
// connect value interfaces
this->Set(providerInterface); // due to the input argument being uniquely defined in the multiple inheritance tree, all versions of Set() are accessible
return 1;
}
//template<typename... Interfaces>
//class Accepting : public Interfaces...
//{
//};
//template<>
//class Accepting<>
//{
//};
//template<typename FirstInterface>
//class Accepting : public InterfaceAcceptor < FirstInterface >
//{
//};
template<typename ... RestInterfaces>
class Accepting
{
public:
interfaceStatus ConnectFromImpl(const char *, ComponentBase*) { return interfaceStatus::noaccepter; }; //no interface called interfacename ;
};
//template<typename FirstInterface, typename ... RestInterfaces>
//class Accepting<FirstInterface, RestInterfaces... > : public InterfaceAcceptor<FirstInterface>, public Accepting< RestInterfaces ... >
//{
//};
template<typename FirstInterface, typename ... RestInterfaces>
class Accepting<FirstInterface, RestInterfaces... > : public Accepting< RestInterfaces ... >, public InterfaceAcceptor<FirstInterface>
class Accepting<FirstInterface, RestInterfaces... > : public InterfaceAcceptor<FirstInterface>, public Accepting< RestInterfaces ... >
{
//FirstInterface firstIF;
public:
interfaceStatus ConnectFromImpl(const char *, ComponentBase*);
};
template<typename... Interfaces>
class Providing : public Interfaces...
{
};
template<typename AcceptingInterfaces, typename ProvidingInterfaces>
class Implements : public ComponentBase, public AcceptingInterfaces, public ProvidingInterfaces
class Implements : public AcceptingInterfaces, public ProvidingInterfaces, public ComponentBase
{
typedef typename AcceptingInterfaces AcceptingInterfacesType;
typedef typename ProvidingInterfaces ProvidingInterfacesType;
public:
virtual interfaceStatus ConnectFrom(const char *, ComponentBase*);
//typedef typename AcceptingInterfaces AcceptingInterfacesType;
//typedef typename ProvidingInterfaces ProvidingInterfacesType;
};
/*
//
template <typename First, typename ... Rest>
int ConnectFromBaseQueryInterface(GUID const & id) noexcept
{
if (id == __uuidof(First) || id == __uuidof(::IUnknown))
{
return static_cast<First *>(this);
}
if (IsInspectable<Interfaces ...>() &&
id == __uuidof(::IInspectable))
{
return FindInspectable<Interfaces ...>();
}
return FindInterface<Rest ...>(id);
}
*/
// TEST
template<class InterfaceT>
class InterfaceProvider {
......@@ -179,6 +140,56 @@ struct AcceptorInterfaceName
}
};
template<class InterfaceT>
int InterfaceAcceptor<InterfaceT>::Connect(ComponentBase* providerComponent){
InterfaceT* providerInterface = dynamic_cast<InterfaceT*> (providerComponent);
if (!providerInterface)
{
std::cout << "providerComponent does not have required " << InterfaceName < InterfaceT >::Get() << std::endl;
return 0;
}
// connect value interfaces
this->Set(providerInterface); // due to the input argument being uniquely defined in the multiple inheritance tree, all versions of Set() are accessible at component level
return 1;
}
//template<template<typename... RestInterfacesT> class AcceptingT, typename ProvidingT>
//interfaceStatus Implements<AcceptingT<RestInterfacesT... >, ProvidingT>::ConnectFrom(const char * interfacename, ComponentBase* other)
//{
// :ConnectFrom(const char * interfacename, ComponentBase* other)
//}
template<typename AcceptingInterfaces, typename ProvidingInterfaces>
interfaceStatus Implements<AcceptingInterfaces, ProvidingInterfaces>::ConnectFrom(const char * interfacename, ComponentBase* other)
{
return AcceptingInterfaces::ConnectFromImpl(interfacename, other);
}
template<typename FirstInterface, typename ... RestInterfaces>
interfaceStatus Accepting<FirstInterface, RestInterfaces... >::ConnectFromImpl(const char * interfacename, ComponentBase* other)
{
// does our component have an accepting interface called interfacename?
if (0 ==std::strcmp(InterfaceName<InterfaceAcceptor<FirstInterface>>::Get(), interfacename))
{
// static_cast always succeeds since we know via the template arguments of the component which InterfaceAcceptors its base classes are.
InterfaceAcceptor<FirstInterface>* acceptIF = static_cast<InterfaceAcceptor<FirstInterface>*> (this);
// See if the other component has the right interface and try to connect them
if (1 == acceptIF->Connect(other))
{
//success. By terminating this function, we assume only one interface listens to interfacename and that one connection with the other component can be made by this name
return interfaceStatus::success;
}
else
{
// interfacename was found, but other component doesn't match
return interfaceStatus::noprovider;
}
}
return Accepting< RestInterfaces ... >::ConnectFromImpl(interfacename, other);
}
} // end namespace elx
#endif // #define Interfaces_hxx
\ No newline at end of file
......@@ -8,7 +8,12 @@
namespace elx
{
// SSDMetric3rdPartyComponent provides a value and a derivative
class SSDMetric3rdPartyComponent : public ComponentBase, public MetricDerivativeInterface, public MetricValueInterface {
class SSDMetric3rdPartyComponent :
public Implements<
Accepting<>,
Providing< MetricDerivativeInterface, MetricValueInterface>
>
{
public:
SSDMetric3rdPartyComponent();
~SSDMetric3rdPartyComponent();
......
......@@ -8,7 +8,12 @@
namespace elx
{
// SSDMetric4thPartyComponent provides only a value and not a derivative
class SSDMetric4thPartyComponent : public ComponentBase, public MetricValueInterface {
class SSDMetric4thPartyComponent :
public Implements<
Accepting<>,
Providing< MetricValueInterface>
>
{
public:
SSDMetric4thPartyComponent();
~SSDMetric4thPartyComponent();
......
......@@ -13,8 +13,6 @@
using namespace elx;
int main() {
{
tuple<double, long long, const char*> t1(12.2, 42, "big");
std::cout << InterfaceName<MetricValueInterface>::Get() << std::endl;
std::cout << AcceptorInterfaceName<InterfaceAcceptor<MetricValueInterface>>::Get() << std::endl;
......@@ -47,7 +45,7 @@ using namespace elx;
GDOptimizer4thPartyComponent* tempOptimizer4p = new GDOptimizer4thPartyComponent();
ComponentBase* optimizer4p = tempOptimizer4p; // type returned by our component factory
int success = optimizer4p->ConnectFrom("MetricValueInterface", metric4p);
interfaceStatus IFstatus = optimizer4p->ConnectFrom("MetricValueInterface", metric4p);
InterfaceAcceptor<MetricValueInterface>* opValIF = dynamic_cast<InterfaceAcceptor<MetricValueInterface>*> (optimizer4p);
if (!opValIF)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment