Added PowerSupply frus:

The dumpInventory and dumpObject options of VPD tool
now includes PowerSupply frus.

Signed-off-by: PriyangaRamasamy <priyanga24@in.ibm.com>
Change-Id: I6078d966780898a20a4c3e7c5cc61c3f4f2e6ddd
diff --git a/vpd_tool_impl.cpp b/vpd_tool_impl.cpp
index 893109c..a424312 100644
--- a/vpd_tool_impl.cpp
+++ b/vpd_tool_impl.cpp
@@ -1,5 +1,7 @@
 #include "vpd_tool_impl.hpp"
 
+#include <cstdlib>
+#include <filesystem>
 #include <iomanip>
 #include <iostream>
 #include <sdbusplus/bus.hpp>
@@ -10,6 +12,36 @@
 using namespace std;
 using sdbusplus::exception::SdBusError;
 using namespace openpower::vpd;
+namespace fs = std::filesystem;
+
+void VpdTool::eraseInventoryPath(string& fru)
+{
+    // Power supply frupath comes with INVENTORY_PATH appended in prefix.
+    // Stripping it off inorder to avoid INVENTORY_PATH duplication
+    // during getVINIProperties() execution.
+    fru.erase(0, sizeof(INVENTORY_PATH) - 1);
+}
+
+void VpdTool::getPowerSupplyFruPath(vector<string>& powSuppFrus)
+{
+    auto bus = sdbusplus::bus::new_default();
+    auto properties = bus.new_method_call(
+        OBJECT_MAPPER_SERVICE, OBJECT_MAPPER_OBJECT,
+        "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths");
+    properties.append(INVENTORY_PATH);
+    properties.append(0);
+    properties.append(std::array<const char*, 1>{POWER_SUPPLY_TYPE_INTERFACE});
+
+    auto result = bus.call(properties);
+
+    if (result.is_method_error())
+    {
+        throw runtime_error(
+            "GetSubTreePaths api in ObjectMapper service is failed.");
+    }
+
+    result.read(powSuppFrus);
+}
 
 void VpdTool::debugger(json output)
 {
@@ -37,13 +69,23 @@
 void VpdTool::addFruTypeAndLocation(json exIntf, const string& object,
                                     json& kwVal)
 {
-    for (const auto& intf : exIntf.items())
+    if (object.find("powersupply") != string::npos)
     {
-        if ((intf.key().find("Item") != string::npos) &&
-            (intf.value().is_null()))
+        kwVal.emplace("type", POWER_SUPPLY_TYPE_INTERFACE);
+    }
+
+    // add else if statement for fan fru
+
+    else
+    {
+        for (const auto& intf : exIntf.items())
         {
-            kwVal.emplace("type", intf.key());
-            break;
+            if ((intf.key().find("Item") != string::npos) &&
+                (intf.value().is_null()))
+            {
+                kwVal.emplace("type", intf.key());
+                break;
+            }
         }
     }
 
@@ -76,7 +118,17 @@
 
     vector<string> keyword{"CC", "SN", "PN", "FN", "DR"};
     string interface = "com.ibm.ipzvpd.VINI";
-    string objectName = INVENTORY_PATH + invPath;
+    string objectName = {};
+
+    if (invPath.find(INVENTORY_PATH) != string::npos)
+    {
+        objectName = invPath;
+        eraseInventoryPath(invPath);
+    }
+    else
+    {
+        objectName = INVENTORY_PATH + invPath;
+    }
 
     for (string kw : keyword)
     {
@@ -223,14 +275,40 @@
 void VpdTool::dumpInventory(const nlohmann::basic_json<>& jsObject)
 {
     char flag = 'I';
-    json output = parseInvJson(jsObject, flag, "");
+    json output = json::array({});
+    output.emplace_back(parseInvJson(jsObject, flag, ""));
+
+    vector<string> powSuppFrus;
+
+    getPowerSupplyFruPath(powSuppFrus);
+
+    for (const auto& fru : powSuppFrus)
+    {
+        output.emplace_back(
+            getVINIProperties(fru, nlohmann::detail::value_t::null));
+    }
+
     debugger(output);
 }
 
 void VpdTool::dumpObject(const nlohmann::basic_json<>& jsObject)
 {
     char flag = 'O';
-    json output = parseInvJson(jsObject, flag, fruPath);
+    json output = json::array({});
+    vector<string> powSuppFrus;
+
+    getPowerSupplyFruPath(powSuppFrus);
+
+    if (find(powSuppFrus.begin(), powSuppFrus.end(), fruPath) !=
+        powSuppFrus.end())
+    {
+        output.emplace_back(
+            getVINIProperties(fruPath, nlohmann::detail::value_t::null));
+    }
+    else
+    {
+        output.emplace_back(parseInvJson(jsObject, flag, fruPath));
+    }
     debugger(output);
 }