Skip to content

Commit 4eb2690

Browse files
authored
Merge pull request #13 from lo-simon/is-14-backup-restore
IS-14: Add GetPropertiesByPath, ValidateSetPropertiesByPath and SetPropertiesByPath
2 parents 36c9566 + ec0643b commit 4eb2690

33 files changed

+3247
-1040
lines changed

Development/cmake/NmosCppLibraries.cmake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,9 @@ set(NMOS_CPP_NMOS_SOURCES
10061006
nmos/client_utils.cpp
10071007
nmos/components.cpp
10081008
nmos/configuration_api.cpp
1009+
nmos/configuration_methods.cpp
1010+
nmos/configuration_resources.cpp
1011+
nmos/configuration_utils.cpp
10091012
nmos/connection_activation.cpp
10101013
nmos/connection_api.cpp
10111014
nmos/connection_events_activation.cpp
@@ -1100,6 +1103,10 @@ set(NMOS_CPP_NMOS_HEADERS
11001103
nmos/components.h
11011104
nmos/copyable_atomic.h
11021105
nmos/configuration_api.h
1106+
nmos/configuration_handlers.h
1107+
nmos/configuration_methods.h
1108+
nmos/configuration_resources.h
1109+
nmos/configuration_utils.h
11031110
nmos/connection_activation.h
11041111
nmos/connection_api.h
11051112
nmos/connection_events_activation.h

Development/cmake/NmosCppTest.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ set(NMOS_CPP_TEST_NMOS_TEST_SOURCES
4343
nmos/test/api_utils_test.cpp
4444
nmos/test/capabilities_test.cpp
4545
nmos/test/channels_test.cpp
46+
nmos/test/configuration_resources_test.cpp
47+
nmos/test/configuration_utils_test.cpp
4648
nmos/test/control_protocol_test.cpp
49+
nmos/test/control_protocol_test.cpp
50+
nmos/test/control_protocol_utils_test.cpp
4751
nmos/test/did_sdid_test.cpp
4852
nmos/test/event_type_test.cpp
4953
nmos/test/json_validator_test.cpp

Development/nmos-cpp-node/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ int main(int argc, char* argv[])
138138
.on_request_authorization_code(nmos::experimental::make_request_authorization_code_handler(gate)); // may be omitted, only required for OAuth client which is using the Authorization Code Flow to obtain the access token
139139
}
140140

141-
nmos::experimental::control_protocol_state control_protocol_state(node_implementation.control_protocol_property_changed, node_implementation.get_properties_by_path, node_implementation.validate_set_properties_by_path, node_implementation.set_properties_by_path);
141+
nmos::experimental::control_protocol_state control_protocol_state(node_implementation.control_protocol_property_changed, node_implementation.filter_property_value_holders, node_implementation.modify_rebuildable_block);
142142
if (0 <= nmos::fields::control_protocol_ws_port(node_model.settings))
143143
{
144144
node_implementation

Development/nmos-cpp-node/node_implementation.cpp

Lines changed: 354 additions & 41 deletions
Large diffs are not rendered by default.

Development/nmos/configuration_api.cpp

Lines changed: 108 additions & 236 deletions
Large diffs are not rendered by default.

Development/nmos/configuration_api.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "cpprest/api_router.h"
55
#include "nmos/control_protocol_handlers.h"
6+
#include "nmos/configuration_handlers.h"
67

78
namespace slog
89
{
@@ -15,7 +16,7 @@ namespace nmos
1516
{
1617
struct node_model;
1718

18-
web::http::experimental::listener::api_router make_configuration_api(nmos::node_model& model, web::http::experimental::listener::route_handler validate_authorization, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate);
19+
web::http::experimental::listener::api_router make_configuration_api(nmos::node_model& model, web::http::experimental::listener::route_handler validate_authorization, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, filter_property_value_holders_handler filter_property_value_holders, modify_rebuildable_block_handler modify_rebuildable_block, control_protocol_property_changed_handler property_changed, slog::base_gate& gate);
1920
}
2021

2122
#endif
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef NMOS_CONFIGURATION_HANDLERS_H
2+
#define NMOS_CONFIGURATION_HANDLERS_H
3+
4+
#include <functional>
5+
#include "nmos/control_protocol_typedefs.h"
6+
#include "nmos/control_protocol_handlers.h"
7+
#include "nmos/resources.h"
8+
9+
namespace slog
10+
{
11+
class base_gate;
12+
}
13+
14+
namespace nmos
15+
{
16+
namespace experimental
17+
{
18+
struct control_protocol_state;
19+
}
20+
// This callback is invoked if attempting to modify read only properties when restoring a configuration.
21+
// This function should modify the Device Model object directly and return a corresponding NcObjectPropertiesSetValidation object
22+
typedef std::function<web::json::array(const nmos::resource& resource, const web::json::array& target_role_path, const web::json::array& object_properties_holders, bool recurse, bool validate, web::json::array& property_restore_notices, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor)> filter_property_value_holders_handler;
23+
24+
// This callback is invoked if attempting to modify a rebuildable block when restoring a configuration.
25+
// This function should handle the modification of the Device Model and any corresponding NMOS resources
26+
// and return correpsonding NcObjectPropertiesSetValidation objects for each object modified/added
27+
typedef std::function<web::json::value(const nmos::resource& resource, const web::json::array& target_role_path, const web::json::array& property_values, bool recurse, bool validate, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor)> modify_rebuildable_block_handler;
28+
}
29+
30+
#endif
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include "nmos/configuration_methods.h"
2+
3+
#include <boost/range/adaptor/filtered.hpp>
4+
#include "cpprest/json_utils.h"
5+
#include "nmos/configuration_handlers.h"
6+
#include "nmos/configuration_utils.h"
7+
#include "nmos/control_protocol_resource.h"
8+
#include "nmos/control_protocol_resources.h"
9+
#include "nmos/control_protocol_state.h"
10+
#include "nmos/control_protocol_utils.h"
11+
#include "nmos/slog.h"
12+
13+
namespace nmos
14+
{
15+
namespace details
16+
{
17+
web::json::value make_property_value_holders(const nmos::resource& resource, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor)
18+
{
19+
using web::json::value;
20+
21+
value property_value_holders = value::array();
22+
23+
nmos::nc_class_id class_id = nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data));
24+
25+
// make NcPropertyValueHolder objects
26+
while (!class_id.empty())
27+
{
28+
const auto& control_class_descriptor = get_control_protocol_class_descriptor(class_id);
29+
30+
for (const auto& property_descriptor : control_class_descriptor.property_descriptors.as_array())
31+
{
32+
value property_value_holder = nmos::details::make_nc_property_value_holder(nmos::details::parse_nc_property_id(nmos::fields::nc::id(property_descriptor)), nmos::fields::nc::name(property_descriptor), nmos::fields::nc::type_name(property_descriptor), nmos::fields::nc::is_read_only(property_descriptor), resource.data.at(nmos::fields::nc::name(property_descriptor)));
33+
34+
web::json::push_back(property_value_holders, property_value_holder);
35+
}
36+
class_id.pop_back();
37+
}
38+
return property_value_holders;
39+
}
40+
41+
void populate_object_property_holder(const nmos::resources& resources, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, const nmos::resource& resource, bool recurse, web::json::value& object_properties_holders)
42+
{
43+
using web::json::value;
44+
45+
// Get property_value_holders for this resource
46+
const auto& property_value_holders = make_property_value_holders(resource, get_control_protocol_class_descriptor).as_array();
47+
48+
const auto role_path = get_role_path(resources, resource);
49+
50+
auto object_properties_holder = nmos::details::make_nc_object_properties_holder(role_path, property_value_holders, nmos::fields::nc::is_rebuildable(resource.data));
51+
52+
web::json::push_back(object_properties_holders, object_properties_holder);
53+
54+
// Recurse into members...if we want to...and the object has them
55+
if (recurse && nmos::nc::is_block(nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data))))
56+
{
57+
if (resource.data.has_field(nmos::fields::nc::members))
58+
{
59+
const auto& members = nmos::fields::nc::members(resource.data);
60+
61+
for (const auto& member : members)
62+
{
63+
const auto& found = find_resource(resources, utility::s2us(std::to_string(nmos::fields::nc::oid(member))));
64+
65+
if (resources.end() != found)
66+
{
67+
populate_object_property_holder(resources, get_control_protocol_class_descriptor, *found, recurse, object_properties_holders);
68+
}
69+
}
70+
}
71+
}
72+
}
73+
74+
std::size_t generate_validation_fingerprint(const nmos::resources& resources, const nmos::resource& resource)
75+
{
76+
// Generate a hash based on structure of the Device Model
77+
size_t hash(0);
78+
79+
nmos::nc_class_id class_id = nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data));
80+
81+
boost::hash_combine(hash, class_id);
82+
boost::hash_combine(hash, nmos::fields::nc::role(resource.data));
83+
84+
// Recurse into members...if we want to...and the object has them
85+
if (nmos::nc::is_block(nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data))))
86+
{
87+
if (resource.data.has_field(nmos::fields::nc::members))
88+
{
89+
const auto& members = nmos::fields::nc::members(resource.data);
90+
91+
// Generate hash for block members
92+
for (const auto& member : members)
93+
{
94+
const auto& oid = nmos::fields::nc::oid(member);
95+
const auto& found = find_resource(resources, utility::s2us(std::to_string(oid)));
96+
if (resources.end() != found)
97+
{
98+
size_t sub_hash = generate_validation_fingerprint(resources, *found);
99+
boost::hash_combine(hash, sub_hash);
100+
}
101+
}
102+
}
103+
}
104+
105+
return hash;
106+
}
107+
}
108+
109+
web::json::value get_properties_by_path(const nmos::resources& resources, const nmos::resource& resource, bool recurse, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor)
110+
{
111+
using web::json::value;
112+
using web::json::value_of;
113+
114+
value object_properties_holders = value::array();
115+
116+
details::populate_object_property_holder(resources, get_control_protocol_class_descriptor, resource, recurse, object_properties_holders);
117+
118+
size_t validation_fingerprint = details::generate_validation_fingerprint(resources, resource);
119+
120+
utility::ostringstream_t ss;
121+
ss << validation_fingerprint;
122+
123+
auto bulk_values_holder = nmos::details::make_nc_bulk_values_holder(ss.str(), object_properties_holders);
124+
125+
return nmos::details::make_nc_method_result({ nmos::nc_method_status::ok }, bulk_values_holder);
126+
}
127+
128+
web::json::value validate_set_properties_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& backup_data_set, bool recurse, const web::json::value& restore_mode, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::filter_property_value_holders_handler filter_property_value_holders, nmos::modify_rebuildable_block_handler modify_rebuildable_block)
129+
{
130+
// Do something with validation fingerprint?
131+
const auto& object_properties_holders = nmos::fields::nc::values(backup_data_set);
132+
133+
const auto& object_properties_set_validation = apply_backup_data_set(resources, resource, object_properties_holders, recurse, restore_mode, true, get_control_protocol_class_descriptor, filter_property_value_holders, modify_rebuildable_block);
134+
135+
return nmos::details::make_nc_method_result({ nmos::nc_method_status::ok }, object_properties_set_validation);
136+
}
137+
138+
web::json::value set_properties_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& backup_data_set, bool recurse, const web::json::value& restore_mode, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::filter_property_value_holders_handler filter_property_value_holders, nmos::modify_rebuildable_block_handler modify_rebuildable_block)
139+
{
140+
// Do something with validation fingerprint?
141+
const auto& object_properties_holders = nmos::fields::nc::values(backup_data_set);
142+
143+
const auto& object_properties_set_validation = apply_backup_data_set(resources, resource, object_properties_holders, recurse, restore_mode, false, get_control_protocol_class_descriptor, filter_property_value_holders, modify_rebuildable_block);
144+
145+
return nmos::details::make_nc_method_result({ nmos::nc_method_status::ok }, object_properties_set_validation);
146+
}
147+
148+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef NMOS_CONFIGURATION_METHODS_H
2+
#define NMOS_CONFIGURATION_METHODS_H
3+
4+
#include "nmos/configuration_handlers.h"
5+
#include "nmos/control_protocol_handlers.h"
6+
#include "nmos/resources.h"
7+
8+
namespace slog
9+
{
10+
class base_gate;
11+
}
12+
13+
namespace nmos
14+
{
15+
struct control_protocol_resource;
16+
17+
// Implementation of IS-14 function for creating backup dataset from a Device Model
18+
web::json::value get_properties_by_path(const nmos::resources& resources, const nmos::resource& resource, bool recurse, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor);
19+
20+
web::json::value validate_set_properties_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& backup_data_set, bool recurse, const web::json::value& restore_mode, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::filter_property_value_holders_handler filter_property_value_holders, nmos::modify_rebuildable_block_handler modify_rebuildable_block);
21+
22+
web::json::value set_properties_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& backup_data_set, bool recurse, const web::json::value& restore_mode, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::filter_property_value_holders_handler filter_property_value_holders, nmos::modify_rebuildable_block_handler modify_rebuildable_block);
23+
}
24+
25+
#endif
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "nmos/configuration_resources.h"
2+
3+
#include "cpprest/json_utils.h"
4+
#include "nmos/control_protocol_resource.h"
5+
#include "nmos/slog.h"
6+
7+
namespace nmos
8+
{
9+
web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const web::json::array& notices, const utility::string_t& status_message)
10+
{
11+
return details::make_nc_object_properties_set_validation(role_path, status, notices, web::json::value::string(status_message));
12+
}
13+
14+
web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const web::json::array& notices)
15+
{
16+
return details::make_nc_object_properties_set_validation(role_path, status, notices, web::json::value::null());
17+
}
18+
19+
web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status)
20+
{
21+
return details::make_nc_object_properties_set_validation(role_path, status, web::json::value::array().as_array(), web::json::value::null());
22+
}
23+
24+
web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const utility::string_t& status_message)
25+
{
26+
return details::make_nc_object_properties_set_validation(role_path, status, web::json::value::array().as_array(), web::json::value::string(status_message));
27+
}
28+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef NMOS_CONFIGURATION_RESOURCES_H
2+
#define NMOS_CONFIGURATION_RESOURCES_H
3+
4+
#include "nmos/control_protocol_typedefs.h"
5+
#include "nmos/resources.h"
6+
7+
namespace nmos
8+
{
9+
web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const web::json::array& notices, const utility::string_t& status_message);
10+
11+
web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const web::json::array& notices);
12+
13+
web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status);
14+
15+
web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const utility::string_t& status_message);
16+
}
17+
18+
#endif

0 commit comments

Comments
 (0)