blob: 5f0181ecb0a6b1db6c7b3d7ca0109a2c62884cf4 [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 {
117 // TODO: Not implemented yet
118 // action = parseIf(element["if"]);
119 // ++propertyCount;
120 }
121 else if (element.contains("not"))
122 {
Bob Kingf1b58dc2020-04-14 14:53:10 +0800123 action = parseNot(element["not"]);
124 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500125 }
126 else if (element.contains("or"))
127 {
128 // TODO: Not implemented yet
129 // action = parseOr(element["or"]);
130 // ++propertyCount;
131 }
132 else if (element.contains("pmbus_read_sensor"))
133 {
134 // TODO: Not implemented yet
135 // action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
136 // ++propertyCount;
137 }
138 else if (element.contains("pmbus_write_vout_command"))
139 {
140 action =
141 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
142 ++propertyCount;
143 }
144 else if (element.contains("run_rule"))
145 {
Bob King315b0b62020-04-03 21:47:58 +0800146 action = parseRunRule(element["run_rule"]);
147 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500148 }
149 else if (element.contains("set_device"))
150 {
151 // TODO: Not implemented yet
152 // action = parseSetDevice(element["set_device"]);
153 // ++propertyCount;
154 }
155 else
156 {
157 throw std::invalid_argument{"Required action type property missing"};
158 }
159
160 // Verify no invalid properties exist
161 verifyPropertyCount(element, propertyCount);
162
163 return action;
164}
165
166std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
167{
168 verifyIsArray(element);
169 std::vector<std::unique_ptr<Action>> actions;
170 for (auto& actionElement : element)
171 {
172 actions.emplace_back(parseAction(actionElement));
173 }
174 return actions;
175}
176
Bob King3a787542020-04-14 13:45:01 +0800177std::unique_ptr<AndAction> parseAnd(const json& element)
178{
179 verifyIsArray(element);
180
181 // Verify if array size less than 2
182 if (element.size() < 2)
183 {
184 throw std::invalid_argument{"Array must contain two or more actions"};
185 }
186 // Array of two or more actions
187 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
188
189 return std::make_unique<AndAction>(std::move(actions));
190}
191
Bob King0e701132020-04-03 21:50:31 +0800192std::unique_ptr<Chassis> parseChassis(const json& element)
193{
194 verifyIsObject(element);
195 unsigned int propertyCount{0};
196
197 // Optional comments property; value not stored
198 if (element.contains("comments"))
199 {
200 ++propertyCount;
201 }
202
203 // Required number property
204 const json& numberElement = getRequiredProperty(element, "number");
205 unsigned int number = parseUnsignedInteger(numberElement);
206 if (number < 1)
207 {
208 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
209 }
210 ++propertyCount;
211
212 // Optional devices property
213 std::vector<std::unique_ptr<Device>> devices{};
214 auto devicesIt = element.find("devices");
215 if (devicesIt != element.end())
216 {
217 devices = parseDeviceArray(*devicesIt);
218 ++propertyCount;
219 }
220
221 // Verify no invalid properties exist
222 verifyPropertyCount(element, propertyCount);
223
224 return std::make_unique<Chassis>(number, std::move(devices));
225}
226
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500227std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
228{
229 verifyIsArray(element);
230 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800231 for (auto& chassisElement : element)
232 {
233 chassis.emplace_back(parseChassis(chassisElement));
234 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500235 return chassis;
236}
237
Bob King33e7eaa2020-04-01 18:09:34 +0800238std::unique_ptr<Configuration> parseConfiguration(const json& element)
239{
240 verifyIsObject(element);
241 unsigned int propertyCount{0};
242
243 // Optional comments property; value not stored
244 if (element.contains("comments"))
245 {
246 ++propertyCount;
247 }
248
249 // Optional volts property
250 std::optional<double> volts{};
251 auto voltsIt = element.find("volts");
252 if (voltsIt != element.end())
253 {
254 volts = parseDouble(*voltsIt);
255 ++propertyCount;
256 }
257
258 // Required rule_id or actions property
259 std::vector<std::unique_ptr<Action>> actions{};
260 actions = parseRuleIDOrActionsProperty(element);
261 ++propertyCount;
262
263 // Verify no invalid properties exist
264 verifyPropertyCount(element, propertyCount);
265
266 return std::make_unique<Configuration>(volts, std::move(actions));
267}
268
Bob King9c36c5f2020-04-06 11:34:09 +0800269std::unique_ptr<Device> parseDevice(const json& element)
270{
271 verifyIsObject(element);
272 unsigned int propertyCount{0};
273
274 // Optional comments property; value not stored
275 if (element.contains("comments"))
276 {
277 ++propertyCount;
278 }
279
280 // Required id property
281 const json& idElement = getRequiredProperty(element, "id");
282 std::string id = parseString(idElement);
283 ++propertyCount;
284
285 // Required is_regulator property
286 const json& isRegulatorElement =
287 getRequiredProperty(element, "is_regulator");
288 bool isRegulator = parseBoolean(isRegulatorElement);
289 ++propertyCount;
290
291 // Required fru property
292 const json& fruElement = getRequiredProperty(element, "fru");
293 std::string fru = parseString(fruElement);
294 ++propertyCount;
295
296 // Required i2c_interface property
297 const json& i2cInterfaceElement =
298 getRequiredProperty(element, "i2c_interface");
299 std::unique_ptr<i2c::I2CInterface> i2cInterface =
300 parseI2CInterface(i2cInterfaceElement);
301 ++propertyCount;
302
303 // Optional presence_detection property
304 // TODO: Not implemented yet
305 std::unique_ptr<PresenceDetection> presenceDetection{};
306 // auto presenceDetectionIt = element.find("presence_detection");
307 // if (presenceDetectionIt != element.end())
308 // {
309 // presenceDetection = parsePresenceDetection(*presenceDetectionIt);
310 // ++propertyCount;
311 // }
312
313 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800314 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800315 auto configurationIt = element.find("configuration");
316 if (configurationIt != element.end())
317 {
318 configuration = parseConfiguration(*configurationIt);
319 ++propertyCount;
320 }
Bob King9c36c5f2020-04-06 11:34:09 +0800321
322 // Optional rails property
323 std::vector<std::unique_ptr<Rail>> rails{};
324 auto railsIt = element.find("rails");
325 if (railsIt != element.end())
326 {
327 if (!isRegulator)
328 {
329 throw std::invalid_argument{
330 "Invalid rails property when is_regulator is false"};
331 }
332 rails = parseRailArray(*railsIt);
333 ++propertyCount;
334 }
335
336 // Verify no invalid properties exist
337 verifyPropertyCount(element, propertyCount);
338
339 return std::make_unique<Device>(id, isRegulator, fru,
340 std::move(i2cInterface),
341 std::move(presenceDetection),
342 std::move(configuration), std::move(rails));
343}
344
Bob King0e701132020-04-03 21:50:31 +0800345std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
346{
347 verifyIsArray(element);
348 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800349 for (auto& deviceElement : element)
350 {
351 devices.emplace_back(parseDevice(deviceElement));
352 }
Bob King0e701132020-04-03 21:50:31 +0800353 return devices;
354}
355
Bob Kingbafcb862020-03-31 16:39:00 +0800356std::vector<uint8_t> parseHexByteArray(const json& element)
357{
358 verifyIsArray(element);
359 std::vector<uint8_t> values;
360 for (auto& valueElement : element)
361 {
362 values.emplace_back(parseHexByte(valueElement));
363 }
364 return values;
365}
366
Bob Kingf09bfe02020-04-13 17:21:15 +0800367std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
368{
369 verifyIsObject(element);
370 unsigned int propertyCount{0};
371
372 // Required register property
373 const json& regElement = getRequiredProperty(element, "register");
374 uint8_t reg = parseHexByte(regElement);
375 ++propertyCount;
376
377 // Required position property
378 const json& positionElement = getRequiredProperty(element, "position");
379 uint8_t position = parseBitPosition(positionElement);
380 ++propertyCount;
381
382 // Required value property
383 const json& valueElement = getRequiredProperty(element, "value");
384 uint8_t value = parseBitValue(valueElement);
385 ++propertyCount;
386
387 // Verify no invalid properties exist
388 verifyPropertyCount(element, propertyCount);
389
390 return std::make_unique<I2CCompareBitAction>(reg, position, value);
391}
392
393std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
394{
395 verifyIsObject(element);
396 unsigned int propertyCount{0};
397
398 // Required register property
399 const json& regElement = getRequiredProperty(element, "register");
400 uint8_t reg = parseHexByte(regElement);
401 ++propertyCount;
402
403 // Required value property
404 const json& valueElement = getRequiredProperty(element, "value");
405 uint8_t value = parseHexByte(valueElement);
406 ++propertyCount;
407
408 // Optional mask property
409 uint8_t mask = 0xff;
410 auto maskIt = element.find("mask");
411 if (maskIt != element.end())
412 {
413 mask = parseHexByte(*maskIt);
414 ++propertyCount;
415 }
416
417 // Verify no invalid properties exist
418 verifyPropertyCount(element, propertyCount);
419
420 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
421}
422
423std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
424{
425 verifyIsObject(element);
426 unsigned int propertyCount{0};
427
428 // Required register property
429 const json& regElement = getRequiredProperty(element, "register");
430 uint8_t reg = parseHexByte(regElement);
431 ++propertyCount;
432
433 // Required values property
434 const json& valueElement = getRequiredProperty(element, "values");
435 std::vector<uint8_t> values = parseHexByteArray(valueElement);
436 ++propertyCount;
437
438 // Optional masks property
439 std::vector<uint8_t> masks{};
440 auto masksIt = element.find("masks");
441 if (masksIt != element.end())
442 {
443 masks = parseHexByteArray(*masksIt);
444 ++propertyCount;
445 }
446
447 // Verify masks array (if specified) was same size as values array
448 if ((!masks.empty()) && (masks.size() != values.size()))
449 {
450 throw std::invalid_argument{"Invalid number of elements in masks"};
451 }
452
453 // Verify no invalid properties exist
454 verifyPropertyCount(element, propertyCount);
455
456 if (masks.empty())
457 {
458 return std::make_unique<I2CCompareBytesAction>(reg, values);
459 }
460 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
461}
462
Bob King9c36c5f2020-04-06 11:34:09 +0800463std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
464{
465 verifyIsObject(element);
466 unsigned int propertyCount{0};
467
468 // Required bus property
469 const json& busElement = getRequiredProperty(element, "bus");
470 uint8_t bus = parseUint8(busElement);
471 ++propertyCount;
472
473 // Required address property
474 const json& addressElement = getRequiredProperty(element, "address");
475 uint8_t address = parseHexByte(addressElement);
476 ++propertyCount;
477
478 verifyPropertyCount(element, propertyCount);
479 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
480}
481
Bob Kingf617f892020-03-30 19:03:35 +0800482std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
483{
484 verifyIsObject(element);
485 unsigned int propertyCount{0};
486
487 // Required register property
488 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800489 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800490 ++propertyCount;
491
492 // Required position property
493 const json& positionElement = getRequiredProperty(element, "position");
494 uint8_t position = parseBitPosition(positionElement);
495 ++propertyCount;
496
497 // Required value property
498 const json& valueElement = getRequiredProperty(element, "value");
499 uint8_t value = parseBitValue(valueElement);
500 ++propertyCount;
501
502 // Verify no invalid properties exist
503 verifyPropertyCount(element, propertyCount);
504
505 return std::make_unique<I2CWriteBitAction>(reg, position, value);
506}
507
Bob King87ff9d72020-03-31 14:02:55 +0800508std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
509{
510 verifyIsObject(element);
511 unsigned int propertyCount{0};
512
513 // Required register property
514 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800515 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800516 ++propertyCount;
517
518 // Required value property
519 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800520 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800521 ++propertyCount;
522
523 // Optional mask property
524 uint8_t mask = 0xff;
525 auto maskIt = element.find("mask");
526 if (maskIt != element.end())
527 {
Bob Kingbafcb862020-03-31 16:39:00 +0800528 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800529 ++propertyCount;
530 }
531
532 // Verify no invalid properties exist
533 verifyPropertyCount(element, propertyCount);
534
535 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
536}
537
Bob Kingbafcb862020-03-31 16:39:00 +0800538std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
539{
540 verifyIsObject(element);
541 unsigned int propertyCount{0};
542
543 // Required register property
544 const json& regElement = getRequiredProperty(element, "register");
545 uint8_t reg = parseHexByte(regElement);
546 ++propertyCount;
547
548 // Required values property
549 const json& valueElement = getRequiredProperty(element, "values");
550 std::vector<uint8_t> values = parseHexByteArray(valueElement);
551 ++propertyCount;
552
553 // Optional masks property
554 std::vector<uint8_t> masks{};
555 auto masksIt = element.find("masks");
556 if (masksIt != element.end())
557 {
558 masks = parseHexByteArray(*masksIt);
559 ++propertyCount;
560 }
561
562 // Verify masks array (if specified) was same size as values array
563 if ((!masks.empty()) && (masks.size() != values.size()))
564 {
565 throw std::invalid_argument{"Invalid number of elements in masks"};
566 }
567
568 // Verify no invalid properties exist
569 verifyPropertyCount(element, propertyCount);
570
571 if (masks.empty())
572 {
573 return std::make_unique<I2CWriteBytesAction>(reg, values);
574 }
575 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
576}
577
Bob Kingf1b58dc2020-04-14 14:53:10 +0800578std::unique_ptr<NotAction> parseNot(const json& element)
579{
580 // Required action to execute
581 std::unique_ptr<Action> action = parseAction(element);
582
583 return std::make_unique<NotAction>(std::move(action));
584}
585
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500586std::unique_ptr<PMBusWriteVoutCommandAction>
587 parsePMBusWriteVoutCommand(const json& element)
588{
589 verifyIsObject(element);
590 unsigned int propertyCount{0};
591
592 // Optional volts property
593 std::optional<double> volts{};
594 auto voltsIt = element.find("volts");
595 if (voltsIt != element.end())
596 {
597 volts = parseDouble(*voltsIt);
598 ++propertyCount;
599 }
600
601 // Required format property
602 const json& formatElement = getRequiredProperty(element, "format");
603 std::string formatString = parseString(formatElement);
604 if (formatString != "linear")
605 {
606 throw std::invalid_argument{"Invalid format value: " + formatString};
607 }
608 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
609 ++propertyCount;
610
611 // Optional exponent property
612 std::optional<int8_t> exponent{};
613 auto exponentIt = element.find("exponent");
614 if (exponentIt != element.end())
615 {
616 exponent = parseInt8(*exponentIt);
617 ++propertyCount;
618 }
619
620 // Optional is_verified property
621 bool isVerified = false;
622 auto isVerifiedIt = element.find("is_verified");
623 if (isVerifiedIt != element.end())
624 {
625 isVerified = parseBoolean(*isVerifiedIt);
626 ++propertyCount;
627 }
628
629 // Verify no invalid properties exist
630 verifyPropertyCount(element, propertyCount);
631
632 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
633 exponent, isVerified);
634}
635
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800636std::unique_ptr<Rail> parseRail(const json& element)
637{
638 verifyIsObject(element);
639 unsigned int propertyCount{0};
640
641 // Optional comments property; value not stored
642 if (element.contains("comments"))
643 {
644 ++propertyCount;
645 }
646
647 // Required id property
648 const json& idElement = getRequiredProperty(element, "id");
649 std::string id = parseString(idElement);
650 ++propertyCount;
651
652 // Optional configuration property
653 std::unique_ptr<Configuration> configuration{};
654 auto configurationIt = element.find("configuration");
655 if (configurationIt != element.end())
656 {
657 configuration = parseConfiguration(*configurationIt);
658 ++propertyCount;
659 }
660
661 // Optional sensor_monitoring property
662 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
663 auto sensorMonitoringIt = element.find("sensor_monitoring");
664 if (sensorMonitoringIt != element.end())
665 {
666 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
667 ++propertyCount;
668 }
669
670 // Verify no invalid properties exist
671 verifyPropertyCount(element, propertyCount);
672
673 return std::make_unique<Rail>(id, std::move(configuration),
674 std::move(sensorMonitoring));
675}
676
Bob King9c36c5f2020-04-06 11:34:09 +0800677std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
678{
679 verifyIsArray(element);
680 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800681 for (auto& railElement : element)
682 {
683 rails.emplace_back(parseRail(railElement));
684 }
Bob King9c36c5f2020-04-06 11:34:09 +0800685 return rails;
686}
687
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500688std::tuple<std::vector<std::unique_ptr<Rule>>,
689 std::vector<std::unique_ptr<Chassis>>>
690 parseRoot(const json& element)
691{
692 verifyIsObject(element);
693 unsigned int propertyCount{0};
694
695 // Optional comments property; value not stored
696 if (element.contains("comments"))
697 {
698 ++propertyCount;
699 }
700
701 // Optional rules property
702 std::vector<std::unique_ptr<Rule>> rules{};
703 auto rulesIt = element.find("rules");
704 if (rulesIt != element.end())
705 {
706 rules = parseRuleArray(*rulesIt);
707 ++propertyCount;
708 }
709
710 // Required chassis property
711 const json& chassisElement = getRequiredProperty(element, "chassis");
712 std::vector<std::unique_ptr<Chassis>> chassis =
713 parseChassisArray(chassisElement);
714 ++propertyCount;
715
716 // Verify no invalid properties exist
717 verifyPropertyCount(element, propertyCount);
718
719 return std::make_tuple(std::move(rules), std::move(chassis));
720}
721
722std::unique_ptr<Rule> parseRule(const json& element)
723{
724 verifyIsObject(element);
725 unsigned int propertyCount{0};
726
727 // Optional comments property; value not stored
728 if (element.contains("comments"))
729 {
730 ++propertyCount;
731 }
732
733 // Required id property
734 const json& idElement = getRequiredProperty(element, "id");
735 std::string id = parseString(idElement);
736 ++propertyCount;
737
738 // Required actions property
739 const json& actionsElement = getRequiredProperty(element, "actions");
740 std::vector<std::unique_ptr<Action>> actions =
741 parseActionArray(actionsElement);
742 ++propertyCount;
743
744 // Verify no invalid properties exist
745 verifyPropertyCount(element, propertyCount);
746
747 return std::make_unique<Rule>(id, std::move(actions));
748}
749
750std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
751{
752 verifyIsArray(element);
753 std::vector<std::unique_ptr<Rule>> rules;
754 for (auto& ruleElement : element)
755 {
756 rules.emplace_back(parseRule(ruleElement));
757 }
758 return rules;
759}
760
Bob King33e7eaa2020-04-01 18:09:34 +0800761std::vector<std::unique_ptr<Action>>
762 parseRuleIDOrActionsProperty(const json& element)
763{
764 verifyIsObject(element);
765 // Required rule_id or actions property
766 std::vector<std::unique_ptr<Action>> actions{};
767 auto ruleIDIt = element.find("rule_id");
768 auto actionsIt = element.find("actions");
769 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
770 {
771 std::string ruleID = parseString(*ruleIDIt);
772 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
773 }
774 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
775 {
776 actions = parseActionArray(*actionsIt);
777 }
778 else
779 {
780 throw std::invalid_argument{"Invalid property combination: Must "
781 "contain either rule_id or actions"};
782 }
783
784 return actions;
785}
786
Bob King315b0b62020-04-03 21:47:58 +0800787std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
788{
789 // String ruleID
790 std::string ruleID = parseString(element);
791
792 return std::make_unique<RunRuleAction>(ruleID);
793}
794
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800795std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
796{
797 verifyIsObject(element);
798 unsigned int propertyCount{0};
799
800 // Optional comments property; value not stored
801 if (element.contains("comments"))
802 {
803 ++propertyCount;
804 }
805
806 // Required rule_id or actions property
807 std::vector<std::unique_ptr<Action>> actions{};
808 actions = parseRuleIDOrActionsProperty(element);
809 ++propertyCount;
810
811 // Verify no invalid properties exist
812 verifyPropertyCount(element, propertyCount);
813
814 return std::make_unique<SensorMonitoring>(std::move(actions));
815}
816
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500817} // namespace internal
818
819} // namespace phosphor::power::regulators::config_file_parser