From 7e6b33d4b48ee1eddf9d256ef4812dc5af344100 Mon Sep 17 00:00:00 2001
From: Floris Berendsen <floris.berendsen@gmail.com>
Date: Mon, 16 Nov 2015 11:54:24 +0100
Subject: [PATCH] ENH: added InterfaceName Type Traits and ConnectFrom

---
 .../Core/ComponentInterface/ComponentBase.h   |  3 +
 .../GDOptimizer3rdPartyComponent.cxx          | 29 ++++++++
 .../GDOptimizer3rdPartyComponent.h            |  2 +
 .../GDOptimizer4thPartyComponent.cxx          | 17 +++++
 .../GDOptimizer4thPartyComponent.h            |  1 +
 .../Core/ComponentInterface/Interfaces.hxx    | 69 +++++++++++++++++++
 .../ComponentInterface/componenthandshake.cxx | 14 ++++
 7 files changed, 135 insertions(+)

diff --git a/Modules/Core/ComponentInterface/ComponentBase.h b/Modules/Core/ComponentInterface/ComponentBase.h
index 3249b12a..78da4c6a 100644
--- a/Modules/Core/ComponentInterface/ComponentBase.h
+++ b/Modules/Core/ComponentInterface/ComponentBase.h
@@ -5,7 +5,10 @@ namespace elx
 {
   class ComponentBase {
   public:
+    virtual int ConnectFrom(const char *, ComponentBase*) { return 0; }; //= 0;
+  protected:
     virtual ~ComponentBase(){};
   };
+
 } // end namespace elx
 #endif // #define ComponentBase_h
\ No newline at end of file
diff --git a/Modules/Core/ComponentInterface/GDOptimizer3rdPartyComponent.cxx b/Modules/Core/ComponentInterface/GDOptimizer3rdPartyComponent.cxx
index b2118b13..0b8fac5c 100644
--- a/Modules/Core/ComponentInterface/GDOptimizer3rdPartyComponent.cxx
+++ b/Modules/Core/ComponentInterface/GDOptimizer3rdPartyComponent.cxx
@@ -13,6 +13,35 @@ GDOptimizer3rdPartyComponent::~GDOptimizer3rdPartyComponent()
   delete this->MetricObject;
 }
 
+
+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);
+    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
+  }
+  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);
diff --git a/Modules/Core/ComponentInterface/GDOptimizer3rdPartyComponent.h b/Modules/Core/ComponentInterface/GDOptimizer3rdPartyComponent.h
index 8ff19a2f..7addba7b 100644
--- a/Modules/Core/ComponentInterface/GDOptimizer3rdPartyComponent.h
+++ b/Modules/Core/ComponentInterface/GDOptimizer3rdPartyComponent.h
@@ -5,6 +5,7 @@
 #include "Interfaces.hxx"
 #include "Example3rdPartyCode.h"
 #include "Metric3rdPartyWrapper.h"
+#include <string.h>
 
 namespace elx
 {
@@ -15,6 +16,7 @@ namespace elx
     ~GDOptimizer3rdPartyComponent();
     Example3rdParty::GDOptimizer3rdParty* theImplementation;
     Metric3rdPartyWrapper* MetricObject;
+    virtual int ConnectFrom(const char *, ComponentBase*);
     int Set(MetricValueInterface*);
     int Set(MetricDerivativeInterface*);
     int Update();
diff --git a/Modules/Core/ComponentInterface/GDOptimizer4thPartyComponent.cxx b/Modules/Core/ComponentInterface/GDOptimizer4thPartyComponent.cxx
index cd797a94..16df9f8d 100644
--- a/Modules/Core/ComponentInterface/GDOptimizer4thPartyComponent.cxx
+++ b/Modules/Core/ComponentInterface/GDOptimizer4thPartyComponent.cxx
@@ -15,6 +15,23 @@ 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)
 {
   this->MetricObject->SetMetricValueComponent(component);
diff --git a/Modules/Core/ComponentInterface/GDOptimizer4thPartyComponent.h b/Modules/Core/ComponentInterface/GDOptimizer4thPartyComponent.h
index f6598949..2e3a33d8 100644
--- a/Modules/Core/ComponentInterface/GDOptimizer4thPartyComponent.h
+++ b/Modules/Core/ComponentInterface/GDOptimizer4thPartyComponent.h
@@ -16,6 +16,7 @@ namespace elx
     ~GDOptimizer4thPartyComponent();
     Example4thParty::GDOptimizer4thParty* theImplementation;
     Metric4thPartyWrapper* MetricObject;
+    virtual int ConnectFrom(const char *, ComponentBase*);
     int Set(MetricValueInterface*);
     int Update();
   };
diff --git a/Modules/Core/ComponentInterface/Interfaces.hxx b/Modules/Core/ComponentInterface/Interfaces.hxx
index ee85ebeb..c74468bb 100644
--- a/Modules/Core/ComponentInterface/Interfaces.hxx
+++ b/Modules/Core/ComponentInterface/Interfaces.hxx
@@ -46,5 +46,74 @@ int InterfaceAcceptor<InterfaceT>::Connect(ComponentBase* providerComponent){
     return 1;
   }
 
+
+// TEST
+template<class InterfaceT>
+class InterfaceProvider {
+public:
+  virtual int Set(InterfaceT*) {};
+private:
+};
+
+
+// Traits to get printable interface name
+// default implementation
+template <typename T>
+struct InterfaceName
+{
+  static const char* Get()
+  {
+    return typeid(T).name();
+  }
+};
+
+// a specialization for each type of those you want to support
+// and don't like the string returned by typeid
+template <>
+struct InterfaceName < MetricValueInterface >
+{
+  static const char* Get()
+  {
+    return "MetricValueInterface";
+  }
+};
+template <>
+struct InterfaceName < MetricDerivativeInterface >
+{
+  static const char* Get()
+  {
+    return "MetricDerivativeInterface";
+  }
+};
+template <>
+struct InterfaceName < OptimizerUpdateInterface >
+{
+  static const char* Get()
+  {
+    return "OptimizerUpdateInterface";
+  }
+};
+
+
+// partial specialization of InterfaceName
+template<template<typename> class TT, typename T1>
+struct InterfaceName < TT<T1> > {
+  static const char* Get()
+  {
+    return InterfaceName<T1>::Get();
+  }
+};
+
+
+template <typename T>
+struct AcceptorInterfaceName
+{
+  static const char* Get()
+  {
+    return InterfaceName<T>::Get();
+  }
+};
+
+
 } // end namespace elx
 #endif // #define Interfaces_hxx
\ No newline at end of file
diff --git a/Modules/Core/ComponentInterface/componenthandshake.cxx b/Modules/Core/ComponentInterface/componenthandshake.cxx
index b7cb8fed..930b2028 100644
--- a/Modules/Core/ComponentInterface/componenthandshake.cxx
+++ b/Modules/Core/ComponentInterface/componenthandshake.cxx
@@ -8,8 +8,20 @@
 #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
@@ -33,6 +45,8 @@ using namespace elx;
     GDOptimizer4thPartyComponent* tempOptimizer4p = new GDOptimizer4thPartyComponent();
     ComponentBase* optimizer4p = tempOptimizer4p; // type returned by our component factory
 
+    int success = optimizer4p->ConnectFrom("MetricValueInterface", metric4p);
+
     InterfaceAcceptor<MetricValueInterface>* opValIF = dynamic_cast<InterfaceAcceptor<MetricValueInterface>*> (optimizer4p);
     if (!opValIF)
     {
-- 
GitLab