From 126b64a2322cf49040e7b1beb20691f14aac7741 Mon Sep 17 00:00:00 2001
From: Floris Berendsen <floris.berendsen@gmail.com>
Date: Tue, 6 Oct 2015 17:47:05 +0200
Subject: [PATCH] ENH: A ComponentFactory Object now has Set- & Add Criteria,
 and maintains its own possibleComponent list.

---
 Modules/Core/Install/itkComponentFactory.h   | 14 ++--
 Modules/Core/Install/itkComponentFactory.hxx | 69 +++++++++++++-------
 Modules/Core/Install/itkfactory.cxx          | 45 +++++++++++--
 3 files changed, 97 insertions(+), 31 deletions(-)

diff --git a/Modules/Core/Install/itkComponentFactory.h b/Modules/Core/Install/itkComponentFactory.h
index 02d5882d..cdf5a032 100644
--- a/Modules/Core/Install/itkComponentFactory.h
+++ b/Modules/Core/Install/itkComponentFactory.h
@@ -42,6 +42,9 @@ public:
 
   /** Run-time type information (and related methods). */
   itkTypeMacro(ComponentFactory, Object);
+
+  /** New macro for creation of through the object factory. */
+  itkNewMacro(Self);
   
   /** Convenient typedefs. */
   typedef ComponentBase::Pointer ComponentBasePointer;
@@ -49,21 +52,22 @@ public:
 
   typedef std::list< typename ComponentBasePointer > ComponentListType;
   /** set selection criteria for possibleComponents*/
+  void Initialize();
   void SetCriteria(const CriteriaType &criteria);
   
   /** Narrow selection criteria*/
   void AddCriteria(const CriteriaType &criteria);
-
+  
+  void UpdatePossibleComponents(void);
   
   /** Create the appropriate ComponentIO depending on
   *  the particulars of the file.
   */
-  static ComponentBasePointer
-    CreateComponent(const CriteriaType &criteria);
-
+  ComponentBasePointer GetComponent(void);
+  
   
 protected:
-  CriteriaType m_Criteria;
+  mutable CriteriaType m_Criteria;
   mutable ComponentListType m_PossibleComponents;
   ComponentFactory();
   ~ComponentFactory();
diff --git a/Modules/Core/Install/itkComponentFactory.hxx b/Modules/Core/Install/itkComponentFactory.hxx
index 4b6fa215..4f4021f6 100644
--- a/Modules/Core/Install/itkComponentFactory.hxx
+++ b/Modules/Core/Install/itkComponentFactory.hxx
@@ -31,35 +31,60 @@ ComponentFactory::~ComponentFactory()
   {
   }
 
-
-
-ComponentBase::Pointer ComponentFactory::CreateComponent(const CriteriaType &criteria)
+void ComponentFactory::Initialize()
 {
-  std::list< typename ComponentBase::Pointer > possibleComponents;
-//  std::list< LightObject::Pointer >     allobjects =
-//    ObjectFactoryBase::CreateAllInstance("itkComponentIOBaseTemplate");
   std::list< LightObject::Pointer >     allobjects =
     ObjectFactoryBase::CreateAllInstance("itkComponentBase");
 
-  for ( std::list< LightObject::Pointer >::iterator i = allobjects.begin();
-        i != allobjects.end(); ++i )
-    {
+  for (std::list< LightObject::Pointer >::iterator i = allobjects.begin();
+    i != allobjects.end(); ++i)
+  {
     ComponentBase *io =
-                        dynamic_cast< ComponentBase * >( i->GetPointer() );
-    if ( io )
-      {
-        possibleComponents.push_back(io);
-      }
-    }
-  for (std::list< typename ComponentBase::Pointer >::iterator k = possibleComponents.begin();
-    k != possibleComponents.end(); ++k)
+      dynamic_cast<ComponentBase *>(i->GetPointer());
+    if (io)
     {
-      if ( ( *k )->MeetsCriteria(criteria) )
-        {
-        return *k;
-        }
+      this->m_PossibleComponents.push_back(io);
     }
-  return ITK_NULLPTR;
+  }
+}
+void ComponentFactory::SetCriteria(const CriteriaType &criteria)
+{
+  this->Initialize();
+  this->m_Criteria = criteria;
+  this->Modified();
+
+}
+
+void ComponentFactory::AddCriteria(const CriteriaType &criteria)
+{
+  this->m_Criteria.insert(criteria.begin(), criteria.end());
+  this->Modified();
+}
+
+// a predicate implemented as a class:
+//struct FailsCriteria {
+//  bool operator() (const ComponentBasePointer& component) { return !component->MeetsCriteria(this->m_Criteria) }
+//};
+
+void ComponentFactory::UpdatePossibleComponents()
+{
+  // Check each possible component if it meets the criteria
+  // Using a Lambda function.
+  this->m_PossibleComponents.remove_if([&](ComponentBasePointer component){ return !component->MeetsCriteria(this->m_Criteria); });
+}
+ComponentFactory::ComponentBasePointer ComponentFactory::GetComponent()
+{
+  //TODO check if Modified
+  this->UpdatePossibleComponents();
+
+  if (this->m_PossibleComponents.size() == 1)
+  {
+    return *(this->m_PossibleComponents.begin());
+  }
+  else
+  {
+    return ITK_NULLPTR;
+  }
 }
 } // end namespace itk
 
diff --git a/Modules/Core/Install/itkfactory.cxx b/Modules/Core/Install/itkfactory.cxx
index b63a1805..ab4153da 100644
--- a/Modules/Core/Install/itkfactory.cxx
+++ b/Modules/Core/Install/itkfactory.cxx
@@ -60,9 +60,9 @@ int main(int argc, char *argv[])
     << registeredComponents.size()
     << " Component objects available to the Overlord.\n" << std::endl;
 
-  std::cout << "After registering the TransformComponent1 object, ";
   itk::TransformComponent1Factory::RegisterOneFactory();
   itk::MetricComponent1Factory::RegisterOneFactory();
+  std::cout << "After registering the TransformComponent1 and MetricComponent1object, ";
   std::cout << "there are\n";
   registeredComponents = itk::ObjectFactoryBase::CreateAllInstance("itkComponentBase");
   std::cout << registeredComponents.size()
@@ -80,10 +80,47 @@ int main(int argc, char *argv[])
   criteria2["ComponentInput"] = "Transform";
   //criteria1.insert(CriteriumType("ComponentInput", "Metric"));
 
+  CriteriaType emptyCriteria;
+
+  typedef itk::ComponentFactory::Pointer NodePointer;
+
+  NodePointer Node1 = itk::ComponentFactory::New();
+  Node1->SetCriteria(emptyCriteria);
+  ComponentType::Pointer Node1Component = Node1->GetComponent();
+  if (Node1Component.IsNull())
+  {
+    std::cout << "Too few criteria means no Component could be selected." << std::endl;
+  }
+  else
+  {
+    std::cout << "FAILED" << std::endl;
+  }
+
+  // Narrow down the selection criteria
+  Node1->AddCriteria(criteria1);
+  Node1Component = Node1->GetComponent();
+  if (Node1Component.IsNull())
+  {
+    std::cout << "FAILED" << std::endl;
+  }
+  else
+  {
+    std::cout << "Based on criteria, Node1 selected: " << Node1Component->GetNameOfClass() << std::endl;  
+  }
+ 
+  NodePointer Node2 = itk::ComponentFactory::New(); 
+  Node2->SetCriteria(criteria2);
+  ComponentType::Pointer Node2Component = Node2->GetComponent();
+  if (Node2Component.IsNull())
+  {
+    std::cout << "FAILED" << std::endl;
+  }
+  else
+  {
+    std::cout << "Based on criteria, Node2 selected: " << Node2Component->GetNameOfClass() << std::endl;
+  }
+
 
-  ComponentType::Pointer Node1 = itk::ComponentFactory::CreateComponent(criteria1);
-  
-  ComponentType::Pointer Node2 = itk::ComponentFactory::CreateComponent(criteria2);
 
   
 
-- 
GitLab