blob: 9615d31703137a8603564f5c508955d7c37bcbaa [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 {
149 // TODO: Not implemented yet
150 // action = parseSetDevice(element["set_device"]);
151 // ++propertyCount;
152 }
153 else
154 {
155 throw std::invalid_argument{"Required action type property missing"};
156 }
157
158 // Verify no invalid properties exist
159 verifyPropertyCount(element, propertyCount);
160
161 return action;
162}
163
164std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
165{
166 verifyIsArray(element);
167 std::vector<std::unique_ptr<Action>> actions;
168 for (auto& actionElement : element)
169 {
170 actions.emplace_back(parseAction(actionElement));
171 }
172 return actions;
173}
174
Bob King3a787542020-04-14 13:45:01 +0800175std::unique_ptr<AndAction> parseAnd(const json& element)
176{
177 verifyIsArray(element);
178
179 // Verify if array size less than 2
180 if (element.size() < 2)
181 {
182 throw std::invalid_argument{"Array must contain two or more actions"};
183 }
184 // Array of two or more actions
185 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
186
187 return std::make_unique<AndAction>(std::move(actions));
188}
189
Bob King0e701132020-04-03 21:50:31 +0800190std::unique_ptr<Chassis> parseChassis(const json& element)
191{
192 verifyIsObject(element);
193 unsigned int propertyCount{0};
194
195 // Optional comments property; value not stored
196 if (element.contains("comments"))
197 {
198 ++propertyCount;
199 }
200
201 // Required number property
202 const json& numberElement = getRequiredProperty(element, "number");
203 unsigned int number = parseUnsignedInteger(numberElement);
204 if (number < 1)
205 {
206 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
207 }
208 ++propertyCount;
209
210 // Optional devices property
211 std::vector<std::unique_ptr<Device>> devices{};
212 auto devicesIt = element.find("devices");
213 if (devicesIt != element.end())
214 {
215 devices = parseDeviceArray(*devicesIt);
216 ++propertyCount;
217 }
218
219 // Verify no invalid properties exist
220 verifyPropertyCount(element, propertyCount);
221
222 return std::make_unique<Chassis>(number, std::move(devices));
223}
224
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500225std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
226{
227 verifyIsArray(element);
228 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800229 for (auto& chassisElement : element)
230 {
231 chassis.emplace_back(parseChassis(chassisElement));
232 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500233 return chassis;
234}
235
Bob King33e7eaa2020-04-01 18:09:34 +0800236std::unique_ptr<Configuration> parseConfiguration(const json& element)
237{
238 verifyIsObject(element);
239 unsigned int propertyCount{0};
240
241 // Optional comments property; value not stored
242 if (element.contains("comments"))
243 {
244 ++propertyCount;
245 }
246
247 // Optional volts property
248 std::optional<double> volts{};
249 auto voltsIt = element.find("volts");
250 if (voltsIt != element.end())
251 {
252 volts = parseDouble(*voltsIt);
253 ++propertyCount;
254 }
255
256 // Required rule_id or actions property
257 std::vector<std::unique_ptr<Action>> actions{};
258 actions = parseRuleIDOrActionsProperty(element);
259 ++propertyCount;
260
261 // Verify no invalid properties exist
262 verifyPropertyCount(element, propertyCount);
263
264 return std::make_unique<Configuration>(volts, std::move(actions));
265}
266
Bob King9c36c5f2020-04-06 11:34:09 +0800267std::unique_ptr<Device> parseDevice(const json& element)
268{
269 verifyIsObject(element);
270 unsigned int propertyCount{0};
271
272 // Optional comments property; value not stored
273 if (element.contains("comments"))
274 {
275 ++propertyCount;
276 }
277
278 // Required id property
279 const json& idElement = getRequiredProperty(element, "id");
280 std::string id = parseString(idElement);
281 ++propertyCount;
282
283 // Required is_regulator property
284 const json& isRegulatorElement =
285 getRequiredProperty(element, "is_regulator");
286 bool isRegulator = parseBoolean(isRegulatorElement);
287 ++propertyCount;
288
289 // Required fru property
290 const json& fruElement = getRequiredProperty(element, "fru");
291 std::string fru = parseString(fruElement);
292 ++propertyCount;
293
294 // Required i2c_interface property
295 const json& i2cInterfaceElement =
296 getRequiredProperty(element, "i2c_interface");
297 std::unique_ptr<i2c::I2CInterface> i2cInterface =
298 parseI2CInterface(i2cInterfaceElement);
299 ++propertyCount;
300
301 // Optional presence_detection property
302 // TODO: Not implemented yet
303 std::unique_ptr<PresenceDetection> presenceDetection{};
304 // auto presenceDetectionIt = element.find("presence_detection");
305 // if (presenceDetectionIt != element.end())
306 // {
307 // presenceDetection = parsePresenceDetection(*presenceDetectionIt);
308 // ++propertyCount;
309 // }
310
311 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800312 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800313 auto configurationIt = element.find("configuration");
314 if (configurationIt != element.end())
315 {
316 configuration = parseConfiguration(*configurationIt);
317 ++propertyCount;
318 }
Bob King9c36c5f2020-04-06 11:34:09 +0800319
320 // Optional rails property
321 std::vector<std::unique_ptr<Rail>> rails{};
322 auto railsIt = element.find("rails");
323 if (railsIt != element.end())
324 {
325 if (!isRegulator)
326 {
327 throw std::invalid_argument{
328 "Invalid rails property when is_regulator is false"};
329 }
330 rails = parseRailArray(*railsIt);
331 ++propertyCount;
332 }
333
334 // Verify no invalid properties exist
335 verifyPropertyCount(element, propertyCount);
336
337 return std::make_unique<Device>(id, isRegulator, fru,
338 std::move(i2cInterface),
339 std::move(presenceDetection),
340 std::move(configuration), std::move(rails));
341}
342
Bob King0e701132020-04-03 21:50:31 +0800343std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
344{
345 verifyIsArray(element);
346 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800347 for (auto& deviceElement : element)
348 {
349 devices.emplace_back(parseDevice(deviceElement));
350 }
Bob King0e701132020-04-03 21:50:31 +0800351 return devices;
352}
353
Bob Kingbafcb862020-03-31 16:39:00 +0800354std::vector<uint8_t> parseHexByteArray(const json& element)
355{
356 verifyIsArray(element);
357 std::vector<uint8_t> values;
358 for (auto& valueElement : element)
359 {
360 values.emplace_back(parseHexByte(valueElement));
361 }
362 return values;
363}
364
Bob Kingf09bfe02020-04-13 17:21:15 +0800365std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
366{
367 verifyIsObject(element);
368 unsigned int propertyCount{0};
369
370 // Required register property
371 const json& regElement = getRequiredProperty(element, "register");
372 uint8_t reg = parseHexByte(regElement);
373 ++propertyCount;
374
375 // Required position property
376 const json& positionElement = getRequiredProperty(element, "position");
377 uint8_t position = parseBitPosition(positionElement);
378 ++propertyCount;
379
380 // Required value property
381 const json& valueElement = getRequiredProperty(element, "value");
382 uint8_t value = parseBitValue(valueElement);
383 ++propertyCount;
384
385 // Verify no invalid properties exist
386 verifyPropertyCount(element, propertyCount);
387
388 return std::make_unique<I2CCompareBitAction>(reg, position, value);
389}
390
391std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
392{
393 verifyIsObject(element);
394 unsigned int propertyCount{0};
395
396 // Required register property
397 const json& regElement = getRequiredProperty(element, "register");
398 uint8_t reg = parseHexByte(regElement);
399 ++propertyCount;
400
401 // Required value property
402 const json& valueElement = getRequiredProperty(element, "value");
403 uint8_t value = parseHexByte(valueElement);
404 ++propertyCount;
405
406 // Optional mask property
407 uint8_t mask = 0xff;
408 auto maskIt = element.find("mask");
409 if (maskIt != element.end())
410 {
411 mask = parseHexByte(*maskIt);
412 ++propertyCount;
413 }
414
415 // Verify no invalid properties exist
416 verifyPropertyCount(element, propertyCount);
417
418 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
419}
420
421std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
422{
423 verifyIsObject(element);
424 unsigned int propertyCount{0};
425
426 // Required register property
427 const json& regElement = getRequiredProperty(element, "register");
428 uint8_t reg = parseHexByte(regElement);
429 ++propertyCount;
430
431 // Required values property
432 const json& valueElement = getRequiredProperty(element, "values");
433 std::vector<uint8_t> values = parseHexByteArray(valueElement);
434 ++propertyCount;
435
436 // Optional masks property
437 std::vector<uint8_t> masks{};
438 auto masksIt = element.find("masks");
439 if (masksIt != element.end())
440 {
441 masks = parseHexByteArray(*masksIt);
442 ++propertyCount;
443 }
444
445 // Verify masks array (if specified) was same size as values array
446 if ((!masks.empty()) && (masks.size() != values.size()))
447 {
448 throw std::invalid_argument{"Invalid number of elements in masks"};
449 }
450
451 // Verify no invalid properties exist
452 verifyPropertyCount(element, propertyCount);
453
454 if (masks.empty())
455 {
456 return std::make_unique<I2CCompareBytesAction>(reg, values);
457 }
458 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
459}
460
Bob King9c36c5f2020-04-06 11:34:09 +0800461std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
462{
463 verifyIsObject(element);
464 unsigned int propertyCount{0};
465
466 // Required bus property
467 const json& busElement = getRequiredProperty(element, "bus");
468 uint8_t bus = parseUint8(busElement);
469 ++propertyCount;
470
471 // Required address property
472 const json& addressElement = getRequiredProperty(element, "address");
473 uint8_t address = parseHexByte(addressElement);
474 ++propertyCount;
475
476 verifyPropertyCount(element, propertyCount);
477 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
478}
479
Bob Kingf617f892020-03-30 19:03:35 +0800480std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
481{
482 verifyIsObject(element);
483 unsigned int propertyCount{0};
484
485 // Required register property
486 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800487 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800488 ++propertyCount;
489
490 // Required position property
491 const json& positionElement = getRequiredProperty(element, "position");
492 uint8_t position = parseBitPosition(positionElement);
493 ++propertyCount;
494
495 // Required value property
496 const json& valueElement = getRequiredProperty(element, "value");
497 uint8_t value = parseBitValue(valueElement);
498 ++propertyCount;
499
500 // Verify no invalid properties exist
501 verifyPropertyCount(element, propertyCount);
502
503 return std::make_unique<I2CWriteBitAction>(reg, position, value);
504}
505
Bob King87ff9d72020-03-31 14:02:55 +0800506std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
507{
508 verifyIsObject(element);
509 unsigned int propertyCount{0};
510
511 // Required register property
512 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800513 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800514 ++propertyCount;
515
516 // Required value property
517 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800518 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800519 ++propertyCount;
520
521 // Optional mask property
522 uint8_t mask = 0xff;
523 auto maskIt = element.find("mask");
524 if (maskIt != element.end())
525 {
Bob Kingbafcb862020-03-31 16:39:00 +0800526 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800527 ++propertyCount;
528 }
529
530 // Verify no invalid properties exist
531 verifyPropertyCount(element, propertyCount);
532
533 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
534}
535
Bob Kingbafcb862020-03-31 16:39:00 +0800536std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
537{
538 verifyIsObject(element);
539 unsigned int propertyCount{0};
540
541 // Required register property
542 const json& regElement = getRequiredProperty(element, "register");
543 uint8_t reg = parseHexByte(regElement);
544 ++propertyCount;
545
546 // Required values property
547 const json& valueElement = getRequiredProperty(element, "values");
548 std::vector<uint8_t> values = parseHexByteArray(valueElement);
549 ++propertyCount;
550
551 // Optional masks property
552 std::vector<uint8_t> masks{};
553 auto masksIt = element.find("masks");
554 if (masksIt != element.end())
555 {
556 masks = parseHexByteArray(*masksIt);
557 ++propertyCount;
558 }
559
560 // Verify masks array (if specified) was same size as values array
561 if ((!masks.empty()) && (masks.size() != values.size()))
562 {
563 throw std::invalid_argument{"Invalid number of elements in masks"};
564 }
565
566 // Verify no invalid properties exist
567 verifyPropertyCount(element, propertyCount);
568
569 if (masks.empty())
570 {
571 return std::make_unique<I2CWriteBytesAction>(reg, values);
572 }
573 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
574}
575
Bob King93a89d72020-04-15 15:11:11 +0800576std::unique_ptr<IfAction> parseIf(const json& element)
577{
578 verifyIsObject(element);
579 unsigned int propertyCount{0};
580
581 // Required condition property
582 const json& conditionElement = getRequiredProperty(element, "condition");
583 std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
584 ++propertyCount;
585
586 // Required then property
587 const json& thenElement = getRequiredProperty(element, "then");
588 std::vector<std::unique_ptr<Action>> thenActions =
589 parseActionArray(thenElement);
590 ++propertyCount;
591
592 // Optional else property
593 std::vector<std::unique_ptr<Action>> elseActions{};
594 auto elseIt = element.find("else");
595 if (elseIt != element.end())
596 {
597 elseActions = parseActionArray(*elseIt);
598 ++propertyCount;
599 }
600
601 // Verify no invalid properties exist
602 verifyPropertyCount(element, propertyCount);
603
604 return std::make_unique<IfAction>(std::move(conditionAction),
605 std::move(thenActions),
606 std::move(elseActions));
607}
608
Bob Kingf1b58dc2020-04-14 14:53:10 +0800609std::unique_ptr<NotAction> parseNot(const json& element)
610{
611 // Required action to execute
612 std::unique_ptr<Action> action = parseAction(element);
613
614 return std::make_unique<NotAction>(std::move(action));
615}
616
Bob King0b51a9b2020-04-15 13:24:18 +0800617std::unique_ptr<OrAction> parseOr(const json& element)
618{
619 verifyIsArray(element);
620
621 // Verify if array size less than 2
622 if (element.size() < 2)
623 {
624 throw std::invalid_argument{"Array must contain two or more actions"};
625 }
626 // Array of two or more actions
627 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
628
629 return std::make_unique<OrAction>(std::move(actions));
630}
631
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500632std::unique_ptr<PMBusWriteVoutCommandAction>
633 parsePMBusWriteVoutCommand(const json& element)
634{
635 verifyIsObject(element);
636 unsigned int propertyCount{0};
637
638 // Optional volts property
639 std::optional<double> volts{};
640 auto voltsIt = element.find("volts");
641 if (voltsIt != element.end())
642 {
643 volts = parseDouble(*voltsIt);
644 ++propertyCount;
645 }
646
647 // Required format property
648 const json& formatElement = getRequiredProperty(element, "format");
649 std::string formatString = parseString(formatElement);
650 if (formatString != "linear")
651 {
652 throw std::invalid_argument{"Invalid format value: " + formatString};
653 }
654 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
655 ++propertyCount;
656
657 // Optional exponent property
658 std::optional<int8_t> exponent{};
659 auto exponentIt = element.find("exponent");
660 if (exponentIt != element.end())
661 {
662 exponent = parseInt8(*exponentIt);
663 ++propertyCount;
664 }
665
666 // Optional is_verified property
667 bool isVerified = false;
668 auto isVerifiedIt = element.find("is_verified");
669 if (isVerifiedIt != element.end())
670 {
671 isVerified = parseBoolean(*isVerifiedIt);
672 ++propertyCount;
673 }
674
675 // Verify no invalid properties exist
676 verifyPropertyCount(element, propertyCount);
677
678 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
679 exponent, isVerified);
680}
681
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800682std::unique_ptr<Rail> parseRail(const json& element)
683{
684 verifyIsObject(element);
685 unsigned int propertyCount{0};
686
687 // Optional comments property; value not stored
688 if (element.contains("comments"))
689 {
690 ++propertyCount;
691 }
692
693 // Required id property
694 const json& idElement = getRequiredProperty(element, "id");
695 std::string id = parseString(idElement);
696 ++propertyCount;
697
698 // Optional configuration property
699 std::unique_ptr<Configuration> configuration{};
700 auto configurationIt = element.find("configuration");
701 if (configurationIt != element.end())
702 {
703 configuration = parseConfiguration(*configurationIt);
704 ++propertyCount;
705 }
706
707 // Optional sensor_monitoring property
708 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
709 auto sensorMonitoringIt = element.find("sensor_monitoring");
710 if (sensorMonitoringIt != element.end())
711 {
712 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
713 ++propertyCount;
714 }
715
716 // Verify no invalid properties exist
717 verifyPropertyCount(element, propertyCount);
718
719 return std::make_unique<Rail>(id, std::move(configuration),
720 std::move(sensorMonitoring));
721}
722
Bob King9c36c5f2020-04-06 11:34:09 +0800723std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
724{
725 verifyIsArray(element);
726 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800727 for (auto& railElement : element)
728 {
729 rails.emplace_back(parseRail(railElement));
730 }
Bob King9c36c5f2020-04-06 11:34:09 +0800731 return rails;
732}
733
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500734std::tuple<std::vector<std::unique_ptr<Rule>>,
735 std::vector<std::unique_ptr<Chassis>>>
736 parseRoot(const json& element)
737{
738 verifyIsObject(element);
739 unsigned int propertyCount{0};
740
741 // Optional comments property; value not stored
742 if (element.contains("comments"))
743 {
744 ++propertyCount;
745 }
746
747 // Optional rules property
748 std::vector<std::unique_ptr<Rule>> rules{};
749 auto rulesIt = element.find("rules");
750 if (rulesIt != element.end())
751 {
752 rules = parseRuleArray(*rulesIt);
753 ++propertyCount;
754 }
755
756 // Required chassis property
757 const json& chassisElement = getRequiredProperty(element, "chassis");
758 std::vector<std::unique_ptr<Chassis>> chassis =
759 parseChassisArray(chassisElement);
760 ++propertyCount;
761
762 // Verify no invalid properties exist
763 verifyPropertyCount(element, propertyCount);
764
765 return std::make_tuple(std::move(rules), std::move(chassis));
766}
767
768std::unique_ptr<Rule> parseRule(const json& element)
769{
770 verifyIsObject(element);
771 unsigned int propertyCount{0};
772
773 // Optional comments property; value not stored
774 if (element.contains("comments"))
775 {
776 ++propertyCount;
777 }
778
779 // Required id property
780 const json& idElement = getRequiredProperty(element, "id");
781 std::string id = parseString(idElement);
782 ++propertyCount;
783
784 // Required actions property
785 const json& actionsElement = getRequiredProperty(element, "actions");
786 std::vector<std::unique_ptr<Action>> actions =
787 parseActionArray(actionsElement);
788 ++propertyCount;
789
790 // Verify no invalid properties exist
791 verifyPropertyCount(element, propertyCount);
792
793 return std::make_unique<Rule>(id, std::move(actions));
794}
795
796std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
797{
798 verifyIsArray(element);
799 std::vector<std::unique_ptr<Rule>> rules;
800 for (auto& ruleElement : element)
801 {
802 rules.emplace_back(parseRule(ruleElement));
803 }
804 return rules;
805}
806
Bob King33e7eaa2020-04-01 18:09:34 +0800807std::vector<std::unique_ptr<Action>>
808 parseRuleIDOrActionsProperty(const json& element)
809{
810 verifyIsObject(element);
811 // Required rule_id or actions property
812 std::vector<std::unique_ptr<Action>> actions{};
813 auto ruleIDIt = element.find("rule_id");
814 auto actionsIt = element.find("actions");
815 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
816 {
817 std::string ruleID = parseString(*ruleIDIt);
818 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
819 }
820 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
821 {
822 actions = parseActionArray(*actionsIt);
823 }
824 else
825 {
826 throw std::invalid_argument{"Invalid property combination: Must "
827 "contain either rule_id or actions"};
828 }
829
830 return actions;
831}
832
Bob King315b0b62020-04-03 21:47:58 +0800833std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
834{
835 // String ruleID
836 std::string ruleID = parseString(element);
837
838 return std::make_unique<RunRuleAction>(ruleID);
839}
840
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800841std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
842{
843 verifyIsObject(element);
844 unsigned int propertyCount{0};
845
846 // Optional comments property; value not stored
847 if (element.contains("comments"))
848 {
849 ++propertyCount;
850 }
851
852 // Required rule_id or actions property
853 std::vector<std::unique_ptr<Action>> actions{};
854 actions = parseRuleIDOrActionsProperty(element);
855 ++propertyCount;
856
857 // Verify no invalid properties exist
858 verifyPropertyCount(element, propertyCount);
859
860 return std::make_unique<SensorMonitoring>(std::move(actions));
861}
862
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500863} // namespace internal
864
865} // namespace phosphor::power::regulators::config_file_parser