Skip to content

Commit 674bb36

Browse files
committed
More flexible default implementation of annotation_patch_merger
1 parent 9cd8985 commit 674bb36

File tree

3 files changed

+45
-18
lines changed

3 files changed

+45
-18
lines changed

Development/nmos-cpp-node/node_implementation.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,13 +1270,23 @@ nmos::channelmapping_activation_handler make_node_implementation_channelmapping_
12701270
}
12711271

12721272
// Example Annotation API patch callback to update resource labels, descriptions and tags
1273-
nmos::annotation_patch_merger make_node_implementation_annotation_patch_merger(slog::base_gate& gate)
1273+
nmos::annotation_patch_merger make_node_implementation_annotation_patch_merger(const nmos::settings& settings, slog::base_gate& gate)
12741274
{
1275-
return [&gate](const nmos::resource& resource, web::json::value& value, const web::json::value& patch)
1275+
using web::json::value;
1276+
using web::json::value_of;
1277+
1278+
return [&settings, &gate](const nmos::resource& resource, web::json::value& value, const web::json::value& patch)
12761279
{
12771280
const std::pair<nmos::id, nmos::type> id_type{ resource.id, resource.type };
12781281
slog::log<slog::severities::info>(gate, SLOG_FLF) << nmos::stash_category(impl::categories::node_implementation) << "Updating " << id_type;
1279-
nmos::details::merge_annotation_patch(value, patch);
1282+
// this example uses the specified tags for node and device resources as defaults
1283+
const auto default_tags
1284+
= id_type.second == nmos::types::node ? impl::fields::node_tags(settings)
1285+
: id_type.second == nmos::types::device ? impl::fields::device_tags(settings)
1286+
: value::object();
1287+
// and uses the default predicate for read-only tags
1288+
nmos::details::merge_annotation_patch(value, patch, &nmos::details::is_read_only_tag, value_of({ { nmos::fields::tags, default_tags } }));
1289+
// this example does not save the new values to persistent storage or e.g. reject values that are too large
12801290
};
12811291
}
12821292

@@ -1434,5 +1444,5 @@ nmos::experimental::node_implementation make_node_implementation(nmos::node_mode
14341444
.on_connection_activated(make_node_implementation_connection_activation_handler(model, gate))
14351445
.on_validate_channelmapping_output_map(make_node_implementation_map_validator()) // may be omitted if not required
14361446
.on_channelmapping_activated(make_node_implementation_channelmapping_activation_handler(gate))
1437-
.on_merge_annotation_patch(make_node_implementation_annotation_patch_merger(gate)); // may be omitted if not required
1447+
.on_merge_annotation_patch(make_node_implementation_annotation_patch_merger(model.settings, gate)); // may be omitted if not required
14381448
}

Development/nmos/annotation_api.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,35 @@ namespace nmos
6767

6868
namespace details
6969
{
70+
// BCP-002-01 Group Hint tag and BCP-002-02 Asset Distinguishing Information tags are read-only
71+
// all other tags are read/write
7072
bool is_read_only_tag(const utility::string_t& key)
7173
{
7274
return boost::algorithm::starts_with(key, U("urn:x-nmos:tag:asset:"))
7375
|| boost::algorithm::starts_with(key, U("urn:x-nmos:tag:grouphint/"));
7476
}
7577

76-
void merge_annotation_patch(web::json::value& value, const web::json::value& patch)
78+
const web::json::field_as_string_or default_label{ nmos::fields::label.key, U("") };
79+
const web::json::field_as_string_or default_description{ nmos::fields::description.key, U("") };
80+
const web::json::field_as_value_or default_tags{ nmos::fields::tags.key, web::json::value::object() };
81+
82+
void merge_annotation_patch(web::json::value& value, const web::json::value& patch, annotation_tag_predicate is_read_only_tag, const web::json::value& default_value)
7783
{
7884
// reject changes to read-ony tags
7985

8086
if (patch.has_object_field(nmos::fields::tags))
8187
{
8288
const auto& tags = nmos::fields::tags(patch);
83-
auto patch_readonly = std::find_if(tags.begin(), tags.end(), [](const std::pair<utility::string_t, web::json::value>& field)
89+
auto patch_readonly = std::find_if(tags.begin(), tags.end(), [&](const std::pair<utility::string_t, web::json::value>& field)
8490
{
8591
return is_read_only_tag(field.first);
8692
});
8793
if (tags.end() != patch_readonly) throw std::runtime_error("cannot patch read-only tag: " + utility::us2s(patch_readonly->first));
8894
}
8995

90-
// save existing read-only tags
96+
// save existing read-only tags (so that read-only tags don't need to be included in default_value)
9197

92-
auto readonly_tags = web::json::value_from_fields(nmos::fields::tags(value) | boost::adaptors::filtered([](const std::pair<utility::string_t, web::json::value>& field)
98+
auto readonly_tags = web::json::value_from_fields(nmos::fields::tags(value) | boost::adaptors::filtered([&](const std::pair<utility::string_t, web::json::value>& field)
9399
{
94100
return is_read_only_tag(field.first);
95101
}));
@@ -100,16 +106,21 @@ namespace nmos
100106

101107
// apply defaults to properties that have been reset
102108

103-
web::json::insert(value, std::make_pair(nmos::fields::label, U("")));
104-
web::json::insert(value, std::make_pair(nmos::fields::description, U("")));
109+
web::json::insert(value, std::make_pair(nmos::fields::label, details::default_label(default_value)));
110+
web::json::insert(value, std::make_pair(nmos::fields::description, details::default_description(default_value)));
105111
web::json::insert(value, std::make_pair(nmos::fields::tags, readonly_tags));
112+
auto& tags = value.at(nmos::fields::tags);
113+
for (const auto& default_tag : details::default_tags(default_value).as_object())
114+
{
115+
web::json::insert(tags, default_tag);
116+
}
106117
}
107118

108119
void assign_annotation_patch(web::json::value& value, web::json::value&& patch)
109120
{
110-
if (value.has_string_field(nmos::fields::label)) value[nmos::fields::label] = std::move(patch.at(nmos::fields::label));
111-
if (value.has_string_field(nmos::fields::description)) value[nmos::fields::description] = std::move(patch.at(nmos::fields::description));
112-
if (value.has_object_field(nmos::fields::tags)) value[nmos::fields::tags] = std::move(patch.at(nmos::fields::tags));
121+
if (patch.has_string_field(nmos::fields::label)) value[nmos::fields::label] = std::move(patch.at(nmos::fields::label));
122+
if (patch.has_string_field(nmos::fields::description)) value[nmos::fields::description] = std::move(patch.at(nmos::fields::description));
123+
if (patch.has_object_field(nmos::fields::tags)) value[nmos::fields::tags] = std::move(patch.at(nmos::fields::tags));
113124
}
114125

115126
void handle_annotation_patch(nmos::resources& resources, const nmos::resource& resource, const web::json::value& patch, const nmos::annotation_patch_merger& merge_patch, slog::base_gate& gate)

Development/nmos/annotation_api.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,19 @@ namespace nmos
3131

3232
namespace details
3333
{
34-
void merge_annotation_patch(web::json::value& value, const web::json::value& patch);
34+
typedef std::function<bool(const utility::string_t& name)> annotation_tag_predicate;
35+
36+
// BCP-002-01 Group Hint tag and BCP-002-02 Asset Distinguishing Information tags are read-only
37+
// all other tags are read/write
38+
bool is_read_only_tag(const utility::string_t& name);
39+
40+
// this function merges the patch into the value with few additional constraints
41+
// when any fields are reset using null, default values are applied if specified or
42+
// read-write tags are removed, and label and description are set to the empty string
43+
void merge_annotation_patch(web::json::value& value, const web::json::value& patch, annotation_tag_predicate is_read_only_tag = &nmos::details::is_read_only_tag, const web::json::value& default_value = {});
3544
}
3645

37-
// this function merges the patch into the value with few additional constraints
38-
// i.e. label, description and all tags are read/write except Group Hint and Asset Distinguishing Information
39-
// when reset using null, tags are removed, and label and description are set to the empty string
40-
// (this is the default patch merger)
46+
// this is the default patch merger
4147
inline void merge_annotation_patch(const nmos::resource& resource, web::json::value& value, const web::json::value& patch)
4248
{
4349
details::merge_annotation_patch(value, patch);

0 commit comments

Comments
 (0)