|
1 | 1 | #include "node_implementation.h" |
2 | 2 |
|
| 3 | +#include <map> |
3 | 4 | #include <boost/range/adaptor/filtered.hpp> |
| 5 | +#include <boost/range/adaptor/map.hpp> |
4 | 6 | #include <boost/range/adaptor/transformed.hpp> |
5 | 7 | #include <boost/range/algorithm/find.hpp> |
6 | 8 | #include <boost/range/algorithm/find_first_of.hpp> |
|
10 | 12 | #include <boost/range/join.hpp> |
11 | 13 | #include "pplx/pplx_utils.h" // for pplx::complete_after, etc. |
12 | 14 | #include "cpprest/host_utils.h" |
| 15 | +#include "cpprest/json_validator.h" |
13 | 16 | #ifdef HAVE_LLDP |
14 | 17 | #include "lldp/lldp_manager.h" |
15 | 18 | #endif |
@@ -2574,6 +2577,88 @@ namespace impl |
2574 | 2577 | { |
2575 | 2578 | web::json::push_back(resource.data[nmos::fields::tags][nmos::fields::group_hint], nmos::make_group_hint({ U("example"), resource.type.name + U(' ') + port.name + utility::conversions::details::to_string_t(index) })); |
2576 | 2579 | } |
| 2580 | + |
| 2581 | + // JSON schema covering the example-node-specific impl::fields::* settings; combined with |
| 2582 | + // nmos::validate_node_settings, this covers all the properties this example reads from the |
| 2583 | + // settings JSON. additionalProperties is not set to false, so all other (standard) settings |
| 2584 | + // pass through unchecked, allowing the two validators to be composed. |
| 2585 | + // definitions: aliases (in nmos::details::settings_definitions_schema() source order) first, then local |
| 2586 | + static const char* node_settings_schema_text = R"-schema-( |
| 2587 | +{ |
| 2588 | + "$schema": "http://json-schema.org/draft-04/schema#", |
| 2589 | + "type": "object", |
| 2590 | + "definitions": { |
| 2591 | + "nonNegativeInteger": { "$ref": "urn:x-nmos-cpp:schemas:defs#/definitions/nonNegativeInteger" }, |
| 2592 | + "positiveInteger": { "$ref": "urn:x-nmos-cpp:schemas:defs#/definitions/positiveInteger" }, |
| 2593 | + "rational": { "$ref": "urn:x-nmos-cpp:schemas:defs#/definitions/rational" }, |
| 2594 | + "tags": { "$ref": "urn:x-nmos-cpp:schemas:defs#/definitions/tags" }, |
| 2595 | + "uuid": { "$ref": "urn:x-nmos-cpp:schemas:defs#/definitions/uuid" }, |
| 2596 | + "interlaceMode": { "$ref": "urn:x-nmos-cpp:schemas:defs#/definitions/interlaceMode" }, |
| 2597 | + "colorspace": { "$ref": "urn:x-nmos-cpp:schemas:defs#/definitions/colorspace" }, |
| 2598 | + "transferCharacteristic": { "$ref": "urn:x-nmos-cpp:schemas:defs#/definitions/transferCharacteristic" }, |
| 2599 | + "colorSampling": { "$ref": "urn:x-nmos-cpp:schemas:defs#/definitions/colorSampling" }, |
| 2600 | + "portKind": { "type": "string", "enum": ["v", "a", "d", "m", "t", "b", "s", "c", "xv", "xa", "xd"] } |
| 2601 | + }, |
| 2602 | + "properties": { |
| 2603 | + "node_tags": { "$ref": "#/definitions/tags" }, |
| 2604 | + "device_tags": { "$ref": "#/definitions/tags" }, |
| 2605 | +
|
| 2606 | + "how_many": { "$ref": "#/definitions/nonNegativeInteger" }, |
| 2607 | + "activate_senders": { "type": "boolean" }, |
| 2608 | +
|
| 2609 | + "senders": { "type": "array", "items": { "$ref": "#/definitions/portKind" } }, |
| 2610 | + "receivers": { "type": "array", "items": { "$ref": "#/definitions/portKind" } }, |
| 2611 | +
|
| 2612 | + "frame_rate": { "$ref": "#/definitions/rational" }, |
| 2613 | + "frame_width": { "$ref": "#/definitions/positiveInteger" }, |
| 2614 | + "frame_height": { "$ref": "#/definitions/positiveInteger" }, |
| 2615 | +
|
| 2616 | + "interlace_mode": { "$ref": "#/definitions/interlaceMode" }, |
| 2617 | +
|
| 2618 | + "colorspace": { "$ref": "#/definitions/colorspace" }, |
| 2619 | + "transfer_characteristic": { "$ref": "#/definitions/transferCharacteristic" }, |
| 2620 | + "color_sampling": { "$ref": "#/definitions/colorSampling" }, |
| 2621 | + "component_depth": { "$ref": "#/definitions/positiveInteger" }, |
| 2622 | + "video_type": { "type": "string", "pattern": "^video\\/[^\\s\\/]+$" }, |
| 2623 | + "mxl_video_type": { "type": "string", "enum": ["video/v210", "video/v210a"] }, |
| 2624 | +
|
| 2625 | + "channel_count": { "$ref": "#/definitions/positiveInteger" }, |
| 2626 | +
|
| 2627 | + "smpte2022_7": { "type": "boolean" }, |
| 2628 | + "simulate_status_monitor_activity": { "type": "boolean" }, |
| 2629 | +
|
| 2630 | + "mxl_domain_id": { "$ref": "#/definitions/uuid" } |
| 2631 | + } |
| 2632 | +} |
| 2633 | + )-schema-"; |
| 2634 | + |
| 2635 | + const std::pair<web::uri, web::json::value>& node_settings_schema() |
| 2636 | + { |
| 2637 | + static const std::pair<web::uri, web::json::value> instance{ |
| 2638 | + web::uri{ U("urn:x-nmos-cpp:schemas:node-settings") }, |
| 2639 | + web::json::value::parse(node_settings_schema_text) |
| 2640 | + }; |
| 2641 | + return instance; |
| 2642 | + } |
| 2643 | + |
| 2644 | +} |
| 2645 | + |
| 2646 | +void validate_node_implementation_settings(const nmos::settings& settings) |
| 2647 | +{ |
| 2648 | + // delegate validation of the standard properties (see nmos/settings.h) |
| 2649 | + nmos::validate_node_settings(settings); |
| 2650 | + |
| 2651 | + // validate the example node-specific impl::fields::* properties |
| 2652 | + static const std::map<web::uri, web::json::value> known{ |
| 2653 | + impl::node_settings_schema(), |
| 2654 | + nmos::details::settings_definitions_schema() |
| 2655 | + }; |
| 2656 | + static const web::json::experimental::json_validator validator |
| 2657 | + { |
| 2658 | + [](const web::uri& wanted) { return known.at(wanted); }, |
| 2659 | + boost::copy_range<std::vector<web::uri>>(known | boost::adaptors::map_keys) |
| 2660 | + }; |
| 2661 | + validator.validate(settings, impl::node_settings_schema().first); |
2577 | 2662 | } |
2578 | 2663 |
|
2579 | 2664 | // This constructs all the callbacks used to integrate the example device-specific underlying implementation |
|
0 commit comments