Api changes in AddReportFuture version

Added support for CollectionFunction, CollectionDuration,
CollectionTimeScope, ReportUpdates, AppendLimit.

New API separates Id and Name, user can decide to pass only Name
to auto generate Id or pass Id which needs to be unique.

Tested:
- No functional changes to old API, everything works as before
- All use cases can be replaced with new API to achieve same results
- New features which require new API work as expected

Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: I647efab36d90a548754f89968223e162a087481e
diff --git a/src/report_manager.cpp b/src/report_manager.cpp
index ab76a31..18636f8 100644
--- a/src/report_manager.cpp
+++ b/src/report_manager.cpp
@@ -3,6 +3,7 @@
 #include "report.hpp"
 #include "types/report_types.hpp"
 #include "utils/conversion.hpp"
+#include "utils/generate_id.hpp"
 #include "utils/transform.hpp"
 
 #include <phosphor-logging/log.hpp>
@@ -17,10 +18,14 @@
     return utils::transform(params, [](const auto& param) {
         using namespace std::chrono_literals;
 
+        const auto& [sensorPath, operationType, id, metadata] = param;
+
         return ReadingParameters::value_type(
-            std::vector{{std::get<0>(param)}}, std::get<1>(param),
-            std::get<2>(param), std::get<3>(param),
-            utils::enumToString(CollectionTimeScope::point), 0u);
+            std::vector<
+                std::tuple<sdbusplus::message::object_path, std::string>>{
+                {sensorPath, metadata}},
+            operationType, id, utils::enumToString(CollectionTimeScope::point),
+            0u);
     });
 }
 
@@ -41,16 +46,16 @@
                 "MaxReports", size_t{}, sdbusplus::vtable::property_::const_,
                 [](const auto&) { return maxReports; });
             dbusIface.register_property_r(
-                "MaxReportNameLength", size_t{},
+                "MaxReportIdLength", size_t{},
                 sdbusplus::vtable::property_::const_,
-                [](const auto&) { return maxReportNameLength; });
+                [](const auto&) { return maxReportIdLength; });
             dbusIface.register_property_r(
                 "MinInterval", uint64_t{}, sdbusplus::vtable::property_::const_,
                 [](const auto&) -> uint64_t { return minInterval.count(); });
 
             dbusIface.register_method(
                 "AddReport", [this](boost::asio::yield_context& yield,
-                                    const std::string& reportName,
+                                    const std::string& reportId,
                                     const std::string& reportingType,
                                     const bool emitsReadingsUpdate,
                                     const bool logToMetricReportsCollection,
@@ -74,7 +79,7 @@
                             ReportAction::logToMetricReportsCollection);
                     }
 
-                    return addReport(yield, reportName,
+                    return addReport(yield, reportId, reportId,
                                      utils::toReportingType(reportingType),
                                      reportActions, Milliseconds(interval),
                                      appendLimitDefault, reportUpdatesDefault,
@@ -86,16 +91,16 @@
 
             dbusIface.register_method(
                 "AddReportFutureVersion",
-                [this](boost::asio::yield_context& yield,
-                       const std::string& reportName,
-                       const std::string& reportingType,
-                       const std::string& reportUpdates,
-                       const uint64_t appendLimit,
-                       const std::vector<std::string>& reportActions,
-                       const uint64_t interval,
-                       ReadingParameters metricParams) {
+                [this](
+                    boost::asio::yield_context& yield,
+                    const std::string& reportId, const std::string& reportName,
+                    const std::string& reportingType,
+                    const std::string& reportUpdates,
+                    const uint64_t appendLimit,
+                    const std::vector<std::string>& reportActions,
+                    const uint64_t interval, ReadingParameters metricParams) {
                     constexpr auto enabledDefault = true;
-                    return addReport(yield, reportName,
+                    return addReport(yield, reportId, reportName,
                                      utils::toReportingType(reportingType),
                                      utils::transform(
                                          reportActions,
@@ -119,19 +124,20 @@
         reports.end());
 }
 
-void ReportManager::verifyReportNameLength(const std::string& reportName)
+void ReportManager::verifyReportIdLength(const std::string& reportId)
 {
-    if (reportName.length() > maxReportNameLength)
+    if (reportId.length() > maxReportIdLength)
     {
         throw sdbusplus::exception::SdBusError(
             static_cast<int>(std::errc::invalid_argument),
-            "Report name exceeds maximum length");
+            "Report id exceeds maximum length");
     }
 }
 
 void ReportManager::verifyAddReport(
-    const std::string& reportName, const ReportingType reportingType,
-    Milliseconds interval, const ReportUpdates reportUpdates,
+    const std::string& reportId, const std::string& reportName,
+    const ReportingType reportingType, Milliseconds interval,
+    const ReportUpdates reportUpdates,
     const std::vector<LabeledMetricParameters>& readingParams)
 {
     if (reportingType == ReportingType::onChange)
@@ -148,11 +154,12 @@
             "Reached maximal report count");
     }
 
-    verifyReportNameLength(reportName);
+    verifyReportIdLength(reportId);
+    utils::verifyIdCharacters(reportId);
 
     for (const auto& report : reports)
     {
-        if (report->getName() == reportName)
+        if (report->getId() == reportId)
         {
             throw sdbusplus::exception::SdBusError(
                 static_cast<int>(std::errc::file_exists), "Duplicate report");
@@ -193,8 +200,8 @@
 }
 
 interfaces::Report& ReportManager::addReport(
-    boost::asio::yield_context& yield, const std::string& reportName,
-    const ReportingType reportingType,
+    boost::asio::yield_context& yield, const std::string& reportId,
+    const std::string& reportName, const ReportingType reportingType,
     const std::vector<ReportAction>& reportActions, Milliseconds interval,
     const uint64_t appendLimit, const ReportUpdates reportUpdates,
     ReadingParameters metricParams, const bool enabled)
@@ -202,23 +209,36 @@
     auto labeledMetricParams =
         reportFactory->convertMetricParams(yield, metricParams);
 
-    return addReport(reportName, reportingType, reportActions, interval,
-                     appendLimit, reportUpdates, std::move(labeledMetricParams),
-                     enabled);
+    return addReport(reportId, reportName, reportingType, reportActions,
+                     interval, appendLimit, reportUpdates,
+                     std::move(labeledMetricParams), enabled);
 }
 
 interfaces::Report& ReportManager::addReport(
-    const std::string& reportName, const ReportingType reportingType,
+    const std::string& reportId, const std::string& reportName,
+    const ReportingType reportingType,
     const std::vector<ReportAction>& reportActions, Milliseconds interval,
     const uint64_t appendLimit, const ReportUpdates reportUpdates,
     std::vector<LabeledMetricParameters> labeledMetricParams,
     const bool enabled)
 {
-    verifyAddReport(reportName, reportingType, interval, reportUpdates,
+    std::string name = reportName;
+    if (name.empty())
+    {
+        name = "Report";
+    }
+
+    const auto existingReportIds = utils::transform(
+        reports, [](const auto& report) { return report->getId(); });
+
+    std::string id =
+        utils::generateId(reportId, name, existingReportIds, maxReportIdLength);
+
+    verifyAddReport(id, name, reportingType, interval, reportUpdates,
                     labeledMetricParams);
 
     reports.emplace_back(reportFactory->make(
-        reportName, reportingType, reportActions, interval, appendLimit,
+        id, name, reportingType, reportActions, interval, appendLimit,
         reportUpdates, *this, *reportStorage, labeledMetricParams, enabled));
     return *reports.back();
 }
@@ -233,12 +253,13 @@
         std::optional<nlohmann::json> data = reportStorage->load(path);
         try
         {
-            bool enabled = data->at("Enabled").get<bool>();
             size_t version = data->at("Version").get<size_t>();
             if (version != Report::reportVersion)
             {
                 throw std::logic_error("Invalid version");
             }
+            bool enabled = data->at("Enabled").get<bool>();
+            std::string& id = data->at("Id").get_ref<std::string&>();
             std::string& name = data->at("Name").get_ref<std::string&>();
 
             uint32_t reportingType = data->at("ReportingType").get<uint32_t>();
@@ -254,7 +275,7 @@
                 data->at("ReadingParameters")
                     .get<std::vector<LabeledMetricParameters>>();
 
-            addReport(name, utils::toReportingType(reportingType),
+            addReport(id, name, utils::toReportingType(reportingType),
                       reportActions, Milliseconds(interval), appendLimit,
                       utils::toReportUpdates(reportUpdates),
                       std::move(readingParameters), enabled);
@@ -272,11 +293,11 @@
     }
 }
 
-void ReportManager::updateReport(const std::string& name)
+void ReportManager::updateReport(const std::string& id)
 {
     for (auto& report : reports)
     {
-        if (report->getName() == name)
+        if (report->getId() == id)
         {
             report->updateReadings();
             return;