1111#include < string>
1212#include < vector>
1313
14- using JsonVariantType =
15- std::variant<std::vector<std::string>, std::vector<double >, std::string,
16- int64_t ,uint64_t ,double ,int32_t ,uint32_t ,int16_t ,
17- uint16_t ,uint8_t ,bool >;
18-
1914namespace dbus_interface
2015{
2116
@@ -238,6 +233,124 @@ void EMDBusInterface::populateInterfaceFromJson(
238233tryIfaceInitialize (iface);
239234}
240235
236+ void EMDBusInterface::addObject (
237+ const std::flat_map<std::string, JsonVariantType, std::less<>>& data,
238+ nlohmann::json& systemConfiguration,const std::string& jsonPointerPath,
239+ const std::string& path,const std::string& board)
240+ {
241+ nlohmann::json::json_pointerptr (jsonPointerPath);
242+ nlohmann::json& base = systemConfiguration[ptr];
243+ auto findExposes = base.find (" Exposes" );
244+
245+ if (findExposes == base.end ())
246+ {
247+ throw std::invalid_argument (" Entity must have children." );
248+ }
249+
250+ // this will throw invalid-argument to sdbusplus if invalid json
251+ nlohmann::json newData{};
252+ for (const auto & item : data)
253+ {
254+ nlohmann::json& newJson = newData[item.first ];
255+ std::visit (
256+ [&newJson](auto && val) {
257+ newJson = std::forward<decltype (val)>(val);
258+ },
259+ item.second );
260+ }
261+
262+ auto findName = newData.find (" Name" );
263+ auto findType = newData.find (" Type" );
264+ if (findName == newData.end () || findType == newData.end ())
265+ {
266+ throw std::invalid_argument (" AddObject missing Name or Type" );
267+ }
268+ const std::string* type = findType->get_ptr <const std::string*>();
269+ const std::string* name = findName->get_ptr <const std::string*>();
270+ if (type ==nullptr || name ==nullptr )
271+ {
272+ throw std::invalid_argument (" Type and Name must be a string." );
273+ }
274+
275+ bool foundNull =false ;
276+ size_t lastIndex =0 ;
277+ // we add in the "exposes"
278+ for (const auto & expose : *findExposes)
279+ {
280+ if (expose.is_null ())
281+ {
282+ foundNull =true ;
283+ continue ;
284+ }
285+
286+ if (expose[" Name" ] == *name && expose[" Type" ] == *type)
287+ {
288+ throw std::invalid_argument (" Field already in JSON, not adding" );
289+ }
290+
291+ if (foundNull)
292+ {
293+ continue ;
294+ }
295+
296+ lastIndex++;
297+ }
298+
299+ if constexpr (ENABLE_RUNTIME_VALIDATE_JSON)
300+ {
301+ const std::filesystem::path schemaPath =
302+ std::filesystem::path (schemaDirectory) /" exposes_record.json" ;
303+
304+ std::ifstream schemaFile{schemaPath};
305+
306+ if (!schemaFile.good ())
307+ {
308+ throw std::invalid_argument (
309+ " No schema avaliable, cannot validate." );
310+ }
311+ nlohmann::json schema =
312+ nlohmann::json::parse (schemaFile,nullptr ,false ,true );
313+ if (schema.is_discarded ())
314+ {
315+ lg2::error (" Schema not legal: {TYPE}.json" ," TYPE" , *type);
316+ throw DBusInternalError ();
317+ }
318+
319+ if (!validateJson (schema, newData))
320+ {
321+ throw std::invalid_argument (" Data does not match schema" );
322+ }
323+ }
324+
325+ if (foundNull)
326+ {
327+ findExposes->at (lastIndex) = newData;
328+ }
329+ else
330+ {
331+ findExposes->push_back (newData);
332+ }
333+ if (!writeJsonFiles (systemConfiguration))
334+ {
335+ lg2::error (" Error writing json files" );
336+ }
337+ std::string dbusName = *name;
338+
339+ std::regex_replace (dbusName.begin (), dbusName.begin (), dbusName.end (),
340+ illegalDbusMemberRegex," _" );
341+
342+ std::shared_ptr<sdbusplus::asio::dbus_interface> interface =
343+ createInterface (path +" /" + dbusName,
344+ " xyz.openbmc_project.Configuration." + *type, board,
345+ true );
346+ // permission is read-write, as since we just created it, must be
347+ // runtime modifiable
348+ populateInterfaceFromJson (
349+ systemConfiguration,
350+ jsonPointerPath +" /Exposes/" +std::to_string (lastIndex), interface,
351+ newData, sdbusplus::asio::PropertyPermission::readWrite);
352+ }
353+
241354void EMDBusInterface::createAddObjectMethod (
242355const std::string& jsonPointerPath,const std::string& path,
243356 nlohmann::json& systemConfiguration,const std::string& board)
@@ -248,123 +361,10 @@ void EMDBusInterface::createAddObjectMethod(
248361 iface->register_method (
249362" AddObject" ,
250363 [&systemConfiguration, jsonPointerPath{std::string (jsonPointerPath)},
251- path{std::string (path)}, board,
364+ path{std::string (path)}, board{ std::string (board)} ,
252365this ](const std::flat_map<std::string, JsonVariantType, std::less<>>&
253366 data) {
254- nlohmann::json::json_pointerptr (jsonPointerPath);
255- nlohmann::json& base = systemConfiguration[ptr];
256- auto findExposes = base.find (" Exposes" );
257-
258- if (findExposes == base.end ())
259- {
260- throw std::invalid_argument (" Entity must have children." );
261- }
262-
263- // this will throw invalid-argument to sdbusplus if invalid json
264- nlohmann::json newData{};
265- for (const auto & item : data)
266- {
267- nlohmann::json& newJson = newData[item.first ];
268- std::visit (
269- [&newJson](auto && val) {
270- newJson = std::forward<decltype (val)>(val);
271- },
272- item.second );
273- }
274-
275- auto findName = newData.find (" Name" );
276- auto findType = newData.find (" Type" );
277- if (findName == newData.end () || findType == newData.end ())
278- {
279- throw std::invalid_argument (" AddObject missing Name or Type" );
280- }
281- const std::string* type = findType->get_ptr <const std::string*>();
282- const std::string* name = findName->get_ptr <const std::string*>();
283- if (type ==nullptr || name ==nullptr )
284- {
285- throw std::invalid_argument (" Type and Name must be a string." );
286- }
287-
288- bool foundNull =false ;
289- size_t lastIndex =0 ;
290- // we add in the "exposes"
291- for (const auto & expose : *findExposes)
292- {
293- if (expose.is_null ())
294- {
295- foundNull =true ;
296- continue ;
297- }
298-
299- if (expose[" Name" ] == *name && expose[" Type" ] == *type)
300- {
301- throw std::invalid_argument (
302- " Field already in JSON, not adding" );
303- }
304-
305- if (foundNull)
306- {
307- continue ;
308- }
309-
310- lastIndex++;
311- }
312-
313- if constexpr (ENABLE_RUNTIME_VALIDATE_JSON)
314- {
315- const std::filesystem::path schemaPath =
316- std::filesystem::path (schemaDirectory) /
317- " exposes_record.json" ;
318-
319- std::ifstream schemaFile{schemaPath};
320-
321- if (!schemaFile.good ())
322- {
323- throw std::invalid_argument (
324- " No schema avaliable, cannot validate." );
325- }
326- nlohmann::json schema =
327- nlohmann::json::parse (schemaFile,nullptr ,false ,true );
328- if (schema.is_discarded ())
329- {
330- lg2::error (" Schema not legal: {TYPE}.json" ," TYPE" , *type);
331- throw DBusInternalError ();
332- }
333-
334- if (!validateJson (schema, newData))
335- {
336- throw std::invalid_argument (" Data does not match schema" );
337- }
338- }
339-
340- if (foundNull)
341- {
342- findExposes->at (lastIndex) = newData;
343- }
344- else
345- {
346- findExposes->push_back (newData);
347- }
348- if (!writeJsonFiles (systemConfiguration))
349- {
350- lg2::error (" Error writing json files" );
351- }
352- std::string dbusName = *name;
353-
354- std::regex_replace (dbusName.begin (), dbusName.begin (),
355- dbusName.end (), illegalDbusMemberRegex," _" );
356-
357- std::shared_ptr<sdbusplus::asio::dbus_interface> interface =
358- createInterface (path +" /" + dbusName,
359- " xyz.openbmc_project.Configuration." + *type,
360- board,true );
361- // permission is read-write, as since we just created it, must be
362- // runtime modifiable
363- populateInterfaceFromJson (
364- systemConfiguration,
365- jsonPointerPath +" /Exposes/" +std::to_string (lastIndex),
366- interface, newData,
367- sdbusplus::asio::PropertyPermission::readWrite);
367+ addObject (data, systemConfiguration, jsonPointerPath, path, board);
368368 });
369369tryIfaceInitialize (iface);
370370}