blob: b94e308119f47beea3d1fdfb7e31306935159539 [file] [log] [blame]
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001/**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "config_file_parser.hpp"
18
19#include "config_file_parser_error.hpp"
Bob Kingf617f892020-03-30 19:03:35 +080020#include "i2c_interface.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050021#include "pmbus_utils.hpp"
22
23#include <exception>
24#include <fstream>
25#include <optional>
26#include <utility>
27
28using json = nlohmann::json;
29
30namespace phosphor::power::regulators::config_file_parser
31{
32
33std::tuple<std::vector<std::unique_ptr<Rule>>,
34 std::vector<std::unique_ptr<Chassis>>>
35 parse(const std::filesystem::path& pathName)
36{
37 try
38 {
39 // Use standard JSON parser to create tree of JSON elements
40 std::ifstream file{pathName};
41 json rootElement = json::parse(file);
42
43 // Parse tree of JSON elements and return corresponding C++ objects
44 return internal::parseRoot(rootElement);
45 }
46 catch (const std::exception& e)
47 {
48 throw ConfigFileParserError{pathName, e.what()};
49 }
50}
51
52namespace internal
53{
54
55std::unique_ptr<Action> parseAction(const json& element)
56{
57 verifyIsObject(element);
58 unsigned int propertyCount{0};
59
60 // Optional comments property; value not stored
61 if (element.contains("comments"))
62 {
63 ++propertyCount;
64 }
65
66 // Required action type property; there must be exactly one specified
67 std::unique_ptr<Action> action{};
68 if (element.contains("and"))
69 {
Bob King3a787542020-04-14 13:45:01 +080070 action = parseAnd(element["and"]);
71 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050072 }
73 else if (element.contains("compare_presence"))
74 {
75 // TODO: Not implemented yet
76 // action = parseComparePresence(element["compare_presence"]);
77 // ++propertyCount;
78 }
79 else if (element.contains("compare_vpd"))
80 {
81 // TODO: Not implemented yet
82 // action = parseCompareVPD(element["compare_vpd"]);
83 // ++propertyCount;
84 }
85 else if (element.contains("i2c_compare_bit"))
86 {
Bob Kingf09bfe02020-04-13 17:21:15 +080087 action = parseI2CCompareBit(element["i2c_compare_bit"]);
88 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050089 }
90 else if (element.contains("i2c_compare_byte"))
91 {
Bob Kingf09bfe02020-04-13 17:21:15 +080092 action = parseI2CCompareByte(element["i2c_compare_byte"]);
93 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050094 }
95 else if (element.contains("i2c_compare_bytes"))
96 {
Bob Kingf09bfe02020-04-13 17:21:15 +080097 action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
98 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050099 }
100 else if (element.contains("i2c_write_bit"))
101 {
Bob Kingf617f892020-03-30 19:03:35 +0800102 action = parseI2CWriteBit(element["i2c_write_bit"]);
103 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500104 }
105 else if (element.contains("i2c_write_byte"))
106 {
Bob King87ff9d72020-03-31 14:02:55 +0800107 action = parseI2CWriteByte(element["i2c_write_byte"]);
108 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500109 }
110 else if (element.contains("i2c_write_bytes"))
111 {
Bob Kingbafcb862020-03-31 16:39:00 +0800112 action = parseI2CWriteBytes(element["i2c_write_bytes"]);
113 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500114 }
115 else if (element.contains("if"))
116 {
Bob King93a89d72020-04-15 15:11:11 +0800117 action = parseIf(element["if"]);
118 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500119 }
120 else if (element.contains("not"))
121 {
Bob Kingf1b58dc2020-04-14 14:53:10 +0800122 action = parseNot(element["not"]);
123 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500124 }
125 else if (element.contains("or"))
126 {
Bob King0b51a9b2020-04-15 13:24:18 +0800127 action = parseOr(element["or"]);
128 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500129 }
130 else if (element.contains("pmbus_read_sensor"))
131 {
132 // TODO: Not implemented yet
133 // action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
134 // ++propertyCount;
135 }
136 else if (element.contains("pmbus_write_vout_command"))
137 {
138 action =
139 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
140 ++propertyCount;
141 }
142 else if (element.contains("run_rule"))
143 {
Bob King315b0b62020-04-03 21:47:58 +0800144 action = parseRunRule(element["run_rule"]);
145 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500146 }
147 else if (element.contains("set_device"))
148 {
Bob King18a68502020-04-17 14:19:56 +0800149 action = parseSetDevice(element["set_device"]);
150 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500151 }
152 else
153 {
154 throw std::invalid_argument{"Required action type property missing"};
155 }
156
157 // Verify no invalid properties exist
158 verifyPropertyCount(element, propertyCount);
159
160 return action;
161}
162
163std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
164{
165 verifyIsArray(element);
166 std::vector<std::unique_ptr<Action>> actions;
167 for (auto& actionElement : element)
168 {
169 actions.emplace_back(parseAction(actionElement));
170 }
171 return actions;
172}
173
Bob King3a787542020-04-14 13:45:01 +0800174std::unique_ptr<AndAction> parseAnd(const json& element)
175{
176 verifyIsArray(element);
177
178 // Verify if array size less than 2
179 if (element.size() < 2)
180 {
181 throw std::invalid_argument{"Array must contain two or more actions"};
182 }
183 // Array of two or more actions
184 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
185
186 return std::make_unique<AndAction>(std::move(actions));
187}
188
Bob King0e701132020-04-03 21:50:31 +0800189std::unique_ptr<Chassis> parseChassis(const json& element)
190{
191 verifyIsObject(element);
192 unsigned int propertyCount{0};
193
194 // Optional comments property; value not stored
195 if (element.contains("comments"))
196 {
197 ++propertyCount;
198 }
199
200 // Required number property
201 const json& numberElement = getRequiredProperty(element, "number");
202 unsigned int number = parseUnsignedInteger(numberElement);
203 if (number < 1)
204 {
205 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
206 }
207 ++propertyCount;
208
209 // Optional devices property
210 std::vector<std::unique_ptr<Device>> devices{};
211 auto devicesIt = element.find("devices");
212 if (devicesIt != element.end())
213 {
214 devices = parseDeviceArray(*devicesIt);
215 ++propertyCount;
216 }
217
218 // Verify no invalid properties exist
219 verifyPropertyCount(element, propertyCount);
220
221 return std::make_unique<Chassis>(number, std::move(devices));
222}
223
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500224std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
225{
226 verifyIsArray(element);
227 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800228 for (auto& chassisElement : element)
229 {
230 chassis.emplace_back(parseChassis(chassisElement));
231 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500232 return chassis;
233}
234
Bob King33e7eaa2020-04-01 18:09:34 +0800235std::unique_ptr<Configuration> parseConfiguration(const json& element)
236{
237 verifyIsObject(element);
238 unsigned int propertyCount{0};
239
240 // Optional comments property; value not stored
241 if (element.contains("comments"))
242 {
243 ++propertyCount;
244 }
245
246 // Optional volts property
247 std::optional<double> volts{};
248 auto voltsIt = element.find("volts");
249 if (voltsIt != element.end())
250 {
251 volts = parseDouble(*voltsIt);
252 ++propertyCount;
253 }
254
255 // Required rule_id or actions property
256 std::vector<std::unique_ptr<Action>> actions{};
257 actions = parseRuleIDOrActionsProperty(element);
258 ++propertyCount;
259
260 // Verify no invalid properties exist
261 verifyPropertyCount(element, propertyCount);
262
263 return std::make_unique<Configuration>(volts, std::move(actions));
264}
265
Bob King9c36c5f2020-04-06 11:34:09 +0800266std::unique_ptr<Device> parseDevice(const json& element)
267{
268 verifyIsObject(element);
269 unsigned int propertyCount{0};
270
271 // Optional comments property; value not stored
272 if (element.contains("comments"))
273 {
274 ++propertyCount;
275 }
276
277 // Required id property
278 const json& idElement = getRequiredProperty(element, "id");
279 std::string id = parseString(idElement);
280 ++propertyCount;
281
282 // Required is_regulator property
283 const json& isRegulatorElement =
284 getRequiredProperty(element, "is_regulator");
285 bool isRegulator = parseBoolean(isRegulatorElement);
286 ++propertyCount;
287
288 // Required fru property
289 const json& fruElement = getRequiredProperty(element, "fru");
290 std::string fru = parseString(fruElement);
291 ++propertyCount;
292
293 // Required i2c_interface property
294 const json& i2cInterfaceElement =
295 getRequiredProperty(element, "i2c_interface");
296 std::unique_ptr<i2c::I2CInterface> i2cInterface =
297 parseI2CInterface(i2cInterfaceElement);
298 ++propertyCount;
299
300 // Optional presence_detection property
Bob King9c36c5f2020-04-06 11:34:09 +0800301 std::unique_ptr<PresenceDetection> presenceDetection{};
Bob King2aafb1c2020-04-16 15:24:32 +0800302 auto presenceDetectionIt = element.find("presence_detection");
303 if (presenceDetectionIt != element.end())
304 {
305 presenceDetection = parsePresenceDetection(*presenceDetectionIt);
306 ++propertyCount;
307 }
Bob King9c36c5f2020-04-06 11:34:09 +0800308
309 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800310 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800311 auto configurationIt = element.find("configuration");
312 if (configurationIt != element.end())
313 {
314 configuration = parseConfiguration(*configurationIt);
315 ++propertyCount;
316 }
Bob King9c36c5f2020-04-06 11:34:09 +0800317
318 // Optional rails property
319 std::vector<std::unique_ptr<Rail>> rails{};
320 auto railsIt = element.find("rails");
321 if (railsIt != element.end())
322 {
323 if (!isRegulator)
324 {
325 throw std::invalid_argument{
326 "Invalid rails property when is_regulator is false"};
327 }
328 rails = parseRailArray(*railsIt);
329 ++propertyCount;
330 }
331
332 // Verify no invalid properties exist
333 verifyPropertyCount(element, propertyCount);
334
335 return std::make_unique<Device>(id, isRegulator, fru,
336 std::move(i2cInterface),
337 std::move(presenceDetection),
338 std::move(configuration), std::move(rails));
339}
340
Bob King0e701132020-04-03 21:50:31 +0800341std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
342{
343 verifyIsArray(element);
344 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800345 for (auto& deviceElement : element)
346 {
347 devices.emplace_back(parseDevice(deviceElement));
348 }
Bob King0e701132020-04-03 21:50:31 +0800349 return devices;
350}
351
Bob Kingbafcb862020-03-31 16:39:00 +0800352std::vector<uint8_t> parseHexByteArray(const json& element)
353{
354 verifyIsArray(element);
355 std::vector<uint8_t> values;
356 for (auto& valueElement : element)
357 {
358 values.emplace_back(parseHexByte(valueElement));
359 }
360 return values;
361}
362
Bob Kingf09bfe02020-04-13 17:21:15 +0800363std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
364{
365 verifyIsObject(element);
366 unsigned int propertyCount{0};
367
368 // Required register property
369 const json& regElement = getRequiredProperty(element, "register");
370 uint8_t reg = parseHexByte(regElement);
371 ++propertyCount;
372
373 // Required position property
374 const json& positionElement = getRequiredProperty(element, "position");
375 uint8_t position = parseBitPosition(positionElement);
376 ++propertyCount;
377
378 // Required value property
379 const json& valueElement = getRequiredProperty(element, "value");
380 uint8_t value = parseBitValue(valueElement);
381 ++propertyCount;
382
383 // Verify no invalid properties exist
384 verifyPropertyCount(element, propertyCount);
385
386 return std::make_unique<I2CCompareBitAction>(reg, position, value);
387}
388
389std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
390{
391 verifyIsObject(element);
392 unsigned int propertyCount{0};
393
394 // Required register property
395 const json& regElement = getRequiredProperty(element, "register");
396 uint8_t reg = parseHexByte(regElement);
397 ++propertyCount;
398
399 // Required value property
400 const json& valueElement = getRequiredProperty(element, "value");
401 uint8_t value = parseHexByte(valueElement);
402 ++propertyCount;
403
404 // Optional mask property
405 uint8_t mask = 0xff;
406 auto maskIt = element.find("mask");
407 if (maskIt != element.end())
408 {
409 mask = parseHexByte(*maskIt);
410 ++propertyCount;
411 }
412
413 // Verify no invalid properties exist
414 verifyPropertyCount(element, propertyCount);
415
416 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
417}
418
419std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
420{
421 verifyIsObject(element);
422 unsigned int propertyCount{0};
423
424 // Required register property
425 const json& regElement = getRequiredProperty(element, "register");
426 uint8_t reg = parseHexByte(regElement);
427 ++propertyCount;
428
429 // Required values property
430 const json& valueElement = getRequiredProperty(element, "values");
431 std::vector<uint8_t> values = parseHexByteArray(valueElement);
432 ++propertyCount;
433
434 // Optional masks property
435 std::vector<uint8_t> masks{};
436 auto masksIt = element.find("masks");
437 if (masksIt != element.end())
438 {
439 masks = parseHexByteArray(*masksIt);
440 ++propertyCount;
441 }
442
443 // Verify masks array (if specified) was same size as values array
444 if ((!masks.empty()) && (masks.size() != values.size()))
445 {
446 throw std::invalid_argument{"Invalid number of elements in masks"};
447 }
448
449 // Verify no invalid properties exist
450 verifyPropertyCount(element, propertyCount);
451
452 if (masks.empty())
453 {
454 return std::make_unique<I2CCompareBytesAction>(reg, values);
455 }
456 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
457}
458
Bob King9c36c5f2020-04-06 11:34:09 +0800459std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
460{
461 verifyIsObject(element);
462 unsigned int propertyCount{0};
463
464 // Required bus property
465 const json& busElement = getRequiredProperty(element, "bus");
466 uint8_t bus = parseUint8(busElement);
467 ++propertyCount;
468
469 // Required address property
470 const json& addressElement = getRequiredProperty(element, "address");
471 uint8_t address = parseHexByte(addressElement);
472 ++propertyCount;
473
474 verifyPropertyCount(element, propertyCount);
475 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
476}
477
Bob Kingf617f892020-03-30 19:03:35 +0800478std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
479{
480 verifyIsObject(element);
481 unsigned int propertyCount{0};
482
483 // Required register property
484 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800485 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800486 ++propertyCount;
487
488 // Required position property
489 const json& positionElement = getRequiredProperty(element, "position");
490 uint8_t position = parseBitPosition(positionElement);
491 ++propertyCount;
492
493 // Required value property
494 const json& valueElement = getRequiredProperty(element, "value");
495 uint8_t value = parseBitValue(valueElement);
496 ++propertyCount;
497
498 // Verify no invalid properties exist
499 verifyPropertyCount(element, propertyCount);
500
501 return std::make_unique<I2CWriteBitAction>(reg, position, value);
502}
503
Bob King87ff9d72020-03-31 14:02:55 +0800504std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
505{
506 verifyIsObject(element);
507 unsigned int propertyCount{0};
508
509 // Required register property
510 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800511 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800512 ++propertyCount;
513
514 // Required value property
515 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800516 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800517 ++propertyCount;
518
519 // Optional mask property
520 uint8_t mask = 0xff;
521 auto maskIt = element.find("mask");
522 if (maskIt != element.end())
523 {
Bob Kingbafcb862020-03-31 16:39:00 +0800524 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800525 ++propertyCount;
526 }
527
528 // Verify no invalid properties exist
529 verifyPropertyCount(element, propertyCount);
530
531 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
532}
533
Bob Kingbafcb862020-03-31 16:39:00 +0800534std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
535{
536 verifyIsObject(element);
537 unsigned int propertyCount{0};
538
539 // Required register property
540 const json& regElement = getRequiredProperty(element, "register");
541 uint8_t reg = parseHexByte(regElement);
542 ++propertyCount;
543
544 // Required values property
545 const json& valueElement = getRequiredProperty(element, "values");
546 std::vector<uint8_t> values = parseHexByteArray(valueElement);
547 ++propertyCount;
548
549 // Optional masks property
550 std::vector<uint8_t> masks{};
551 auto masksIt = element.find("masks");
552 if (masksIt != element.end())
553 {
554 masks = parseHexByteArray(*masksIt);
555 ++propertyCount;
556 }
557
558 // Verify masks array (if specified) was same size as values array
559 if ((!masks.empty()) && (masks.size() != values.size()))
560 {
561 throw std::invalid_argument{"Invalid number of elements in masks"};
562 }
563
564 // Verify no invalid properties exist
565 verifyPropertyCount(element, propertyCount);
566
567 if (masks.empty())
568 {
569 return std::make_unique<I2CWriteBytesAction>(reg, values);
570 }
571 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
572}
573
Bob King93a89d72020-04-15 15:11:11 +0800574std::unique_ptr<IfAction> parseIf(const json& element)
575{
576 verifyIsObject(element);
577 unsigned int propertyCount{0};
578
579 // Required condition property
580 const json& conditionElement = getRequiredProperty(element, "condition");
581 std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
582 ++propertyCount;
583
584 // Required then property
585 const json& thenElement = getRequiredProperty(element, "then");
586 std::vector<std::unique_ptr<Action>> thenActions =
587 parseActionArray(thenElement);
588 ++propertyCount;
589
590 // Optional else property
591 std::vector<std::unique_ptr<Action>> elseActions{};
592 auto elseIt = element.find("else");
593 if (elseIt != element.end())
594 {
595 elseActions = parseActionArray(*elseIt);
596 ++propertyCount;
597 }
598
599 // Verify no invalid properties exist
600 verifyPropertyCount(element, propertyCount);
601
602 return std::make_unique<IfAction>(std::move(conditionAction),
603 std::move(thenActions),
604 std::move(elseActions));
605}
606
Bob Kingf1b58dc2020-04-14 14:53:10 +0800607std::unique_ptr<NotAction> parseNot(const json& element)
608{
609 // Required action to execute
610 std::unique_ptr<Action> action = parseAction(element);
611
612 return std::make_unique<NotAction>(std::move(action));
613}
614
Bob King0b51a9b2020-04-15 13:24:18 +0800615std::unique_ptr<OrAction> parseOr(const json& element)
616{
617 verifyIsArray(element);
618
619 // Verify if array size less than 2
620 if (element.size() < 2)
621 {
622 throw std::invalid_argument{"Array must contain two or more actions"};
623 }
624 // Array of two or more actions
625 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
626
627 return std::make_unique<OrAction>(std::move(actions));
628}
629
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500630std::unique_ptr<PMBusWriteVoutCommandAction>
631 parsePMBusWriteVoutCommand(const json& element)
632{
633 verifyIsObject(element);
634 unsigned int propertyCount{0};
635
636 // Optional volts property
637 std::optional<double> volts{};
638 auto voltsIt = element.find("volts");
639 if (voltsIt != element.end())
640 {
641 volts = parseDouble(*voltsIt);
642 ++propertyCount;
643 }
644
645 // Required format property
646 const json& formatElement = getRequiredProperty(element, "format");
647 std::string formatString = parseString(formatElement);
648 if (formatString != "linear")
649 {
650 throw std::invalid_argument{"Invalid format value: " + formatString};
651 }
652 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
653 ++propertyCount;
654
655 // Optional exponent property
656 std::optional<int8_t> exponent{};
657 auto exponentIt = element.find("exponent");
658 if (exponentIt != element.end())
659 {
660 exponent = parseInt8(*exponentIt);
661 ++propertyCount;
662 }
663
664 // Optional is_verified property
665 bool isVerified = false;
666 auto isVerifiedIt = element.find("is_verified");
667 if (isVerifiedIt != element.end())
668 {
669 isVerified = parseBoolean(*isVerifiedIt);
670 ++propertyCount;
671 }
672
673 // Verify no invalid properties exist
674 verifyPropertyCount(element, propertyCount);
675
676 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
677 exponent, isVerified);
678}
679
Bob King2aafb1c2020-04-16 15:24:32 +0800680std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
681{
682 verifyIsObject(element);
683 unsigned int propertyCount{0};
684
685 // Optional comments property; value not stored
686 if (element.contains("comments"))
687 {
688 ++propertyCount;
689 }
690
691 // Required rule_id or actions property
692 std::vector<std::unique_ptr<Action>> actions{};
693 actions = parseRuleIDOrActionsProperty(element);
694 ++propertyCount;
695
696 // Verify no invalid properties exist
697 verifyPropertyCount(element, propertyCount);
698
699 return std::make_unique<PresenceDetection>(std::move(actions));
700}
701
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800702std::unique_ptr<Rail> parseRail(const json& element)
703{
704 verifyIsObject(element);
705 unsigned int propertyCount{0};
706
707 // Optional comments property; value not stored
708 if (element.contains("comments"))
709 {
710 ++propertyCount;
711 }
712
713 // Required id property
714 const json& idElement = getRequiredProperty(element, "id");
715 std::string id = parseString(idElement);
716 ++propertyCount;
717
718 // Optional configuration property
719 std::unique_ptr<Configuration> configuration{};
720 auto configurationIt = element.find("configuration");
721 if (configurationIt != element.end())
722 {
723 configuration = parseConfiguration(*configurationIt);
724 ++propertyCount;
725 }
726
727 // Optional sensor_monitoring property
728 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
729 auto sensorMonitoringIt = element.find("sensor_monitoring");
730 if (sensorMonitoringIt != element.end())
731 {
732 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
733 ++propertyCount;
734 }
735
736 // Verify no invalid properties exist
737 verifyPropertyCount(element, propertyCount);
738
739 return std::make_unique<Rail>(id, std::move(configuration),
740 std::move(sensorMonitoring));
741}
742
Bob King9c36c5f2020-04-06 11:34:09 +0800743std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
744{
745 verifyIsArray(element);
746 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800747 for (auto& railElement : element)
748 {
749 rails.emplace_back(parseRail(railElement));
750 }
Bob King9c36c5f2020-04-06 11:34:09 +0800751 return rails;
752}
753
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500754std::tuple<std::vector<std::unique_ptr<Rule>>,
755 std::vector<std::unique_ptr<Chassis>>>
756 parseRoot(const json& element)
757{
758 verifyIsObject(element);
759 unsigned int propertyCount{0};
760
761 // Optional comments property; value not stored
762 if (element.contains("comments"))
763 {
764 ++propertyCount;
765 }
766
767 // Optional rules property
768 std::vector<std::unique_ptr<Rule>> rules{};
769 auto rulesIt = element.find("rules");
770 if (rulesIt != element.end())
771 {
772 rules = parseRuleArray(*rulesIt);
773 ++propertyCount;
774 }
775
776 // Required chassis property
777 const json& chassisElement = getRequiredProperty(element, "chassis");
778 std::vector<std::unique_ptr<Chassis>> chassis =
779 parseChassisArray(chassisElement);
780 ++propertyCount;
781
782 // Verify no invalid properties exist
783 verifyPropertyCount(element, propertyCount);
784
785 return std::make_tuple(std::move(rules), std::move(chassis));
786}
787
788std::unique_ptr<Rule> parseRule(const json& element)
789{
790 verifyIsObject(element);
791 unsigned int propertyCount{0};
792
793 // Optional comments property; value not stored
794 if (element.contains("comments"))
795 {
796 ++propertyCount;
797 }
798
799 // Required id property
800 const json& idElement = getRequiredProperty(element, "id");
801 std::string id = parseString(idElement);
802 ++propertyCount;
803
804 // Required actions property
805 const json& actionsElement = getRequiredProperty(element, "actions");
806 std::vector<std::unique_ptr<Action>> actions =
807 parseActionArray(actionsElement);
808 ++propertyCount;
809
810 // Verify no invalid properties exist
811 verifyPropertyCount(element, propertyCount);
812
813 return std::make_unique<Rule>(id, std::move(actions));
814}
815
816std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
817{
818 verifyIsArray(element);
819 std::vector<std::unique_ptr<Rule>> rules;
820 for (auto& ruleElement : element)
821 {
822 rules.emplace_back(parseRule(ruleElement));
823 }
824 return rules;
825}
826
Bob King33e7eaa2020-04-01 18:09:34 +0800827std::vector<std::unique_ptr<Action>>
828 parseRuleIDOrActionsProperty(const json& element)
829{
830 verifyIsObject(element);
831 // Required rule_id or actions property
832 std::vector<std::unique_ptr<Action>> actions{};
833 auto ruleIDIt = element.find("rule_id");
834 auto actionsIt = element.find("actions");
835 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
836 {
837 std::string ruleID = parseString(*ruleIDIt);
838 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
839 }
840 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
841 {
842 actions = parseActionArray(*actionsIt);
843 }
844 else
845 {
846 throw std::invalid_argument{"Invalid property combination: Must "
847 "contain either rule_id or actions"};
848 }
849
850 return actions;
851}
852
Bob King315b0b62020-04-03 21:47:58 +0800853std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
854{
855 // String ruleID
856 std::string ruleID = parseString(element);
857
858 return std::make_unique<RunRuleAction>(ruleID);
859}
860
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800861std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
862{
863 verifyIsObject(element);
864 unsigned int propertyCount{0};
865
866 // Optional comments property; value not stored
867 if (element.contains("comments"))
868 {
869 ++propertyCount;
870 }
871
872 // Required rule_id or actions property
873 std::vector<std::unique_ptr<Action>> actions{};
874 actions = parseRuleIDOrActionsProperty(element);
875 ++propertyCount;
876
877 // Verify no invalid properties exist
878 verifyPropertyCount(element, propertyCount);
879
880 return std::make_unique<SensorMonitoring>(std::move(actions));
881}
882
Bob King18a68502020-04-17 14:19:56 +0800883std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element)
884{
885 // String deviceID
886 std::string deviceID = parseString(element);
887
888 return std::make_unique<SetDeviceAction>(deviceID);
889}
890
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500891} // namespace internal
892
893} // namespace phosphor::power::regulators::config_file_parser