1*3cc348ceSShawn McCarney /**
2*3cc348ceSShawn McCarney  * Copyright © 2024 IBM Corporation
3*3cc348ceSShawn McCarney  *
4*3cc348ceSShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
5*3cc348ceSShawn McCarney  * you may not use this file except in compliance with the License.
6*3cc348ceSShawn McCarney  * You may obtain a copy of the License at
7*3cc348ceSShawn McCarney  *
8*3cc348ceSShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
9*3cc348ceSShawn McCarney  *
10*3cc348ceSShawn McCarney  * Unless required by applicable law or agreed to in writing, software
11*3cc348ceSShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
12*3cc348ceSShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*3cc348ceSShawn McCarney  * See the License for the specific language governing permissions and
14*3cc348ceSShawn McCarney  * limitations under the License.
15*3cc348ceSShawn McCarney  */
16*3cc348ceSShawn McCarney 
17*3cc348ceSShawn McCarney #include "compatible_system_types_finder.hpp"
18*3cc348ceSShawn McCarney 
19*3cc348ceSShawn McCarney #include <phosphor-logging/lg2.hpp>
20*3cc348ceSShawn McCarney 
21*3cc348ceSShawn McCarney #include <algorithm>
22*3cc348ceSShawn McCarney #include <exception>
23*3cc348ceSShawn McCarney #include <format>
24*3cc348ceSShawn McCarney #include <ranges>
25*3cc348ceSShawn McCarney #include <regex>
26*3cc348ceSShawn McCarney #include <stdexcept>
27*3cc348ceSShawn McCarney #include <utility>
28*3cc348ceSShawn McCarney #include <variant>
29*3cc348ceSShawn McCarney 
30*3cc348ceSShawn McCarney namespace phosphor::power::util
31*3cc348ceSShawn McCarney {
32*3cc348ceSShawn McCarney 
33*3cc348ceSShawn McCarney const std::string compatibleInterfaceService =
34*3cc348ceSShawn McCarney     "xyz.openbmc_project.EntityManager";
35*3cc348ceSShawn McCarney 
36*3cc348ceSShawn McCarney const std::string compatibleInterface =
37*3cc348ceSShawn McCarney     "xyz.openbmc_project.Inventory.Decorator.Compatible";
38*3cc348ceSShawn McCarney 
39*3cc348ceSShawn McCarney const std::string namesProperty = "Names";
40*3cc348ceSShawn McCarney 
41*3cc348ceSShawn McCarney CompatibleSystemTypesFinder::CompatibleSystemTypesFinder(sdbusplus::bus_t& bus,
42*3cc348ceSShawn McCarney                                                          Callback callback) :
43*3cc348ceSShawn McCarney     callback{std::move(callback)},
44*3cc348ceSShawn McCarney     interfaceFinder{
45*3cc348ceSShawn McCarney         bus, compatibleInterfaceService,
46*3cc348ceSShawn McCarney         std::vector<std::string>{compatibleInterface},
47*3cc348ceSShawn McCarney         std::bind_front(&CompatibleSystemTypesFinder::interfaceFoundCallback,
48*3cc348ceSShawn McCarney                         this)}
49*3cc348ceSShawn McCarney {}
50*3cc348ceSShawn McCarney 
51*3cc348ceSShawn McCarney void CompatibleSystemTypesFinder::interfaceFoundCallback(
52*3cc348ceSShawn McCarney     [[maybe_unused]] const std::string& path,
53*3cc348ceSShawn McCarney     [[maybe_unused]] const std::string& interface,
54*3cc348ceSShawn McCarney     const DbusPropertyMap& properties)
55*3cc348ceSShawn McCarney {
56*3cc348ceSShawn McCarney     try
57*3cc348ceSShawn McCarney     {
58*3cc348ceSShawn McCarney         // Get the property containing the list of compatible names
59*3cc348ceSShawn McCarney         auto it = properties.find(namesProperty);
60*3cc348ceSShawn McCarney         if (it == properties.end())
61*3cc348ceSShawn McCarney         {
62*3cc348ceSShawn McCarney             throw std::runtime_error{
63*3cc348ceSShawn McCarney                 std::format("{} property not found", namesProperty)};
64*3cc348ceSShawn McCarney         }
65*3cc348ceSShawn McCarney         auto names = std::get<std::vector<std::string>>(it->second);
66*3cc348ceSShawn McCarney         if (!names.empty())
67*3cc348ceSShawn McCarney         {
68*3cc348ceSShawn McCarney             // If all the compatible names are system or chassis types
69*3cc348ceSShawn McCarney             std::regex pattern{"\\.(system|chassis)\\.", std::regex::icase};
70*3cc348ceSShawn McCarney             if (std::ranges::all_of(names, [&pattern](auto&& name) {
71*3cc348ceSShawn McCarney                 return std::regex_search(name, pattern);
72*3cc348ceSShawn McCarney             }))
73*3cc348ceSShawn McCarney             {
74*3cc348ceSShawn McCarney                 // Call callback with compatible system type names
75*3cc348ceSShawn McCarney                 callback(names);
76*3cc348ceSShawn McCarney             }
77*3cc348ceSShawn McCarney         }
78*3cc348ceSShawn McCarney     }
79*3cc348ceSShawn McCarney     catch (const std::exception& e)
80*3cc348ceSShawn McCarney     {
81*3cc348ceSShawn McCarney         lg2::error(
82*3cc348ceSShawn McCarney             "Unable to obtain properties of Compatible interface: {ERROR}",
83*3cc348ceSShawn McCarney             "ERROR", e);
84*3cc348ceSShawn McCarney     }
85*3cc348ceSShawn McCarney }
86*3cc348ceSShawn McCarney 
87*3cc348ceSShawn McCarney } // namespace phosphor::power::util
88