add assignment or operator for multiple name suggestions
includes tests and config update

Change-Id: I4facf792d89c5ce34bc09f5495c45d0a3bab458a
diff --git a/src/configuration.cpp b/src/configuration.cpp
index 5bad3bb..1386d13 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -23,6 +23,7 @@
 #include <ndn-cxx/util/io.hpp>
 #include <boost/filesystem.hpp>
 #include <name-assignments/assignment-funcs.hpp>
+#include <name-assignments/assignment-or.hpp>
 
 namespace ndn {
 namespace ndncert {
@@ -152,7 +153,7 @@
   m_nameAssignmentFunc = nullptr;
   auto nameAssignmentItems = configJson.get_child_optional(CONFIG_NAME_ASSIGNMENT);
   if (nameAssignmentItems) {
-    std::vector<NameAssignmentFunc> funcs;
+    std::list<NameAssignmentFunc> funcs;
     for (const auto item : *nameAssignmentItems) {
         auto factory = NameAssignmentFuncFactory::createNameAssignmentFuncFactory(item.first);
         if (!factory) {
@@ -167,10 +168,10 @@
     if (funcs.size() < 1) {
         BOOST_THROW_EXCEPTION(std::runtime_error("Empty assignment body supplied"));
     } else if (funcs.size() == 1) {
-        m_nameAssignmentFunc = funcs[0];
+        m_nameAssignmentFunc = *funcs.begin();
     } else {
-        //TODO "or" all the name function together as all suggestions
-        m_nameAssignmentFunc = funcs[0];
+        AssignmentOr orFunction;
+        m_nameAssignmentFunc = orFunction.getFunction(funcs);
     }
   }
 }
diff --git a/src/name-assignments/assignment-or.cpp b/src/name-assignments/assignment-or.cpp
new file mode 100644
index 0000000..cd1f306
--- /dev/null
+++ b/src/name-assignments/assignment-or.cpp
@@ -0,0 +1,73 @@
+//
+// Created by Tyler on 10/6/20.
+//
+
+#include <iosfwd>
+#include "assignment-or.hpp"
+
+namespace ndn {
+namespace ndncert {
+
+_LOG_INIT(ndncert.assignment.or);
+
+NDNCERT_REGISTER_FUNCFACTORY(AssignmentOr, "or");
+
+AssignmentOr::AssignmentOr()
+    : NameAssignmentFuncFactory("or")
+{
+}
+
+NameAssignmentFunc
+AssignmentOr::getFunction(std::list<NameAssignmentFunc> funcs){
+    if (funcs.size() == 1) return *funcs.begin();
+    return OrAssignmentFunc(funcs);
+}
+
+NameAssignmentFunc
+AssignmentOr::getFunction(const std::string &factoryParam) {
+    std::list<NameAssignmentFunc> paramList;
+    std::stringstream ss;
+    ss << factoryParam;
+    JsonSection section;
+    try {
+        boost::property_tree::read_json(ss, section);
+    }
+    catch (const std::exception& error) {
+        BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Failed to parse configuration for name assignment function or, ") + error.what()));
+    }
+    if (section.begin() == section.end()) {
+        BOOST_THROW_EXCEPTION(std::runtime_error("No JSON configuration found for name assignment function"));
+    }
+    for (const auto& item: section) {
+        auto factory = NameAssignmentFuncFactory::createNameAssignmentFuncFactory(item.first);
+        if (!factory) {
+            BOOST_THROW_EXCEPTION(std::runtime_error("Invalid assignment factory type"));
+        }
+        try {
+            paramList.push_back(factory->getFunction(item.second.data()));
+        } catch (const std::exception& e) {
+            BOOST_THROW_EXCEPTION(std::runtime_error("Error on creating function"));
+        }
+    }
+
+    return getFunction(paramList);
+}
+
+AssignmentOr::OrAssignmentFunc::OrAssignmentFunc(std::list<NameAssignmentFunc> funcList)
+    : m_funcList(std::move(funcList))
+{}
+
+std::vector<PartialName>
+AssignmentOr::OrAssignmentFunc::operator() (const std::vector<std::tuple<std::string, std::string>> params)
+{
+  std::vector<PartialName> nameList;
+  for (const auto& func : m_funcList) {
+      auto result = func(params);
+      nameList.insert(nameList.end(), result.begin(), result.end());
+  }
+
+  return nameList;
+}
+
+}
+}
diff --git a/src/name-assignments/assignment-or.hpp b/src/name-assignments/assignment-or.hpp
new file mode 100644
index 0000000..68ffd66
--- /dev/null
+++ b/src/name-assignments/assignment-or.hpp
@@ -0,0 +1,40 @@
+//
+// Created by Tyler on 10/6/20.
+//
+
+#ifndef NDNCERT_ASSIGNMENT_OR_HPP
+#define NDNCERT_ASSIGNMENT_OR_HPP
+
+#include "assignment-funcs.hpp"
+
+namespace ndn {
+namespace ndncert {
+
+/**
+ * assign names base on client probe parameter
+ */
+class AssignmentOr: public NameAssignmentFuncFactory{
+public:
+  AssignmentOr();
+
+  NameAssignmentFunc getFunction(std::list<NameAssignmentFunc> funcs);
+
+  NameAssignmentFunc getFunction(const std::string &factoryParam) override;
+
+  class OrAssignmentFunc {
+  public:
+    OrAssignmentFunc(std::list<NameAssignmentFunc> funcList);
+
+    std::vector<PartialName>
+    operator() (const std::vector<std::tuple<std::string, std::string>> params);
+  private:
+    std::list<NameAssignmentFunc> m_funcList;
+  };
+
+};
+}
+}
+
+
+
+#endif //NDNCERT_ASSIGNMENT_OR_HPP