blob: 946bd74840dd5bc616049bfa81e74b849ba76cdc [file] [log] [blame]
Matt Spinler852db672019-03-06 13:46:14 -06001#include "association_manager.hpp"
2
Matt Spinler99e66a02019-03-06 14:11:22 -06003#include <nlohmann/json.hpp>
4#include <phosphor-logging/log.hpp>
5
Brad Bishopa83db302020-12-06 14:51:23 -05006#include <filesystem>
7#include <fstream>
8
Matt Spinler852db672019-03-06 13:46:14 -06009namespace phosphor
10{
11namespace inventory
12{
13namespace manager
14{
15namespace associations
16{
Matt Spinler99e66a02019-03-06 14:11:22 -060017using namespace phosphor::logging;
18using sdbusplus::exception::SdBusError;
Matt Spinler852db672019-03-06 13:46:14 -060019
20Manager::Manager(sdbusplus::bus::bus& bus, const std::string& jsonPath) :
21 _bus(bus), _jsonFile(jsonPath)
22{
Matt Spinler99e66a02019-03-06 14:11:22 -060023 load();
24}
25
26/**
27 * @brief Throws an exception if 'num' is zero. Used for JSON
28 * sanity checking.
29 *
30 * @param[in] num - the number to check
31 */
32void throwIfZero(int num)
33{
34 if (!num)
35 {
36 throw std::invalid_argument("Invalid empty field in JSON");
37 }
38}
39
40void Manager::load()
41{
42 // Load the contents of _jsonFile into _associations and throw
43 // an exception on any problem.
44
45 std::ifstream file{_jsonFile};
46
47 auto json = nlohmann::json::parse(file, nullptr, true);
48
49 const std::string root{INVENTORY_ROOT};
50
51 for (const auto& jsonAssoc : json)
52 {
53 // Only add the slash if necessary
54 std::string path = jsonAssoc.at("path");
55 throwIfZero(path.size());
56 if (path.front() != '/')
57 {
58 path = root + "/" + path;
59 }
60 else
61 {
62 path = root + path;
63 }
64
65 auto& assocEndpoints = _associations[path];
66
67 for (const auto& endpoint : jsonAssoc.at("endpoints"))
68 {
69 std::string ftype = endpoint.at("types").at("fType");
70 std::string rtype = endpoint.at("types").at("rType");
71 throwIfZero(ftype.size());
72 throwIfZero(rtype.size());
73 Types types{std::move(ftype), std::move(rtype)};
74
75 Paths paths = endpoint.at("paths");
76 throwIfZero(paths.size());
77 assocEndpoints.emplace_back(std::move(types), std::move(paths));
78 }
79 }
Matt Spinler852db672019-03-06 13:46:14 -060080}
81
82void Manager::createAssociations(const std::string& objectPath)
83{
Matt Spinlerc47ca582019-03-06 14:37:42 -060084 auto endpoints = _associations.find(objectPath);
85 if (endpoints == _associations.end())
86 {
87 return;
88 }
89
90 if (std::find(_handled.begin(), _handled.end(), objectPath) !=
91 _handled.end())
92 {
93 return;
94 }
95
96 _handled.push_back(objectPath);
97
98 for (const auto& endpoint : endpoints->second)
99 {
100 const auto& types = std::get<typesPos>(endpoint);
101 const auto& paths = std::get<pathsPos>(endpoint);
102
103 for (const auto& endpointPath : paths)
104 {
105 const auto& forwardType = std::get<forwardTypePos>(types);
106 const auto& reverseType = std::get<reverseTypePos>(types);
107
108 createAssociation(objectPath, forwardType, endpointPath,
109 reverseType);
110 }
111 }
112}
113
114void Manager::createAssociation(const std::string& forwardPath,
115 const std::string& forwardType,
116 const std::string& reversePath,
117 const std::string& reverseType)
118{
119 auto object = _associationIfaces.find(forwardPath);
120 if (object == _associationIfaces.end())
121 {
122 auto a = std::make_unique<AssociationObject>(_bus, forwardPath.c_str(),
123 true);
124
125 using AssociationProperty =
126 std::vector<std::tuple<std::string, std::string, std::string>>;
127 AssociationProperty prop;
128
129 prop.emplace_back(forwardType, reverseType, reversePath);
130 a->associations(std::move(prop));
131 a->emit_object_added();
132 _associationIfaces.emplace(forwardPath, std::move(a));
133 }
134 else
135 {
136 // Interface exists, just update the property
137 auto prop = object->second->associations();
138 prop.emplace_back(forwardType, reverseType, reversePath);
139 object->second->associations(std::move(prop));
140 }
Matt Spinler852db672019-03-06 13:46:14 -0600141}
142} // namespace associations
143} // namespace manager
144} // namespace inventory
145} // namespace phosphor