Integrate DataQuery

Change-Id: I439374afe485baf08a4d5a1a02fd70d908bec9e1
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index e59fc36..6ecfbc5 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -30,7 +30,7 @@
             _pass(context) = false;
             parserContext.m_errorMsg = "Key \"" + ast.first + "\" was entered more than once.";
         } else {
-            parserContext.m_tmpListKeys.insert(ast.first);
+            parserContext.m_tmpListKeys.insert({ast.first, ast.second});
         }
     }
 
@@ -68,11 +68,11 @@
 
         if (schema.listHasKey(location, list, ast)) {
             schemaNode_ listNode;
-            listNode.m_prefix = parserContext.m_curModule ? boost::optional<module_>{{*parserContext.m_curModule}} : boost::none;
+            listNode.m_prefix = parserContext.m_curModule.flat_map([] (auto mod) { return boost::optional<module_>{{mod}}; });;
             listNode.m_suffix = list_{parserContext.m_tmpListName};
             location.m_nodes.push_back(listNode);
             parserContext.m_tmpListKeyLeafPath.m_location = location;
-            parserContext.m_tmpListKeyLeafPath.m_node = {boost::none, ast};
+            parserContext.m_tmpListKeyLeafPath.m_node = { parserContext.m_curModule, ast };
         } else {
             parserContext.m_errorMsg = parserContext.m_tmpListName + " is not indexed by \"" + ast + "\".";
             _pass(context) = false;
@@ -577,7 +577,7 @@
     }
 };
 
-std::set<std::string> generateMissingKeyCompletionSet(std::set<std::string> keysNeeded, std::set<std::string> currentSet);
+std::set<std::string> generateMissingKeyCompletionSet(std::set<std::string> keysNeeded, std::map<std::string, leaf_data_> currentSet);
 
 struct createKeySuggestions_class {
     template <typename T, typename Iterator, typename Context>
@@ -593,6 +593,42 @@
     }
 };
 
+std::string leafDataToCompletion(const leaf_data_& value);
+
+struct createValueSuggestions_class {
+    template <typename T, typename Iterator, typename Context>
+    void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
+    {
+        auto& parserContext = x3::get<parser_context_tag>(context);
+        if (!parserContext.m_completing) {
+            return;
+        }
+        const auto& dataQuery = parserContext.m_dataquery;
+
+        parserContext.m_completionIterator = begin;
+        auto listInstances = dataQuery->listKeys(parserContext.currentDataPath(), {parserContext.m_curModule, parserContext.m_tmpListName});
+
+        decltype(listInstances) filteredInstances;
+        //This filters out instances, which don't correspond to the partial instance we have.
+        const auto partialFitsComplete = [&parserContext] (const auto& complete) {
+            const auto& partial = parserContext.m_tmpListKeys;
+            return std::all_of(partial.begin(), partial.end(), [&complete] (const auto& oneKV) {
+                    const auto& [k, v] = oneKV;
+                    return complete.at(k) == v;
+                    });
+        };
+        std::copy_if(listInstances.begin(), listInstances.end(), std::inserter(filteredInstances, filteredInstances.end()), partialFitsComplete);
+
+        std::set<std::string> validValues;
+
+        std::transform(filteredInstances.begin(), filteredInstances.end(), std::inserter(validValues, validValues.end()), [&parserContext] (const auto& instance) {
+            return leafDataToCompletion(instance.at(parserContext.m_tmpListKeyLeafPath.m_node.second));
+        });
+
+        parserContext.m_suggestions = validValues;
+    }
+};
+
 struct suggestKeysEnd_class {
     template <typename T, typename Iterator, typename Context>
     void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)