1852db67bSMatt Spinler #pragma once
2852db67bSMatt Spinler 
3852db67bSMatt Spinler #include "config.h"
4852db67bSMatt Spinler 
559521e87SMatt Spinler #include "types.hpp"
659521e87SMatt Spinler 
759521e87SMatt Spinler #include <nlohmann/json.hpp>
8c47ca585SMatt Spinler #include <xyz/openbmc_project/Association/Definitions/server.hpp>
9852db67bSMatt Spinler 
1059521e87SMatt Spinler #include <any>
1159521e87SMatt Spinler #include <filesystem>
1259521e87SMatt Spinler 
13852db67bSMatt Spinler namespace phosphor
14852db67bSMatt Spinler {
15852db67bSMatt Spinler namespace inventory
16852db67bSMatt Spinler {
17852db67bSMatt Spinler namespace manager
18852db67bSMatt Spinler {
19852db67bSMatt Spinler namespace associations
20852db67bSMatt Spinler {
21852db67bSMatt Spinler 
2299e66a03SMatt Spinler static constexpr auto forwardTypePos = 0;
2399e66a03SMatt Spinler static constexpr auto reverseTypePos = 1;
2499e66a03SMatt Spinler using Types = std::tuple<std::string, std::string>;
2599e66a03SMatt Spinler using Paths = std::vector<std::string>;
2699e66a03SMatt Spinler 
2799e66a03SMatt Spinler static constexpr auto typesPos = 0;
2899e66a03SMatt Spinler static constexpr auto pathsPos = 1;
2999e66a03SMatt Spinler using EndpointsEntry = std::vector<std::tuple<Types, Paths>>;
3099e66a03SMatt Spinler 
3199e66a03SMatt Spinler using AssociationMap = std::map<std::string, EndpointsEntry>;
3299e66a03SMatt Spinler 
33*563306f6SPatrick Williams using AssociationObject = sdbusplus::server::object_t<
34c47ca585SMatt Spinler     sdbusplus::xyz::openbmc_project::Association::server::Definitions>;
35c47ca585SMatt Spinler 
36c47ca585SMatt Spinler using AssociationIfaceMap =
37c47ca585SMatt Spinler     std::map<std::string, std::unique_ptr<AssociationObject>>;
38c47ca585SMatt Spinler 
39852db67bSMatt Spinler /**
40852db67bSMatt Spinler  * @class Manager
41852db67bSMatt Spinler  *
42852db67bSMatt Spinler  * @brief This class provides the ability to add org.openbmc.Associations
43852db67bSMatt Spinler  *        interfaces on inventory D-Bus objects, based on a definition in a
44852db67bSMatt Spinler  *        JSON file.
45852db67bSMatt Spinler  *
46852db67bSMatt Spinler  *        The purpose for this is to be able to associate other D-Bus paths
47852db67bSMatt Spinler  *        with the inventory items they relate to.
48852db67bSMatt Spinler  *
49852db67bSMatt Spinler  *        For example, a card temperature sensor D-Bus object can be associated
50852db67bSMatt Spinler  *        with the D-Bus object for that card's inventory entry so that some
51852db67bSMatt Spinler  *        code can tie them together.
52852db67bSMatt Spinler  */
53852db67bSMatt Spinler class Manager
54852db67bSMatt Spinler {
55852db67bSMatt Spinler   public:
5659521e87SMatt Spinler     struct Condition
5759521e87SMatt Spinler     {
5859521e87SMatt Spinler         std::string path;
5959521e87SMatt Spinler         std::string interface;
6059521e87SMatt Spinler         std::string property;
6159521e87SMatt Spinler         std::vector<InterfaceVariantType> values;
6259521e87SMatt Spinler         std::filesystem::path file;
6359521e87SMatt Spinler         InterfaceVariantType actualValue;
6459521e87SMatt Spinler     };
6559521e87SMatt Spinler 
66852db67bSMatt Spinler     Manager() = delete;
67852db67bSMatt Spinler     ~Manager() = default;
68852db67bSMatt Spinler     Manager(const Manager&) = delete;
69852db67bSMatt Spinler     Manager& operator=(const Manager&) = delete;
70852db67bSMatt Spinler     Manager(Manager&&) = delete;
71852db67bSMatt Spinler     Manager& operator=(Manager&&) = delete;
72852db67bSMatt Spinler 
73852db67bSMatt Spinler     /**
74852db67bSMatt Spinler      * @brief Constructor
75852db67bSMatt Spinler      *
76852db67bSMatt Spinler      * @param[in] bus - sdbusplus object
77852db67bSMatt Spinler      * @param[in] jsonPath - path to the JSON File that contains associations
78852db67bSMatt Spinler      */
79*563306f6SPatrick Williams     Manager(sdbusplus::bus_t& bus, const std::string& jsonPath);
80852db67bSMatt Spinler 
81852db67bSMatt Spinler     /**
82852db67bSMatt Spinler      * @brief Constructor
83852db67bSMatt Spinler      *
84852db67bSMatt Spinler      * @param[in] bus - sdbusplus object
85852db67bSMatt Spinler      */
Manager(sdbusplus::bus_t & bus)86*563306f6SPatrick Williams     explicit Manager(sdbusplus::bus_t& bus) :
87852db67bSMatt Spinler         Manager(bus, ASSOCIATIONS_FILE_PATH)
88a83db30eSBrad Bishop     {}
89852db67bSMatt Spinler 
90852db67bSMatt Spinler     /**
91852db67bSMatt Spinler      * @brief Creates any association D-Bus interfaces required based on
92852db67bSMatt Spinler      *        the JSON associations definition for the object path passed
93852db67bSMatt Spinler      *        in.
94852db67bSMatt Spinler      *
95852db67bSMatt Spinler      * Called after PIM creates a new inventory D-Bus interface on objectPath.
96852db67bSMatt Spinler      *
97852db67bSMatt Spinler      * @param[in] objectPath - the D-Bus object path to check for associations
98104ccba9SBrad Bishop      * @param[in] deferSignal - whether or not to send a Properties or
99104ccba9SBrad Bishop      *                          ObjectManager signal
100852db67bSMatt Spinler      */
101104ccba9SBrad Bishop     void createAssociations(const std::string& objectPath, bool deferSignal);
102852db67bSMatt Spinler 
10399e66a03SMatt Spinler     /**
10499e66a03SMatt Spinler      * @brief Returned the association configuration.
10599e66a03SMatt Spinler      *        Used for testing.
10699e66a03SMatt Spinler      *
10799e66a03SMatt Spinler      * @return AssociationMap& - the association config
10899e66a03SMatt Spinler      */
getAssociationsConfig()10999e66a03SMatt Spinler     const AssociationMap& getAssociationsConfig()
11099e66a03SMatt Spinler     {
11199e66a03SMatt Spinler         return _associations;
11299e66a03SMatt Spinler     }
11399e66a03SMatt Spinler 
11459521e87SMatt Spinler     /**
11559521e87SMatt Spinler      * @brief Returns the list of conditions
11659521e87SMatt Spinler      *
11759521e87SMatt Spinler      * @return vector<Condition>& - The conditions
11859521e87SMatt Spinler      */
getConditions()11959521e87SMatt Spinler     std::vector<Condition>& getConditions()
12059521e87SMatt Spinler     {
12159521e87SMatt Spinler         return _conditions;
12259521e87SMatt Spinler     }
12359521e87SMatt Spinler 
12459521e87SMatt Spinler     /**
12559521e87SMatt Spinler      * @brief Says if there are conditions that need to be met
12659521e87SMatt Spinler      *        before an associations file is valid.
12759521e87SMatt Spinler      *
12859521e87SMatt Spinler      * @return bool - If there are pending conditions
12959521e87SMatt Spinler      */
pendingCondition() const13059521e87SMatt Spinler     bool pendingCondition() const
13159521e87SMatt Spinler     {
13259521e87SMatt Spinler         return !_conditions.empty();
13359521e87SMatt Spinler     }
13459521e87SMatt Spinler 
13559521e87SMatt Spinler     /**
13659521e87SMatt Spinler      * @brief Checks if a pending condition is satisfied based on the
13759521e87SMatt Spinler      *        path, interface, and property value of the object passed
13859521e87SMatt Spinler      *        in.
13959521e87SMatt Spinler      *
14059521e87SMatt Spinler      *        If it is valid, it will load the associations pointed to
14159521e87SMatt Spinler      *        by that condition and erase the _conditions vector as
14259521e87SMatt Spinler      *        there are no longer any pending conditions.
14359521e87SMatt Spinler      *
14459521e87SMatt Spinler      * @param[in] objectPath - The D-Bus path of the object to check
14559521e87SMatt Spinler      * @param[in] in object - The interface and properties of the object
14659521e87SMatt Spinler      *
14759521e87SMatt Spinler      * @return bool - If the object matched a condition
14859521e87SMatt Spinler      */
14959521e87SMatt Spinler     bool conditionMatch(const sdbusplus::message::object_path& objectPath,
15059521e87SMatt Spinler                         const Object& object);
15159521e87SMatt Spinler 
15259521e87SMatt Spinler     /**
15359521e87SMatt Spinler      * @brief Checks if a pending condition is satisfied based on if the
15459521e87SMatt Spinler      *        actualValue field in the condition matches one of the values
15559521e87SMatt Spinler      *        in the values field.
15659521e87SMatt Spinler      *
15759521e87SMatt Spinler      *        The actualValue field was previously set by code based on the
15859521e87SMatt Spinler      *        real property value of the specified interface on the specified
15959521e87SMatt Spinler      *        path.
16059521e87SMatt Spinler      *
16159521e87SMatt Spinler      *        If it is valid, it will load the associations pointed to
16259521e87SMatt Spinler      *        by that condition and erase the _conditions vector as
16359521e87SMatt Spinler      *        there are no longer any pending conditions.
16459521e87SMatt Spinler      *
16559521e87SMatt Spinler      * @return bool - If a condition was met
16659521e87SMatt Spinler      */
16759521e87SMatt Spinler     bool conditionMatch();
16859521e87SMatt Spinler 
169852db67bSMatt Spinler   private:
170852db67bSMatt Spinler     /**
17159521e87SMatt Spinler      *  @brief Loads the association JSON into the _associations data
17259521e87SMatt Spinler      *         structure.
17359521e87SMatt Spinler      *
17459521e87SMatt Spinler      *  @param[in] json - The associations JSON
17599e66a03SMatt Spinler      */
17659521e87SMatt Spinler     void load(const nlohmann::json& json);
17799e66a03SMatt Spinler 
17899e66a03SMatt Spinler     /**
179c47ca585SMatt Spinler      * @brief Creates an instance of an org.openbmc.Associations
180c47ca585SMatt Spinler      *        interface using the passed in properties.
181c47ca585SMatt Spinler      *
182c47ca585SMatt Spinler      * @param[in] forwardPath - the path of the forward association
183c47ca585SMatt Spinler      * @param[in] forwardType - the type of the forward association
184c47ca585SMatt Spinler      * @param[in] reversePath - the path of the reverse association
185c47ca585SMatt Spinler      * @param[in] reverseType - the type of the reverse association
186104ccba9SBrad Bishop      * @param[in] deferSignal - whether or not to send a Properties or
187104ccba9SBrad Bishop      *                          ObjectManager signal
188c47ca585SMatt Spinler      */
189c47ca585SMatt Spinler     void createAssociation(const std::string& forwardPath,
190c47ca585SMatt Spinler                            const std::string& forwardType,
191c47ca585SMatt Spinler                            const std::string& reversePath,
192104ccba9SBrad Bishop                            const std::string& reverseType, bool deferSignal);
193c47ca585SMatt Spinler 
194c47ca585SMatt Spinler     /**
19559521e87SMatt Spinler      * @brief Looks for all JSON files in the associations directory that
19659521e87SMatt Spinler      *        contain a valid association condition, and loads the
19759521e87SMatt Spinler      *        conditions into the _conditions vector.
19859521e87SMatt Spinler      */
19959521e87SMatt Spinler     bool loadConditions();
20059521e87SMatt Spinler 
20159521e87SMatt Spinler     /**
20299e66a03SMatt Spinler      * @brief The map of association data that is loaded from its
20399e66a03SMatt Spinler      *        JSON definition.  Association D-Bus objects will be
20499e66a03SMatt Spinler      *        created from this data.
20599e66a03SMatt Spinler      */
20699e66a03SMatt Spinler     AssociationMap _associations;
20799e66a03SMatt Spinler 
20899e66a03SMatt Spinler     /**
209c47ca585SMatt Spinler      * @brief The map of org.openbmc_project.Associations D-Bus
210c47ca585SMatt Spinler      *        interfaces objects based on their object path.
211c47ca585SMatt Spinler      */
212c47ca585SMatt Spinler     AssociationIfaceMap _associationIfaces;
213c47ca585SMatt Spinler 
214c47ca585SMatt Spinler     /**
215852db67bSMatt Spinler      * @brief The sdbusplus bus object.
216852db67bSMatt Spinler      */
217*563306f6SPatrick Williams     sdbusplus::bus_t& _bus;
218852db67bSMatt Spinler 
219852db67bSMatt Spinler     /**
220852db67bSMatt Spinler      * @brief The path to the associations JSON File.
221852db67bSMatt Spinler      */
22259521e87SMatt Spinler     const std::filesystem::path _jsonFile;
223c47ca585SMatt Spinler 
224c47ca585SMatt Spinler     /**
225c47ca585SMatt Spinler      * A list of the inventory association paths that have already been handled.
226c47ca585SMatt Spinler      */
227c47ca585SMatt Spinler     std::vector<std::string> _handled;
22859521e87SMatt Spinler 
22959521e87SMatt Spinler     /**
23059521e87SMatt Spinler      * @brief Conditions that specify when an associations file is valid.
23159521e87SMatt Spinler      */
23259521e87SMatt Spinler     std::vector<Condition> _conditions;
233852db67bSMatt Spinler };
234852db67bSMatt Spinler 
235852db67bSMatt Spinler } // namespace associations
236852db67bSMatt Spinler } // namespace manager
237852db67bSMatt Spinler } // namespace inventory
238852db67bSMatt Spinler } // namespace phosphor
239