1 /** 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" 20 #include "i2c_interface.hpp" 21 #include "pmbus_utils.hpp" 22 23 #include <exception> 24 #include <fstream> 25 #include <optional> 26 #include <utility> 27 28 using json = nlohmann::json; 29 30 namespace phosphor::power::regulators::config_file_parser 31 { 32 33 std::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 52 namespace internal 53 { 54 55 std::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 { 70 action = parseAnd(element["and"]); 71 ++propertyCount; 72 } 73 else if (element.contains("compare_presence")) 74 { 75 action = parseComparePresence(element["compare_presence"]); 76 ++propertyCount; 77 } 78 else if (element.contains("compare_vpd")) 79 { 80 // TODO: Not implemented yet 81 // action = parseCompareVPD(element["compare_vpd"]); 82 // ++propertyCount; 83 } 84 else if (element.contains("i2c_compare_bit")) 85 { 86 action = parseI2CCompareBit(element["i2c_compare_bit"]); 87 ++propertyCount; 88 } 89 else if (element.contains("i2c_compare_byte")) 90 { 91 action = parseI2CCompareByte(element["i2c_compare_byte"]); 92 ++propertyCount; 93 } 94 else if (element.contains("i2c_compare_bytes")) 95 { 96 action = parseI2CCompareBytes(element["i2c_compare_bytes"]); 97 ++propertyCount; 98 } 99 else if (element.contains("i2c_write_bit")) 100 { 101 action = parseI2CWriteBit(element["i2c_write_bit"]); 102 ++propertyCount; 103 } 104 else if (element.contains("i2c_write_byte")) 105 { 106 action = parseI2CWriteByte(element["i2c_write_byte"]); 107 ++propertyCount; 108 } 109 else if (element.contains("i2c_write_bytes")) 110 { 111 action = parseI2CWriteBytes(element["i2c_write_bytes"]); 112 ++propertyCount; 113 } 114 else if (element.contains("if")) 115 { 116 action = parseIf(element["if"]); 117 ++propertyCount; 118 } 119 else if (element.contains("not")) 120 { 121 action = parseNot(element["not"]); 122 ++propertyCount; 123 } 124 else if (element.contains("or")) 125 { 126 action = parseOr(element["or"]); 127 ++propertyCount; 128 } 129 else if (element.contains("pmbus_read_sensor")) 130 { 131 // TODO: Not implemented yet 132 // action = parsePMBusReadSensor(element["pmbus_read_sensor"]); 133 // ++propertyCount; 134 } 135 else if (element.contains("pmbus_write_vout_command")) 136 { 137 action = 138 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]); 139 ++propertyCount; 140 } 141 else if (element.contains("run_rule")) 142 { 143 action = parseRunRule(element["run_rule"]); 144 ++propertyCount; 145 } 146 else if (element.contains("set_device")) 147 { 148 action = parseSetDevice(element["set_device"]); 149 ++propertyCount; 150 } 151 else 152 { 153 throw std::invalid_argument{"Required action type property missing"}; 154 } 155 156 // Verify no invalid properties exist 157 verifyPropertyCount(element, propertyCount); 158 159 return action; 160 } 161 162 std::vector<std::unique_ptr<Action>> parseActionArray(const json& element) 163 { 164 verifyIsArray(element); 165 std::vector<std::unique_ptr<Action>> actions; 166 for (auto& actionElement : element) 167 { 168 actions.emplace_back(parseAction(actionElement)); 169 } 170 return actions; 171 } 172 173 std::unique_ptr<AndAction> parseAnd(const json& element) 174 { 175 verifyIsArray(element); 176 177 // Verify if array size less than 2 178 if (element.size() < 2) 179 { 180 throw std::invalid_argument{"Array must contain two or more actions"}; 181 } 182 // Array of two or more actions 183 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element); 184 185 return std::make_unique<AndAction>(std::move(actions)); 186 } 187 188 std::unique_ptr<Chassis> parseChassis(const json& element) 189 { 190 verifyIsObject(element); 191 unsigned int propertyCount{0}; 192 193 // Optional comments property; value not stored 194 if (element.contains("comments")) 195 { 196 ++propertyCount; 197 } 198 199 // Required number property 200 const json& numberElement = getRequiredProperty(element, "number"); 201 unsigned int number = parseUnsignedInteger(numberElement); 202 if (number < 1) 203 { 204 throw std::invalid_argument{"Invalid chassis number: Must be > 0"}; 205 } 206 ++propertyCount; 207 208 // Optional devices property 209 std::vector<std::unique_ptr<Device>> devices{}; 210 auto devicesIt = element.find("devices"); 211 if (devicesIt != element.end()) 212 { 213 devices = parseDeviceArray(*devicesIt); 214 ++propertyCount; 215 } 216 217 // Verify no invalid properties exist 218 verifyPropertyCount(element, propertyCount); 219 220 return std::make_unique<Chassis>(number, std::move(devices)); 221 } 222 223 std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element) 224 { 225 verifyIsArray(element); 226 std::vector<std::unique_ptr<Chassis>> chassis; 227 for (auto& chassisElement : element) 228 { 229 chassis.emplace_back(parseChassis(chassisElement)); 230 } 231 return chassis; 232 } 233 234 std::unique_ptr<ComparePresenceAction> parseComparePresence(const json& element) 235 { 236 verifyIsObject(element); 237 unsigned int propertyCount{0}; 238 239 // Required fru property 240 const json& fruElement = getRequiredProperty(element, "fru"); 241 std::string fru = parseString(fruElement); 242 ++propertyCount; 243 244 // Required value property 245 const json& valueElement = getRequiredProperty(element, "value"); 246 bool value = parseBoolean(valueElement); 247 ++propertyCount; 248 249 // Verify no invalid properties exist 250 verifyPropertyCount(element, propertyCount); 251 252 return std::make_unique<ComparePresenceAction>(fru, value); 253 } 254 255 std::unique_ptr<Configuration> parseConfiguration(const json& element) 256 { 257 verifyIsObject(element); 258 unsigned int propertyCount{0}; 259 260 // Optional comments property; value not stored 261 if (element.contains("comments")) 262 { 263 ++propertyCount; 264 } 265 266 // Optional volts property 267 std::optional<double> volts{}; 268 auto voltsIt = element.find("volts"); 269 if (voltsIt != element.end()) 270 { 271 volts = parseDouble(*voltsIt); 272 ++propertyCount; 273 } 274 275 // Required rule_id or actions property 276 std::vector<std::unique_ptr<Action>> actions{}; 277 actions = parseRuleIDOrActionsProperty(element); 278 ++propertyCount; 279 280 // Verify no invalid properties exist 281 verifyPropertyCount(element, propertyCount); 282 283 return std::make_unique<Configuration>(volts, std::move(actions)); 284 } 285 286 std::unique_ptr<Device> parseDevice(const json& element) 287 { 288 verifyIsObject(element); 289 unsigned int propertyCount{0}; 290 291 // Optional comments property; value not stored 292 if (element.contains("comments")) 293 { 294 ++propertyCount; 295 } 296 297 // Required id property 298 const json& idElement = getRequiredProperty(element, "id"); 299 std::string id = parseString(idElement); 300 ++propertyCount; 301 302 // Required is_regulator property 303 const json& isRegulatorElement = 304 getRequiredProperty(element, "is_regulator"); 305 bool isRegulator = parseBoolean(isRegulatorElement); 306 ++propertyCount; 307 308 // Required fru property 309 const json& fruElement = getRequiredProperty(element, "fru"); 310 std::string fru = parseString(fruElement); 311 ++propertyCount; 312 313 // Required i2c_interface property 314 const json& i2cInterfaceElement = 315 getRequiredProperty(element, "i2c_interface"); 316 std::unique_ptr<i2c::I2CInterface> i2cInterface = 317 parseI2CInterface(i2cInterfaceElement); 318 ++propertyCount; 319 320 // Optional presence_detection property 321 std::unique_ptr<PresenceDetection> presenceDetection{}; 322 auto presenceDetectionIt = element.find("presence_detection"); 323 if (presenceDetectionIt != element.end()) 324 { 325 presenceDetection = parsePresenceDetection(*presenceDetectionIt); 326 ++propertyCount; 327 } 328 329 // Optional configuration property 330 std::unique_ptr<Configuration> configuration{}; 331 auto configurationIt = element.find("configuration"); 332 if (configurationIt != element.end()) 333 { 334 configuration = parseConfiguration(*configurationIt); 335 ++propertyCount; 336 } 337 338 // Optional rails property 339 std::vector<std::unique_ptr<Rail>> rails{}; 340 auto railsIt = element.find("rails"); 341 if (railsIt != element.end()) 342 { 343 if (!isRegulator) 344 { 345 throw std::invalid_argument{ 346 "Invalid rails property when is_regulator is false"}; 347 } 348 rails = parseRailArray(*railsIt); 349 ++propertyCount; 350 } 351 352 // Verify no invalid properties exist 353 verifyPropertyCount(element, propertyCount); 354 355 return std::make_unique<Device>(id, isRegulator, fru, 356 std::move(i2cInterface), 357 std::move(presenceDetection), 358 std::move(configuration), std::move(rails)); 359 } 360 361 std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element) 362 { 363 verifyIsArray(element); 364 std::vector<std::unique_ptr<Device>> devices; 365 for (auto& deviceElement : element) 366 { 367 devices.emplace_back(parseDevice(deviceElement)); 368 } 369 return devices; 370 } 371 372 std::vector<uint8_t> parseHexByteArray(const json& element) 373 { 374 verifyIsArray(element); 375 std::vector<uint8_t> values; 376 for (auto& valueElement : element) 377 { 378 values.emplace_back(parseHexByte(valueElement)); 379 } 380 return values; 381 } 382 383 std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element) 384 { 385 verifyIsObject(element); 386 unsigned int propertyCount{0}; 387 388 // Required register property 389 const json& regElement = getRequiredProperty(element, "register"); 390 uint8_t reg = parseHexByte(regElement); 391 ++propertyCount; 392 393 // Required position property 394 const json& positionElement = getRequiredProperty(element, "position"); 395 uint8_t position = parseBitPosition(positionElement); 396 ++propertyCount; 397 398 // Required value property 399 const json& valueElement = getRequiredProperty(element, "value"); 400 uint8_t value = parseBitValue(valueElement); 401 ++propertyCount; 402 403 // Verify no invalid properties exist 404 verifyPropertyCount(element, propertyCount); 405 406 return std::make_unique<I2CCompareBitAction>(reg, position, value); 407 } 408 409 std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element) 410 { 411 verifyIsObject(element); 412 unsigned int propertyCount{0}; 413 414 // Required register property 415 const json& regElement = getRequiredProperty(element, "register"); 416 uint8_t reg = parseHexByte(regElement); 417 ++propertyCount; 418 419 // Required value property 420 const json& valueElement = getRequiredProperty(element, "value"); 421 uint8_t value = parseHexByte(valueElement); 422 ++propertyCount; 423 424 // Optional mask property 425 uint8_t mask = 0xff; 426 auto maskIt = element.find("mask"); 427 if (maskIt != element.end()) 428 { 429 mask = parseHexByte(*maskIt); 430 ++propertyCount; 431 } 432 433 // Verify no invalid properties exist 434 verifyPropertyCount(element, propertyCount); 435 436 return std::make_unique<I2CCompareByteAction>(reg, value, mask); 437 } 438 439 std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element) 440 { 441 verifyIsObject(element); 442 unsigned int propertyCount{0}; 443 444 // Required register property 445 const json& regElement = getRequiredProperty(element, "register"); 446 uint8_t reg = parseHexByte(regElement); 447 ++propertyCount; 448 449 // Required values property 450 const json& valueElement = getRequiredProperty(element, "values"); 451 std::vector<uint8_t> values = parseHexByteArray(valueElement); 452 ++propertyCount; 453 454 // Optional masks property 455 std::vector<uint8_t> masks{}; 456 auto masksIt = element.find("masks"); 457 if (masksIt != element.end()) 458 { 459 masks = parseHexByteArray(*masksIt); 460 ++propertyCount; 461 } 462 463 // Verify masks array (if specified) was same size as values array 464 if ((!masks.empty()) && (masks.size() != values.size())) 465 { 466 throw std::invalid_argument{"Invalid number of elements in masks"}; 467 } 468 469 // Verify no invalid properties exist 470 verifyPropertyCount(element, propertyCount); 471 472 if (masks.empty()) 473 { 474 return std::make_unique<I2CCompareBytesAction>(reg, values); 475 } 476 return std::make_unique<I2CCompareBytesAction>(reg, values, masks); 477 } 478 479 std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element) 480 { 481 verifyIsObject(element); 482 unsigned int propertyCount{0}; 483 484 // Required bus property 485 const json& busElement = getRequiredProperty(element, "bus"); 486 uint8_t bus = parseUint8(busElement); 487 ++propertyCount; 488 489 // Required address property 490 const json& addressElement = getRequiredProperty(element, "address"); 491 uint8_t address = parseHexByte(addressElement); 492 ++propertyCount; 493 494 verifyPropertyCount(element, propertyCount); 495 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED); 496 } 497 498 std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element) 499 { 500 verifyIsObject(element); 501 unsigned int propertyCount{0}; 502 503 // Required register property 504 const json& regElement = getRequiredProperty(element, "register"); 505 uint8_t reg = parseHexByte(regElement); 506 ++propertyCount; 507 508 // Required position property 509 const json& positionElement = getRequiredProperty(element, "position"); 510 uint8_t position = parseBitPosition(positionElement); 511 ++propertyCount; 512 513 // Required value property 514 const json& valueElement = getRequiredProperty(element, "value"); 515 uint8_t value = parseBitValue(valueElement); 516 ++propertyCount; 517 518 // Verify no invalid properties exist 519 verifyPropertyCount(element, propertyCount); 520 521 return std::make_unique<I2CWriteBitAction>(reg, position, value); 522 } 523 524 std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element) 525 { 526 verifyIsObject(element); 527 unsigned int propertyCount{0}; 528 529 // Required register property 530 const json& regElement = getRequiredProperty(element, "register"); 531 uint8_t reg = parseHexByte(regElement); 532 ++propertyCount; 533 534 // Required value property 535 const json& valueElement = getRequiredProperty(element, "value"); 536 uint8_t value = parseHexByte(valueElement); 537 ++propertyCount; 538 539 // Optional mask property 540 uint8_t mask = 0xff; 541 auto maskIt = element.find("mask"); 542 if (maskIt != element.end()) 543 { 544 mask = parseHexByte(*maskIt); 545 ++propertyCount; 546 } 547 548 // Verify no invalid properties exist 549 verifyPropertyCount(element, propertyCount); 550 551 return std::make_unique<I2CWriteByteAction>(reg, value, mask); 552 } 553 554 std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element) 555 { 556 verifyIsObject(element); 557 unsigned int propertyCount{0}; 558 559 // Required register property 560 const json& regElement = getRequiredProperty(element, "register"); 561 uint8_t reg = parseHexByte(regElement); 562 ++propertyCount; 563 564 // Required values property 565 const json& valueElement = getRequiredProperty(element, "values"); 566 std::vector<uint8_t> values = parseHexByteArray(valueElement); 567 ++propertyCount; 568 569 // Optional masks property 570 std::vector<uint8_t> masks{}; 571 auto masksIt = element.find("masks"); 572 if (masksIt != element.end()) 573 { 574 masks = parseHexByteArray(*masksIt); 575 ++propertyCount; 576 } 577 578 // Verify masks array (if specified) was same size as values array 579 if ((!masks.empty()) && (masks.size() != values.size())) 580 { 581 throw std::invalid_argument{"Invalid number of elements in masks"}; 582 } 583 584 // Verify no invalid properties exist 585 verifyPropertyCount(element, propertyCount); 586 587 if (masks.empty()) 588 { 589 return std::make_unique<I2CWriteBytesAction>(reg, values); 590 } 591 return std::make_unique<I2CWriteBytesAction>(reg, values, masks); 592 } 593 594 std::unique_ptr<IfAction> parseIf(const json& element) 595 { 596 verifyIsObject(element); 597 unsigned int propertyCount{0}; 598 599 // Required condition property 600 const json& conditionElement = getRequiredProperty(element, "condition"); 601 std::unique_ptr<Action> conditionAction = parseAction(conditionElement); 602 ++propertyCount; 603 604 // Required then property 605 const json& thenElement = getRequiredProperty(element, "then"); 606 std::vector<std::unique_ptr<Action>> thenActions = 607 parseActionArray(thenElement); 608 ++propertyCount; 609 610 // Optional else property 611 std::vector<std::unique_ptr<Action>> elseActions{}; 612 auto elseIt = element.find("else"); 613 if (elseIt != element.end()) 614 { 615 elseActions = parseActionArray(*elseIt); 616 ++propertyCount; 617 } 618 619 // Verify no invalid properties exist 620 verifyPropertyCount(element, propertyCount); 621 622 return std::make_unique<IfAction>(std::move(conditionAction), 623 std::move(thenActions), 624 std::move(elseActions)); 625 } 626 627 std::unique_ptr<NotAction> parseNot(const json& element) 628 { 629 // Required action to execute 630 std::unique_ptr<Action> action = parseAction(element); 631 632 return std::make_unique<NotAction>(std::move(action)); 633 } 634 635 std::unique_ptr<OrAction> parseOr(const json& element) 636 { 637 verifyIsArray(element); 638 639 // Verify if array size less than 2 640 if (element.size() < 2) 641 { 642 throw std::invalid_argument{"Array must contain two or more actions"}; 643 } 644 // Array of two or more actions 645 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element); 646 647 return std::make_unique<OrAction>(std::move(actions)); 648 } 649 650 std::unique_ptr<PMBusWriteVoutCommandAction> 651 parsePMBusWriteVoutCommand(const json& element) 652 { 653 verifyIsObject(element); 654 unsigned int propertyCount{0}; 655 656 // Optional volts property 657 std::optional<double> volts{}; 658 auto voltsIt = element.find("volts"); 659 if (voltsIt != element.end()) 660 { 661 volts = parseDouble(*voltsIt); 662 ++propertyCount; 663 } 664 665 // Required format property 666 const json& formatElement = getRequiredProperty(element, "format"); 667 std::string formatString = parseString(formatElement); 668 if (formatString != "linear") 669 { 670 throw std::invalid_argument{"Invalid format value: " + formatString}; 671 } 672 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear; 673 ++propertyCount; 674 675 // Optional exponent property 676 std::optional<int8_t> exponent{}; 677 auto exponentIt = element.find("exponent"); 678 if (exponentIt != element.end()) 679 { 680 exponent = parseInt8(*exponentIt); 681 ++propertyCount; 682 } 683 684 // Optional is_verified property 685 bool isVerified = false; 686 auto isVerifiedIt = element.find("is_verified"); 687 if (isVerifiedIt != element.end()) 688 { 689 isVerified = parseBoolean(*isVerifiedIt); 690 ++propertyCount; 691 } 692 693 // Verify no invalid properties exist 694 verifyPropertyCount(element, propertyCount); 695 696 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format, 697 exponent, isVerified); 698 } 699 700 std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element) 701 { 702 verifyIsObject(element); 703 unsigned int propertyCount{0}; 704 705 // Optional comments property; value not stored 706 if (element.contains("comments")) 707 { 708 ++propertyCount; 709 } 710 711 // Required rule_id or actions property 712 std::vector<std::unique_ptr<Action>> actions{}; 713 actions = parseRuleIDOrActionsProperty(element); 714 ++propertyCount; 715 716 // Verify no invalid properties exist 717 verifyPropertyCount(element, propertyCount); 718 719 return std::make_unique<PresenceDetection>(std::move(actions)); 720 } 721 722 std::unique_ptr<Rail> parseRail(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 // Optional configuration property 739 std::unique_ptr<Configuration> configuration{}; 740 auto configurationIt = element.find("configuration"); 741 if (configurationIt != element.end()) 742 { 743 configuration = parseConfiguration(*configurationIt); 744 ++propertyCount; 745 } 746 747 // Optional sensor_monitoring property 748 std::unique_ptr<SensorMonitoring> sensorMonitoring{}; 749 auto sensorMonitoringIt = element.find("sensor_monitoring"); 750 if (sensorMonitoringIt != element.end()) 751 { 752 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt); 753 ++propertyCount; 754 } 755 756 // Verify no invalid properties exist 757 verifyPropertyCount(element, propertyCount); 758 759 return std::make_unique<Rail>(id, std::move(configuration), 760 std::move(sensorMonitoring)); 761 } 762 763 std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element) 764 { 765 verifyIsArray(element); 766 std::vector<std::unique_ptr<Rail>> rails; 767 for (auto& railElement : element) 768 { 769 rails.emplace_back(parseRail(railElement)); 770 } 771 return rails; 772 } 773 774 std::tuple<std::vector<std::unique_ptr<Rule>>, 775 std::vector<std::unique_ptr<Chassis>>> 776 parseRoot(const json& element) 777 { 778 verifyIsObject(element); 779 unsigned int propertyCount{0}; 780 781 // Optional comments property; value not stored 782 if (element.contains("comments")) 783 { 784 ++propertyCount; 785 } 786 787 // Optional rules property 788 std::vector<std::unique_ptr<Rule>> rules{}; 789 auto rulesIt = element.find("rules"); 790 if (rulesIt != element.end()) 791 { 792 rules = parseRuleArray(*rulesIt); 793 ++propertyCount; 794 } 795 796 // Required chassis property 797 const json& chassisElement = getRequiredProperty(element, "chassis"); 798 std::vector<std::unique_ptr<Chassis>> chassis = 799 parseChassisArray(chassisElement); 800 ++propertyCount; 801 802 // Verify no invalid properties exist 803 verifyPropertyCount(element, propertyCount); 804 805 return std::make_tuple(std::move(rules), std::move(chassis)); 806 } 807 808 std::unique_ptr<Rule> parseRule(const json& element) 809 { 810 verifyIsObject(element); 811 unsigned int propertyCount{0}; 812 813 // Optional comments property; value not stored 814 if (element.contains("comments")) 815 { 816 ++propertyCount; 817 } 818 819 // Required id property 820 const json& idElement = getRequiredProperty(element, "id"); 821 std::string id = parseString(idElement); 822 ++propertyCount; 823 824 // Required actions property 825 const json& actionsElement = getRequiredProperty(element, "actions"); 826 std::vector<std::unique_ptr<Action>> actions = 827 parseActionArray(actionsElement); 828 ++propertyCount; 829 830 // Verify no invalid properties exist 831 verifyPropertyCount(element, propertyCount); 832 833 return std::make_unique<Rule>(id, std::move(actions)); 834 } 835 836 std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element) 837 { 838 verifyIsArray(element); 839 std::vector<std::unique_ptr<Rule>> rules; 840 for (auto& ruleElement : element) 841 { 842 rules.emplace_back(parseRule(ruleElement)); 843 } 844 return rules; 845 } 846 847 std::vector<std::unique_ptr<Action>> 848 parseRuleIDOrActionsProperty(const json& element) 849 { 850 verifyIsObject(element); 851 // Required rule_id or actions property 852 std::vector<std::unique_ptr<Action>> actions{}; 853 auto ruleIDIt = element.find("rule_id"); 854 auto actionsIt = element.find("actions"); 855 if ((actionsIt == element.end()) && (ruleIDIt != element.end())) 856 { 857 std::string ruleID = parseString(*ruleIDIt); 858 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID)); 859 } 860 else if ((actionsIt != element.end()) && (ruleIDIt == element.end())) 861 { 862 actions = parseActionArray(*actionsIt); 863 } 864 else 865 { 866 throw std::invalid_argument{"Invalid property combination: Must " 867 "contain either rule_id or actions"}; 868 } 869 870 return actions; 871 } 872 873 std::unique_ptr<RunRuleAction> parseRunRule(const json& element) 874 { 875 // String ruleID 876 std::string ruleID = parseString(element); 877 878 return std::make_unique<RunRuleAction>(ruleID); 879 } 880 881 std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element) 882 { 883 verifyIsObject(element); 884 unsigned int propertyCount{0}; 885 886 // Optional comments property; value not stored 887 if (element.contains("comments")) 888 { 889 ++propertyCount; 890 } 891 892 // Required rule_id or actions property 893 std::vector<std::unique_ptr<Action>> actions{}; 894 actions = parseRuleIDOrActionsProperty(element); 895 ++propertyCount; 896 897 // Verify no invalid properties exist 898 verifyPropertyCount(element, propertyCount); 899 900 return std::make_unique<SensorMonitoring>(std::move(actions)); 901 } 902 903 std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element) 904 { 905 // String deviceID 906 std::string deviceID = parseString(element); 907 908 return std::make_unique<SetDeviceAction>(deviceID); 909 } 910 911 } // namespace internal 912 913 } // namespace phosphor::power::regulators::config_file_parser 914