Refactor : Add a helper function to addFruObjectToDbus

Refactoring addFruObjectToDbus function and created a new helper
function getProductName. Moved this function to fru_utils.cpp as
it is common for all fru-device deamons and avoid code duplication.

This patch is created based on suggestion on the below patch.
https://gerrit.openbmc.org/c/openbmc/entity-manager/+/51555

TESTED : Built Facebook YosemiteV2 images and loaded
on the target hardware. Verified all the fru's read and write.

Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>
Change-Id: I272d2fd2fc664a471774c668503d87147eb80a54
diff --git a/include/fru_utils.hpp b/include/fru_utils.hpp
index 20d1b66..64765b0 100644
--- a/include/fru_utils.hpp
+++ b/include/fru_utils.hpp
@@ -191,6 +191,7 @@
 /// properties.
 /// \return true on success false on failure. restFieldLoc and restFieldEnd
 /// are updated.
+
 bool copyRestFRUArea(std::vector<uint8_t>& fruData,
                      const std::string& propertyName,
                      struct FruArea& fruAreaParams,
@@ -207,3 +208,17 @@
         std::pair<size_t, size_t>,
         std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
     std::string& productName);
+
+/// \brief It does format fru data and find productName in the formatted
+/// fru data and return productName.
+/// \param device - vector that contains device list
+/// \param formattedFRU - map that contains formatted FRU data
+/// \param bus - bus number of the device
+/// \param address - address of the device
+/// \param unknownBusObjectCount - Unknown Bus object counter variable
+/// \return optional string. it returns productName or NULL
+
+std::optional<std::string> getProductName(
+    std::vector<uint8_t>& device,
+    boost::container::flat_map<std::string, std::string>& formattedFRU,
+    uint32_t bus, uint32_t address, size_t& unknownBusObjectCount);
diff --git a/src/fru_device.cpp b/src/fru_device.cpp
index c4272cb..26ac516 100644
--- a/src/fru_device.cpp
+++ b/src/fru_device.cpp
@@ -657,40 +657,16 @@
     std::shared_ptr<sdbusplus::asio::connection>& systemBus)
 {
     boost::container::flat_map<std::string, std::string> formattedFRU;
-    resCodes res = formatIPMIFRU(device, formattedFRU);
-    if (res == resCodes::resErr)
+
+    std::optional<std::string> optionalProductName = getProductName(
+        device, formattedFRU, bus, address, unknownBusObjectCount);
+    if (!optionalProductName)
     {
-        std::cerr << "failed to parse FRU for device at bus " << bus
-                  << " address " << address << "\n";
+        std::cerr << "getProductName failed. product name is empty.\n";
         return;
     }
-    if (res == resCodes::resWarn)
-    {
-        std::cerr << "there were warnings while parsing FRU for device at bus "
-                  << bus << " address " << address << "\n";
-    }
 
-    auto productNameFind = formattedFRU.find("BOARD_PRODUCT_NAME");
-    std::string productName;
-    // Not found under Board section or an empty string.
-    if (productNameFind == formattedFRU.end() ||
-        productNameFind->second.empty())
-    {
-        productNameFind = formattedFRU.find("PRODUCT_PRODUCT_NAME");
-    }
-    // Found under Product section and not an empty string.
-    if (productNameFind != formattedFRU.end() &&
-        !productNameFind->second.empty())
-    {
-        productName = productNameFind->second;
-        std::regex illegalObject("[^A-Za-z0-9_]");
-        productName = std::regex_replace(productName, illegalObject, "_");
-    }
-    else
-    {
-        productName = "UNKNOWN" + std::to_string(unknownBusObjectCount);
-        unknownBusObjectCount++;
-    }
+    std::string productName = optionalProductName.value();
 
     std::optional<int> index = findIndexForFRU(dbusInterfaceMap, productName);
     if (index.has_value())
diff --git a/src/fru_utils.cpp b/src/fru_utils.cpp
index 25cd37e..bcc1180 100644
--- a/src/fru_utils.cpp
+++ b/src/fru_utils.cpp
@@ -987,3 +987,50 @@
     }
     return highest;
 }
+
+// This function does format fru data as per IPMI format and find the
+// productName in the formatted fru data, get that productName and return
+// productName if found or return NULL.
+
+std::optional<std::string> getProductName(
+    std::vector<uint8_t>& device,
+    boost::container::flat_map<std::string, std::string>& formattedFRU,
+    uint32_t bus, uint32_t address, size_t& unknownBusObjectCount)
+{
+    std::string productName;
+
+    resCodes res = formatIPMIFRU(device, formattedFRU);
+    if (res == resCodes::resErr)
+    {
+        std::cerr << "failed to parse FRU for device at bus " << bus
+                  << " address " << address << "\n";
+        return std::nullopt;
+    }
+    if (res == resCodes::resWarn)
+    {
+        std::cerr << "Warnings while parsing FRU for device at bus " << bus
+                  << " address " << address << "\n";
+    }
+
+    auto productNameFind = formattedFRU.find("BOARD_PRODUCT_NAME");
+    // Not found under Board section or an empty string.
+    if (productNameFind == formattedFRU.end() ||
+        productNameFind->second.empty())
+    {
+        productNameFind = formattedFRU.find("PRODUCT_PRODUCT_NAME");
+    }
+    // Found under Product section and not an empty string.
+    if (productNameFind != formattedFRU.end() &&
+        !productNameFind->second.empty())
+    {
+        productName = productNameFind->second;
+        std::regex illegalObject("[^A-Za-z0-9_]");
+        productName = std::regex_replace(productName, illegalObject, "_");
+    }
+    else
+    {
+        productName = "UNKNOWN" + std::to_string(unknownBusObjectCount);
+        unknownBusObjectCount++;
+    }
+    return productName;
+}