From 8db4df61a465b41c5f153fa064a4db22cad0600d Mon Sep 17 00:00:00 2001
From: Kasper Marstal <kaspermarstal@gmail.com>
Date: Tue, 29 Sep 2015 11:34:24 +0200
Subject: [PATCH] ENH: ELASTIX-9 Add ComponentDescriptor class

---
 .../Core/Blueprints/include/elxBlueprint.h    | 35 ++++++++------
 .../include/elxComponentDescriptor.h          | 20 ++++----
 Modules/Core/Blueprints/src/elxBlueprint.hxx  |  3 +-
 .../Blueprints/src/elxComponentDescriptor.hxx | 46 +++++++++++++++++++
 Modules/Core/ElastixFilter/CMakeLists.txt     |  1 +
 .../ElastixFilter/include/elxElastixFilter.h  |  5 ++
 Testing/Unit/elxBluePrintTest.cxx             | 19 ++++----
 7 files changed, 93 insertions(+), 36 deletions(-)
 create mode 100644 Modules/Core/Blueprints/src/elxComponentDescriptor.hxx
 create mode 100644 Modules/Core/ElastixFilter/CMakeLists.txt
 create mode 100644 Modules/Core/ElastixFilter/include/elxElastixFilter.h

diff --git a/Modules/Core/Blueprints/include/elxBlueprint.h b/Modules/Core/Blueprints/include/elxBlueprint.h
index 02720821..9531a695 100644
--- a/Modules/Core/Blueprints/include/elxBlueprint.h
+++ b/Modules/Core/Blueprints/include/elxBlueprint.h
@@ -19,30 +19,37 @@ public:
 
   elxNewMacro( Blueprint, itk::DataObject );
 
-  typedef TComponentDescriptor                                           ComponentDescriptorType;
+  typedef TComponentDescriptor                                                ComponentDescriptorType;
+  typedef typename TComponentDescriptor::ComponentNameType                    ComponentNameType;
   
   typedef boost::adjacency_list< boost::listS,      
                                  boost::listS,      
                                  boost::directedS,
-                                 ComponentDescriptorType >               GraphType;
+                                 ComponentDescriptorType >                    GraphType;
 
-  typedef typename boost::graph_traits< GraphType >::vertex_descriptor   ComponentType;
-  typedef typename boost::graph_traits< GraphType >::vertex_iterator     ComponentIterator, ComponentIteratorEnd;
+  typedef typename boost::graph_traits< GraphType >::vertex_descriptor        ComponentType;
+  typedef typename boost::graph_traits< GraphType >::vertex_iterator          ComponentIterator, ComponentIteratorEnd;
 
-  typedef typename boost::graph_traits< GraphType >::edge_descriptor     ConnectionDescriptorType;
-  typedef typename boost::graph_traits< GraphType >::edge_iterator       ConnectionIterator, ConnectionIteratorEnd;
+  
+
+  // TODO: Why can't we get the vertex index map type like they show in 
+  // http://www.boost.org/doc/libs/1_38_0/libs/graph/doc/quick_tour.html
+  // under "Access Vertex Set"?
+  typedef boost::vertex_index_t                                               ComponentIndexType;
+  typedef typename boost::property_map< GraphType, ComponentIndexType >::type ComponentIndexMapType;
 
-  typedef typename boost::graph_traits< GraphType >::in_edge_iterator    InputIterator, InputIteratorEnd;
-  typedef typename boost::graph_traits< GraphType >::out_edge_iterator   OutputIterator, OutputIteratorEnd;
+  typedef typename boost::graph_traits< GraphType >::edge_descriptor          ConnectionDescriptorType;
+  typedef typename boost::graph_traits< GraphType >::edge_iterator            ConnectionIterator, ConnectionIteratorEnd;
 
-  void SetGraph( GraphType graph ) { this->m_Graph = graph; };
-  GraphType GetGraph( void ) const { return m_Graph; };
+  typedef typename boost::graph_traits< GraphType >::in_edge_iterator         InputIterator, InputIteratorEnd;
+  typedef typename boost::graph_traits< GraphType >::out_edge_iterator        OutputIterator, OutputIteratorEnd;
 
-  void AddComponent( ComponentDescriptorType component );
-  void RemoveComponent( ComponentDescriptorType component );
+  bool AddComponent( ComponentDescriptorType component );
+  // bool SetComponent( ComponentIndexType componentIndex, ComponentDescriptorType component );
+  // ComponentDescriptorType GetComponent( ComponentIndexType componentIndex );
 
-  void AddConnection( ComponentDescriptorType upstream, ComponentDescriptorType downstream );
-  void RemoveConnection( ConnectionDescriptorType connection );
+  // bool SetConnection( ComponentIndexType upstream, ComponentIndexType downstream );
+  ConnectionDescriptorType GetConnection( ConnectionDescriptorType Connection );
 
 private:
 
diff --git a/Modules/Core/Blueprints/include/elxComponentDescriptor.h b/Modules/Core/Blueprints/include/elxComponentDescriptor.h
index c6ace2d9..8cfcde65 100644
--- a/Modules/Core/Blueprints/include/elxComponentDescriptor.h
+++ b/Modules/Core/Blueprints/include/elxComponentDescriptor.h
@@ -2,29 +2,29 @@
 #define __ComponentDescriptor_h
 
 #include "elxMacro.h"
-#include "itkLightObject.h"
+#include "itkDataObject.h"
 
 namespace elx {
 
-class ComponentDescriptor : public itk::LightObject
+class ComponentDescriptor : public itk::DataObject
 {
 public:
 
-  elxNewMacro( ComponentDescriptor, itk::LightObject );
+  elxNewMacro( ComponentDescriptor, itk::DataObject );
 
-  typedef std::string                                         ComponentNameType;
-  typedef std::map< std::string, std::vector< std::string > > ParameterMapType;
+  // Identifier to find component in the component database
+  typedef std::string ComponentNameType;
 
-  void SetComponentName( ComponentNameType componentName ) { this->m_ComponentName = componentName; };
-  ComponentNameType GetComponentName( void ) { return this->m_ComponentName; };
+  // TODO: Setter should validate ComponentName exists in ComponentDatabase
+  itkSetMacro( ComponentName, ComponentNameType ); 
+  itkGetMacro( ComponentName, ComponentNameType );
 
 private:
 
-  ComponentNameType  m_ComponentName;
-  ParameterMapType   m_ParameterMap;
+  ComponentNameType m_ComponentName;
 
 };
 
 }
 
-#endif // __ComponentDescriptor_h
\ No newline at end of file
+#endif // __ComponentDescriptor_h
diff --git a/Modules/Core/Blueprints/src/elxBlueprint.hxx b/Modules/Core/Blueprints/src/elxBlueprint.hxx
index b37fe4d6..d5be04e6 100644
--- a/Modules/Core/Blueprints/src/elxBlueprint.hxx
+++ b/Modules/Core/Blueprints/src/elxBlueprint.hxx
@@ -11,13 +11,14 @@ void
 Blueprint< ComponentDescriptor >
 ::Blueprint( void )
 {
-  this->m_Graph = GraphType;
+  this->SetGraph( GraphType );
 }
 
 ComponentDescriptorType
 Blueprint< ComponentDescriptor >
 ::AddComponent( ComponentDescriptorType component )
 {
+  // TODO: Check that the component is in the component::ComponentName is in the ComponentDatabase
   this->Modified();
   return this->m_Graph->add_vertex( component );
 }
diff --git a/Modules/Core/Blueprints/src/elxComponentDescriptor.hxx b/Modules/Core/Blueprints/src/elxComponentDescriptor.hxx
new file mode 100644
index 00000000..b37f5f3f
--- /dev/null
+++ b/Modules/Core/Blueprints/src/elxComponentDescriptor.hxx
@@ -0,0 +1,46 @@
+#ifndef __ComponentDescriptor_hxx
+#define __ComponentDescriptor_hxx
+
+#include "elxComponentDescriptor.h"
+
+// TODO: Need enum for component name?
+
+namespace elx {
+
+ComponentDescriptor
+::ComponentDescriptor( const ComponentNameType componentName )
+{
+  this->SetComponentName( componentName );
+  this->SetComponentUniqueId( this->GenerateUniqueId() );
+  this->SetParameterMap( this->ParameterMapType() );
+}
+
+ComponentDescriptor
+::ComponentDescriptor( const ComponentNameType componentName, 
+                       const ComponentUniqueIdType componentUniqueId )
+{
+  this->SetComponentName( componentName );
+  this->SetComponentUniqueId( componentUniqueId );
+  this->SetParameterMap( this->ParameterMapType() );
+}
+
+ComponentDescriptor
+::ComponentDescriptor( const ComponentNameType componentName,
+                       const ComponentIdType componentUniqueId,
+                       const ParameterMapType parameterMap )
+{
+  this->SetComponentName( componentName );
+  this->SetComponentUniqueId( componentUniqueId );
+  this->SetParameterMap( parameterMap );
+}
+
+ComponentDescriptor::ComponentIdType
+ComponentDescriptor
+::GenerateUniqueId()
+{
+
+}
+
+} // namespace elx
+
+#endif // __ComponentDescriptor_hxx
\ No newline at end of file
diff --git a/Modules/Core/ElastixFilter/CMakeLists.txt b/Modules/Core/ElastixFilter/CMakeLists.txt
new file mode 100644
index 00000000..b83cfce3
--- /dev/null
+++ b/Modules/Core/ElastixFilter/CMakeLists.txt
@@ -0,0 +1 @@
+include_directories( include )
diff --git a/Modules/Core/ElastixFilter/include/elxElastixFilter.h b/Modules/Core/ElastixFilter/include/elxElastixFilter.h
new file mode 100644
index 00000000..99dc4e66
--- /dev/null
+++ b/Modules/Core/ElastixFilter/include/elxElastixFilter.h
@@ -0,0 +1,5 @@
+#ifndef __ElastixFilter_h
+#define __ElastixFilter_h
+
+
+#endif // #define __ElastixFilter_h
\ No newline at end of file
diff --git a/Testing/Unit/elxBluePrintTest.cxx b/Testing/Unit/elxBluePrintTest.cxx
index d3cc27fe..5451c97b 100644
--- a/Testing/Unit/elxBluePrintTest.cxx
+++ b/Testing/Unit/elxBluePrintTest.cxx
@@ -6,21 +6,18 @@ namespace elx {
 
 TEST( Blueprint, Instantiation )
 {
-  typedef Blueprint< ComponentDescriptor >  BlueprintType;
-  BlueprintType::Pointer blueprint = BlueprintType::New();
+  typedef Blueprint< ComponentDescriptor > BlueprintType;
+  BlueprintType::Pointer blueprint;
+  EXPECT_NO_THROW( blueprint = BlueprintType::New() );
 
   typedef BlueprintType::ComponentDescriptorType ComponentDescriptorType;
-  ComponentDescriptorType::Pointer componentDescriptor = ComponentDescriptorType::New();
+  ComponentDescriptorType::Pointer componentDescriptor;
+  EXPECT_NO_THROW( componentDescriptor = ComponentDescriptorType::New() );
 
   typedef ComponentDescriptorType::ComponentNameType ComponentNameType;
-  ComponentNameType componentName = ComponentNameType("Metric");
-  componentDescriptor->SetComponentName( componentName );
-
-  // We would like to save all data in the graph itself, but the following is 
-  // not possible because the component (of type itk::LightObject has private copy 
-  // constructor. How do we save data in graph and make this as itk-like as possible?
-  // Ideally when a component descriptor is changed the blueprint calls Modified() on itself
-  // blueprint->AddComponent( (*componentDescriptor) );
+  ComponentNameType componentName;
+  EXPECT_NO_THROW( componentName = ComponentNameType("Metric") );
+  EXPECT_NO_THROW( componentDescriptor->SetComponentName( componentName ) );
 
   ASSERT_TRUE( true );
 }
-- 
GitLab