topology: get opposite association

Introduce function getOppositeAssoc to get the opposite association
instead of hardcoding it.

For example powering -> powered_by.

Tested: Topology Unit Tests Pass

Change-Id: I2b902c7e5bd7d7bcc124b4c8f25e2dd14200c6bb
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
diff --git a/src/entity_manager/topology.cpp b/src/entity_manager/topology.cpp
index d2f7f33..8f7b7b1 100644
--- a/src/entity_manager/topology.cpp
+++ b/src/entity_manager/topology.cpp
@@ -101,14 +101,52 @@
         return;
     }
 
-    result[downstream].insert({"contained_by", "containing", upstream});
+    std::string assoc = "contained_by";
+    std::optional<std::string> opposite = getOppositeAssoc(assoc);
+
+    if (!opposite.has_value())
+    {
+        return;
+    }
+
+    result[downstream].insert({assoc, opposite.value(), upstream});
 
     if (powerPaths.contains(downstream))
     {
-        result[downstream].insert({"powering", "powered_by", upstream});
+        assoc = "powering";
+        opposite = getOppositeAssoc(assoc);
+        if (!opposite.has_value())
+        {
+            return;
+        }
+
+        result[downstream].insert({assoc, opposite.value(), upstream});
     }
 }
 
+const std::set<std::pair<std::string, std::string>> assocs = {
+    {"powering", "powered_by"}, {"containing", "contained_by"},
+    // ... extend as needed
+};
+
+std::optional<std::string> Topology::getOppositeAssoc(
+    const AssocName& assocName)
+{
+    for (const auto& entry : assocs)
+    {
+        if (entry.first == assocName)
+        {
+            return entry.second;
+        }
+        if (entry.second == assocName)
+        {
+            return entry.first;
+        }
+    }
+
+    return std::nullopt;
+}
+
 void Topology::remove(const std::string& boardName)
 {
     // Remove the board from boardNames, and then using the path