From 9cd89854d2e9d99b0ea7d35cd280cfe432c14d7c Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley Date: Fri, 19 May 2023 17:31:07 +0100 Subject: [PATCH] Rename Read/Write Node API to Annotation API (cf. https://github.com/AMWA-TV/is-13/pull/19) --- Development/cmake/NmosCppLibraries.cmake | 7 +- Development/cmake/NmosCppTest.cmake | 2 +- Development/nmos-cpp-node/config.json | 2 +- .../nmos-cpp-node/node_implementation.cpp | 8 +- .../{rwnode_api.cpp => annotation_api.cpp} | 86 ++++++++++--------- .../nmos/{rwnode_api.h => annotation_api.h} | 22 ++--- Development/nmos/api_utils.h | 4 +- Development/nmos/is13_schemas/is13_schemas.h | 3 +- Development/nmos/json_schema.cpp | 6 +- Development/nmos/json_schema.h | 2 +- Development/nmos/node_resource.cpp | 12 +-- Development/nmos/node_server.cpp | 4 +- Development/nmos/node_server.h | 6 +- Development/nmos/settings.cpp | 2 +- Development/nmos/settings.h | 2 +- ...e_api_test.cpp => annotation_api_test.cpp} | 16 ++-- Development/third_party/README.md | 2 +- Development/third_party/is-13/README.md | 4 +- .../APIs/schemas/annotationapi-base.json | 15 ++++ ...base.json => annotationapi-node-base.json} | 4 +- .../APIs/schemas/resource_core_patch.json | 2 +- README.md | 2 +- 22 files changed, 118 insertions(+), 95 deletions(-) rename Development/nmos/{rwnode_api.cpp => annotation_api.cpp} (69%) rename Development/nmos/{rwnode_api.h => annotation_api.h} (53%) rename Development/nmos/test/{rwnode_api_test.cpp => annotation_api_test.cpp} (86%) create mode 100644 Development/third_party/is-13/v1.0-dev/APIs/schemas/annotationapi-base.json rename Development/third_party/is-13/v1.0-dev/APIs/schemas/{rwnodeapi-base.json => annotationapi-node-base.json} (72%) diff --git a/Development/cmake/NmosCppLibraries.cmake b/Development/cmake/NmosCppLibraries.cmake index 5f266c032..ecf845a14 100644 --- a/Development/cmake/NmosCppLibraries.cmake +++ b/Development/cmake/NmosCppLibraries.cmake @@ -695,11 +695,12 @@ set(NMOS_IS13_SCHEMAS_HEADERS set(NMOS_IS13_V1_0_TAG v1.0-dev) set(NMOS_IS13_V1_0_SCHEMAS_JSON + third_party/is-13/${NMOS_IS13_V1_0_TAG}/APIs/schemas/annotationapi-base.json + third_party/is-13/${NMOS_IS13_V1_0_TAG}/APIs/schemas/annotationapi-node-base.json third_party/is-13/${NMOS_IS13_V1_0_TAG}/APIs/schemas/error.json third_party/is-13/${NMOS_IS13_V1_0_TAG}/APIs/schemas/resource_core.json third_party/is-13/${NMOS_IS13_V1_0_TAG}/APIs/schemas/resource_core_patch.json third_party/is-13/${NMOS_IS13_V1_0_TAG}/APIs/schemas/resource_cores.json - third_party/is-13/${NMOS_IS13_V1_0_TAG}/APIs/schemas/rwnodeapi-base.json ) set(NMOS_IS13_SCHEMAS_JSON_MATCH "third_party/is-13/([^/]+)/APIs/schemas/([^;]+)\\.json") @@ -813,6 +814,7 @@ set(NMOS_CPP_CPPREST_DETAILS_HEADERS set(NMOS_CPP_NMOS_SOURCES nmos/activation_utils.cpp nmos/admin_ui.cpp + nmos/annotation_api.cpp nmos/api_downgrade.cpp nmos/api_utils.cpp nmos/capabilities.cpp @@ -864,7 +866,6 @@ set(NMOS_CPP_NMOS_SOURCES nmos/registry_server.cpp nmos/resource.cpp nmos/resources.cpp - nmos/rwnode_api.cpp nmos/schemas_api.cpp nmos/sdp_utils.cpp nmos/server.cpp @@ -879,6 +880,7 @@ set(NMOS_CPP_NMOS_HEADERS nmos/activation_mode.h nmos/activation_utils.h nmos/admin_ui.h + nmos/annotation_api.h nmos/api_downgrade.h nmos/api_utils.h nmos/api_version.h @@ -958,7 +960,6 @@ set(NMOS_CPP_NMOS_HEADERS nmos/registry_server.h nmos/resource.h nmos/resources.h - nmos/rwnode_api.h nmos/schemas_api.h nmos/sdp_utils.h nmos/server.h diff --git a/Development/cmake/NmosCppTest.cmake b/Development/cmake/NmosCppTest.cmake index 6141ea40e..f33f98e40 100644 --- a/Development/cmake/NmosCppTest.cmake +++ b/Development/cmake/NmosCppTest.cmake @@ -39,6 +39,7 @@ set(NMOS_CPP_TEST_MDNS_TEST_HEADERS ) set(NMOS_CPP_TEST_NMOS_TEST_SOURCES + nmos/test/annotation_api_test.cpp nmos/test/api_utils_test.cpp nmos/test/capabilities_test.cpp nmos/test/channels_test.cpp @@ -46,7 +47,6 @@ set(NMOS_CPP_TEST_NMOS_TEST_SOURCES nmos/test/event_type_test.cpp nmos/test/json_validator_test.cpp nmos/test/paging_utils_test.cpp - nmos/test/rwnode_api_test.cpp nmos/test/query_api_test.cpp nmos/test/sdp_utils_test.cpp nmos/test/system_resources_test.cpp diff --git a/Development/nmos-cpp-node/config.json b/Development/nmos-cpp-node/config.json index 715b72386..f9a8b4814 100644 --- a/Development/nmos-cpp-node/config.json +++ b/Development/nmos-cpp-node/config.json @@ -135,7 +135,7 @@ //"events_port": 3216, //"events_ws_port": 3217, //"channelmapping_port": 3215, - //"rwnode_port": 3212, + //"annotation_port": 3212, // system_port [node]: used to construct request URLs for the System API (if not discovered via DNS-SD) //"system_port": 10641, diff --git a/Development/nmos-cpp-node/node_implementation.cpp b/Development/nmos-cpp-node/node_implementation.cpp index 6104944ff..85df5bca5 100644 --- a/Development/nmos-cpp-node/node_implementation.cpp +++ b/Development/nmos-cpp-node/node_implementation.cpp @@ -1269,14 +1269,14 @@ nmos::channelmapping_activation_handler make_node_implementation_channelmapping_ }; } -// Example Read/Write Node API patch callback to update resource labels, descriptions and tags -nmos::rwnode_patch_merger make_node_implementation_rwnode_patch_merger(slog::base_gate& gate) +// Example Annotation API patch callback to update resource labels, descriptions and tags +nmos::annotation_patch_merger make_node_implementation_annotation_patch_merger(slog::base_gate& gate) { return [&gate](const nmos::resource& resource, web::json::value& value, const web::json::value& patch) { const std::pair id_type{ resource.id, resource.type }; slog::log(gate, SLOG_FLF) << nmos::stash_category(impl::categories::node_implementation) << "Updating " << id_type; - nmos::details::merge_rwnode_patch(value, patch); + nmos::details::merge_annotation_patch(value, patch); }; } @@ -1434,5 +1434,5 @@ nmos::experimental::node_implementation make_node_implementation(nmos::node_mode .on_connection_activated(make_node_implementation_connection_activation_handler(model, gate)) .on_validate_channelmapping_output_map(make_node_implementation_map_validator()) // may be omitted if not required .on_channelmapping_activated(make_node_implementation_channelmapping_activation_handler(gate)) - .on_merge_rwnode_patch(make_node_implementation_rwnode_patch_merger(gate)); // may be omitted if not required + .on_merge_annotation_patch(make_node_implementation_annotation_patch_merger(gate)); // may be omitted if not required } diff --git a/Development/nmos/rwnode_api.cpp b/Development/nmos/annotation_api.cpp similarity index 69% rename from Development/nmos/rwnode_api.cpp rename to Development/nmos/annotation_api.cpp index 42018f0c7..0cf638672 100644 --- a/Development/nmos/rwnode_api.cpp +++ b/Development/nmos/annotation_api.cpp @@ -1,4 +1,4 @@ -#include "nmos/rwnode_api.h" +#include "nmos/annotation_api.h" #include #include @@ -11,39 +11,39 @@ namespace nmos { - web::http::experimental::listener::api_router make_unmounted_rwnode_api(nmos::model& model, nmos::rwnode_patch_merger merge_patch, slog::base_gate& gate); + web::http::experimental::listener::api_router make_unmounted_annotation_api(nmos::model& model, nmos::annotation_patch_merger merge_patch, slog::base_gate& gate); - web::http::experimental::listener::api_router make_rwnode_api(nmos::model& model, nmos::rwnode_patch_merger merge_patch, slog::base_gate& gate) + web::http::experimental::listener::api_router make_annotation_api(nmos::model& model, nmos::annotation_patch_merger merge_patch, slog::base_gate& gate) { using namespace web::http::experimental::listener::api_router_using_declarations; - api_router rwnode_api; + api_router annotation_api; - rwnode_api.support(U("/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) + annotation_api.support(U("/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) { set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("x-nmos/") }, req, res)); return pplx::task_from_result(true); }); - rwnode_api.support(U("/x-nmos/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) + annotation_api.support(U("/x-nmos/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) { - set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("rwnode/") }, req, res)); + set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("annotation/") }, req, res)); return pplx::task_from_result(true); }); const auto versions = with_read_lock(model.mutex, [&model] { return nmos::is13_versions::from_settings(model.settings); }); - rwnode_api.support(U("/x-nmos/") + nmos::patterns::rwnode_api.pattern + U("/?"), methods::GET, [versions](http_request req, http_response res, const string_t&, const route_parameters&) + annotation_api.support(U("/x-nmos/") + nmos::patterns::annotation_api.pattern + U("/?"), methods::GET, [versions](http_request req, http_response res, const string_t&, const route_parameters&) { set_reply(res, status_codes::OK, nmos::make_sub_routes_body(nmos::make_api_version_sub_routes(versions), req, res)); return pplx::task_from_result(true); }); - rwnode_api.mount(U("/x-nmos/") + nmos::patterns::rwnode_api.pattern + U("/") + nmos::patterns::version.pattern, make_unmounted_rwnode_api(model, std::move(merge_patch), gate)); + annotation_api.mount(U("/x-nmos/") + nmos::patterns::annotation_api.pattern + U("/") + nmos::patterns::version.pattern, make_unmounted_annotation_api(model, std::move(merge_patch), gate)); - return rwnode_api; + return annotation_api; } - web::json::value make_rwnode_patch(const nmos::resource& resource) + web::json::value make_annotation_patch(const nmos::resource& resource) { using web::json::value_of; return value_of({ @@ -53,7 +53,7 @@ namespace nmos }); } - web::json::value make_rwnode_response(const nmos::resource& resource) + web::json::value make_annotation_response(const nmos::resource& resource) { using web::json::value_of; return value_of({ @@ -73,7 +73,7 @@ namespace nmos || boost::algorithm::starts_with(key, U("urn:x-nmos:tag:grouphint/")); } - void merge_rwnode_patch(web::json::value& value, const web::json::value& patch) + void merge_annotation_patch(web::json::value& value, const web::json::value& patch) { // reject changes to read-ony tags @@ -105,16 +105,16 @@ namespace nmos web::json::insert(value, std::make_pair(nmos::fields::tags, readonly_tags)); } - void assign_rwnode_patch(web::json::value& value, web::json::value&& patch) + void assign_annotation_patch(web::json::value& value, web::json::value&& patch) { if (value.has_string_field(nmos::fields::label)) value[nmos::fields::label] = std::move(patch.at(nmos::fields::label)); if (value.has_string_field(nmos::fields::description)) value[nmos::fields::description] = std::move(patch.at(nmos::fields::description)); if (value.has_object_field(nmos::fields::tags)) value[nmos::fields::tags] = std::move(patch.at(nmos::fields::tags)); } - void handle_rwnode_patch(nmos::resources& resources, const nmos::resource& resource, const web::json::value& patch, const nmos::rwnode_patch_merger& merge_patch, slog::base_gate& gate) + 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) { - auto merged = nmos::make_rwnode_patch(resource); + auto merged = nmos::make_annotation_patch(resource); try { if (merge_patch) @@ -123,7 +123,7 @@ namespace nmos } else { - nmos::merge_rwnode_patch(resource, merged, patch); + nmos::merge_annotation_patch(resource, merged, patch); } } catch (const web::json::json_exception& e) @@ -137,28 +137,34 @@ namespace nmos modify_resource(resources, resource.id, [&merged](nmos::resource& resource) { resource.data[nmos::fields::version] = web::json::value::string(nmos::make_version()); - details::assign_rwnode_patch(resource.data, std::move(merged)); + details::assign_annotation_patch(resource.data, std::move(merged)); }); } } - web::http::experimental::listener::api_router make_unmounted_rwnode_api(nmos::model& model, nmos::rwnode_patch_merger merge_patch, slog::base_gate& gate_) + web::http::experimental::listener::api_router make_unmounted_annotation_api(nmos::model& model, nmos::annotation_patch_merger merge_patch, slog::base_gate& gate_) { using namespace web::http::experimental::listener::api_router_using_declarations; - api_router rwnode_api; + api_router annotation_api; // check for supported API version const auto versions = with_read_lock(model.mutex, [&model] { return nmos::is13_versions::from_settings(model.settings); }); - rwnode_api.support(U(".*"), details::make_api_version_handler(versions, gate_)); + annotation_api.support(U(".*"), details::make_api_version_handler(versions, gate_)); - rwnode_api.support(U("/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) + annotation_api.support(U("/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) + { + set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("node/") }, req, res)); + return pplx::task_from_result(true); + }); + + annotation_api.support(U("/node/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) { set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("self/"), U("devices/"), U("sources/"), U("flows/"), U("senders/"), U("receivers/") }, req, res)); return pplx::task_from_result(true); }); - rwnode_api.support(U("/self/?"), methods::GET, [&model, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + annotation_api.support(U("/node/self/?"), methods::GET, [&model, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) { nmos::api_gate gate(gate_, req, parameters); auto lock = model.read_lock(); @@ -168,12 +174,12 @@ namespace nmos if (resources.end() != resource) { slog::log(gate, SLOG_FLF) << "Returning self resource: " << resource->id; - set_reply(res, status_codes::OK, nmos::make_rwnode_response(*resource)); + set_reply(res, status_codes::OK, nmos::make_annotation_response(*resource)); } else { slog::log(gate, SLOG_FLF) << "Self resource not found!"; - set_reply(res, status_codes::InternalError); // rather than Not Found, since the Read/Write Node API doesn't allow a 404 response + set_reply(res, status_codes::InternalError); // rather than Not Found, since the Annotation API doesn't allow a 404 response } return pplx::task_from_result(true); @@ -182,10 +188,10 @@ namespace nmos const web::json::experimental::json_validator validator { nmos::experimental::load_json_schema, - boost::copy_range>(versions | boost::adaptors::transformed(experimental::make_rwnodeapi_resource_core_patch_request_schema_uri)) + boost::copy_range>(versions | boost::adaptors::transformed(experimental::make_annotationapi_resource_core_patch_request_schema_uri)) }; - rwnode_api.support(U("/self/?"), methods::PATCH, [&model, validator, merge_patch, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + annotation_api.support(U("/node/self/?"), methods::PATCH, [&model, validator, merge_patch, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) { nmos::api_gate gate(gate_, req, parameters); @@ -193,7 +199,7 @@ namespace nmos { const nmos::api_version version = nmos::parse_api_version(parameters.at(nmos::patterns::version.name)); - validator.validate(body, experimental::make_rwnodeapi_resource_core_patch_request_schema_uri(version)); + validator.validate(body, experimental::make_annotationapi_resource_core_patch_request_schema_uri(version)); auto lock = model.write_lock(); auto& resources = model.node_resources; @@ -203,23 +209,23 @@ namespace nmos { slog::log(gate, SLOG_FLF) << "Patching self resource: " << resource->id; - details::handle_rwnode_patch(resources, *resource, body, merge_patch, gate); + details::handle_annotation_patch(resources, *resource, body, merge_patch, gate); - set_reply(res, status_codes::OK, nmos::make_rwnode_response(*resource)); + set_reply(res, status_codes::OK, nmos::make_annotation_response(*resource)); model.notify(); } else { slog::log(gate, SLOG_FLF) << "Self resource not found!"; - set_reply(res, status_codes::InternalError); // rather than Not Found, since the Read/Write Node API doesn't allow a 404 response + set_reply(res, status_codes::InternalError); // rather than Not Found, since the Annotation API doesn't allow a 404 response } return true; }); }); - rwnode_api.support(U("/") + nmos::patterns::subresourceType.pattern + U("/?"), methods::GET, [&model, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + annotation_api.support(U("/node/") + nmos::patterns::subresourceType.pattern + U("/?"), methods::GET, [&model, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) { nmos::api_gate gate(gate_, req, parameters); auto lock = model.read_lock(); @@ -235,7 +241,7 @@ namespace nmos web::json::serialize_array(resources | boost::adaptors::filtered(match) | boost::adaptors::transformed( - [&count](const nmos::resources::value_type& resource) { ++count; return nmos::make_rwnode_response(resource); } + [&count](const nmos::resources::value_type& resource) { ++count; return nmos::make_annotation_response(resource); } )), web::http::details::mime_types::application_json); @@ -244,7 +250,7 @@ namespace nmos return pplx::task_from_result(true); }); - rwnode_api.support(U("/") + nmos::patterns::subresourceType.pattern + U("/") + nmos::patterns::resourceId.pattern + U("/?"), methods::GET, [&model, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + annotation_api.support(U("/node/") + nmos::patterns::subresourceType.pattern + U("/") + nmos::patterns::resourceId.pattern + U("/?"), methods::GET, [&model, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) { nmos::api_gate gate(gate_, req, parameters); auto lock = model.read_lock(); @@ -258,7 +264,7 @@ namespace nmos if (resources.end() != resource) { slog::log(gate, SLOG_FLF) << "Returning " << id_type; - set_reply(res, status_codes::OK, nmos::make_rwnode_response(*resource)); + set_reply(res, status_codes::OK, nmos::make_annotation_response(*resource)); } else { @@ -268,7 +274,7 @@ namespace nmos return pplx::task_from_result(true); }); - rwnode_api.support(U("/") + nmos::patterns::subresourceType.pattern + U("/") + nmos::patterns::resourceId.pattern + U("/?"), methods::PATCH, [&model, validator, merge_patch, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + annotation_api.support(U("/node/") + nmos::patterns::subresourceType.pattern + U("/") + nmos::patterns::resourceId.pattern + U("/?"), methods::PATCH, [&model, validator, merge_patch, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) { nmos::api_gate gate(gate_, req, parameters); @@ -276,7 +282,7 @@ namespace nmos { const nmos::api_version version = nmos::parse_api_version(parameters.at(nmos::patterns::version.name)); - validator.validate(body, experimental::make_rwnodeapi_resource_core_patch_request_schema_uri(version)); + validator.validate(body, experimental::make_annotationapi_resource_core_patch_request_schema_uri(version)); auto lock = model.write_lock(); auto& resources = model.node_resources; @@ -290,9 +296,9 @@ namespace nmos { slog::log(gate, SLOG_FLF) << "Patching " << id_type; - details::handle_rwnode_patch(resources, *resource, body, merge_patch, gate); + details::handle_annotation_patch(resources, *resource, body, merge_patch, gate); - set_reply(res, status_codes::OK, nmos::make_rwnode_response(*resource)); + set_reply(res, status_codes::OK, nmos::make_annotation_response(*resource)); model.notify(); } @@ -305,6 +311,6 @@ namespace nmos }); }); - return rwnode_api; + return annotation_api; } } diff --git a/Development/nmos/rwnode_api.h b/Development/nmos/annotation_api.h similarity index 53% rename from Development/nmos/rwnode_api.h rename to Development/nmos/annotation_api.h index 5b57a6ffe..c6586a8f4 100644 --- a/Development/nmos/rwnode_api.h +++ b/Development/nmos/annotation_api.h @@ -8,39 +8,39 @@ namespace slog class base_gate; } -// Read/Write Node API implementation +// Annotation API implementation // See https://specs.amwa.tv/is-13/branches/v1.0-dev/APIs/ReadWriteNodeAPI.html namespace nmos { struct model; struct resource; - // Read/Write Node API callbacks + // Annotation API callbacks - // a rwnode_patch_merger validates the specified patch data for the specified IS-04 resource and updates the object to be merged + // an annotation_patch_merger validates the specified patch data for the specified IS-04 resource and updates the object to be merged // or may throw std::runtime_error, which will be mapped to a 500 Internal Error status code with NMOS error "debug" information including the exception message - // (the default patch merger, nmos::merge_rwnode_patch, implements the minimum requirements) - typedef std::function rwnode_patch_merger; + // (the default patch merger, nmos::merge_annotation_patch, implements the minimum requirements) + typedef std::function annotation_patch_merger; - // Read/Write Node API factory functions + // Annotation API factory functions // callbacks from this function are called with the model locked, and may read but should not write directly to the model - web::http::experimental::listener::api_router make_rwnode_api(nmos::model& model, rwnode_patch_merger merge_patch, slog::base_gate& gate); + web::http::experimental::listener::api_router make_annotation_api(nmos::model& model, annotation_patch_merger merge_patch, slog::base_gate& gate); - // Helper functions for the Read/Write Node API callbacks + // Helper functions for the Annotation API callbacks namespace details { - void merge_rwnode_patch(web::json::value& value, const web::json::value& patch); + void merge_annotation_patch(web::json::value& value, const web::json::value& patch); } // this function merges the patch into the value with few additional constraints // i.e. label, description and all tags are read/write except Group Hint and Asset Distinguishing Information // when reset using null, tags are removed, and label and description are set to the empty string // (this is the default patch merger) - inline void merge_rwnode_patch(const nmos::resource& resource, web::json::value& value, const web::json::value& patch) + inline void merge_annotation_patch(const nmos::resource& resource, web::json::value& value, const web::json::value& patch) { - details::merge_rwnode_patch(value, patch); + details::merge_annotation_patch(value, patch); } } diff --git a/Development/nmos/api_utils.h b/Development/nmos/api_utils.h index 0b5b2d1ea..976d7f316 100644 --- a/Development/nmos/api_utils.h +++ b/Development/nmos/api_utils.h @@ -50,8 +50,8 @@ namespace nmos const route_pattern channelmapping_api = make_route_pattern(U("api"), U("channelmapping")); // IS-09 System API (originally specified in JT-NM TR-1001-1:2018 Annex A) const route_pattern system_api = make_route_pattern(U("api"), U("system")); - // IS-13 Read/Write Node API - const route_pattern rwnode_api = make_route_pattern(U("api"), U("rwnode")); + // IS-13 Annotation API + const route_pattern annotation_api = make_route_pattern(U("api"), U("annotation")); // API version pattern const route_pattern version = make_route_pattern(U("version"), U("v[0-9]+\\.[0-9]+")); diff --git a/Development/nmos/is13_schemas/is13_schemas.h b/Development/nmos/is13_schemas/is13_schemas.h index e6ff520f1..85396e8fb 100644 --- a/Development/nmos/is13_schemas/is13_schemas.h +++ b/Development/nmos/is13_schemas/is13_schemas.h @@ -9,11 +9,12 @@ namespace nmos { namespace v1_0_dev { + extern const char* annotationapi_base; + extern const char* annotationapi_node_base; extern const char* error; extern const char* resource_core; extern const char* resource_core_patch; extern const char* resource_cores; - extern const char* rwnodeapi_base; } } } diff --git a/Development/nmos/json_schema.cpp b/Development/nmos/json_schema.cpp index 4038f284e..2a4e6bbe0 100644 --- a/Development/nmos/json_schema.cpp +++ b/Development/nmos/json_schema.cpp @@ -142,7 +142,7 @@ namespace nmos using namespace nmos::is13_schemas::v1_0_dev; const utility::string_t tag(_XPLATSTR("v1.0-dev")); - const web::uri rwnodeapi_resource_core_patch_request_uri = make_schema_uri(tag, _XPLATSTR("resource_core_patch.json")); + const web::uri annotationapi_resource_core_patch_request_uri = make_schema_uri(tag, _XPLATSTR("resource_core_patch.json")); } } } @@ -413,9 +413,9 @@ namespace nmos return is08_schemas::v1_0::map_activations_post_request_uri; } - web::uri make_rwnodeapi_resource_core_patch_request_schema_uri(const nmos::api_version& version) + web::uri make_annotationapi_resource_core_patch_request_schema_uri(const nmos::api_version& version) { - return is13_schemas::v1_0::rwnodeapi_resource_core_patch_request_uri; + return is13_schemas::v1_0::annotationapi_resource_core_patch_request_uri; } // load the json schema for the specified base URI diff --git a/Development/nmos/json_schema.h b/Development/nmos/json_schema.h index e95348e05..7eda1598c 100644 --- a/Development/nmos/json_schema.h +++ b/Development/nmos/json_schema.h @@ -29,7 +29,7 @@ namespace nmos web::uri make_channelmappingapi_map_activations_post_request_schema_uri(const nmos::api_version& version); - web::uri make_rwnodeapi_resource_core_patch_request_schema_uri(const nmos::api_version& version); + web::uri make_annotationapi_resource_core_patch_request_schema_uri(const nmos::api_version& version); // load the json schema for the specified base URI web::json::value load_json_schema(const web::uri& id); diff --git a/Development/nmos/node_resource.cpp b/Development/nmos/node_resource.cpp index d68b84067..85f78efc6 100644 --- a/Development/nmos/node_resource.cpp +++ b/Development/nmos/node_resource.cpp @@ -44,20 +44,20 @@ namespace nmos data[U("services")] = value::array(); - if (0 <= nmos::fields::rwnode_port(settings)) + if (0 <= nmos::fields::annotation_port(settings)) { for (const auto& version : nmos::is13_versions::from_settings(settings)) { - auto rwnode_uri = web::uri_builder() + auto annotation_uri = web::uri_builder() .set_scheme(nmos::http_scheme(settings)) - .set_port(nmos::fields::rwnode_port(settings)) - .set_path(U("/x-nmos/rwnode/") + make_api_version(version)); - auto type = U("urn:x-nmos:service:rw-node/") + make_api_version(version); + .set_port(nmos::fields::annotation_port(settings)) + .set_path(U("/x-nmos/annotation/") + make_api_version(version)); + auto type = U("urn:x-nmos:service:annotation/") + make_api_version(version); for (const auto& host : hosts) { web::json::push_back(data[U("services")], value_of({ - { U("href"), rwnode_uri.set_host(host).to_uri().to_string() }, + { U("href"), annotation_uri.set_host(host).to_uri().to_string() }, { U("type"), type } })); } diff --git a/Development/nmos/node_server.cpp b/Development/nmos/node_server.cpp index 97848306c..7c92f38e8 100644 --- a/Development/nmos/node_server.cpp +++ b/Development/nmos/node_server.cpp @@ -10,7 +10,7 @@ #include "nmos/model.h" #include "nmos/node_api.h" #include "nmos/node_behaviour.h" -#include "nmos/rwnode_api.h" +#include "nmos/annotation_api.h" #include "nmos/server.h" #include "nmos/server_utils.h" #include "nmos/settings_api.h" @@ -52,7 +52,7 @@ namespace nmos nmos::node_api_target_handler target_handler = nmos::make_node_api_target_handler(node_model, node_implementation.load_ca_certificates, node_implementation.parse_transport_file, node_implementation.validate_staged); node_server.api_routers[{ {}, nmos::fields::node_port(node_model.settings) }].mount({}, nmos::make_node_api(node_model, target_handler, gate)); - node_server.api_routers[{ {}, nmos::fields::rwnode_port(node_model.settings) }].mount({}, nmos::make_rwnode_api(node_model, node_implementation.merge_rwnode_patch, gate)); + node_server.api_routers[{ {}, nmos::fields::annotation_port(node_model.settings) }].mount({}, nmos::make_annotation_api(node_model, node_implementation.merge_annotation_patch, gate)); node_server.api_routers[{ {}, nmos::experimental::fields::manifest_port(node_model.settings) }].mount({}, nmos::experimental::make_manifest_api(node_model, gate)); // Configure the Connection API diff --git a/Development/nmos/node_server.h b/Development/nmos/node_server.h index 379c9e3f0..bace14793 100644 --- a/Development/nmos/node_server.h +++ b/Development/nmos/node_server.h @@ -9,7 +9,7 @@ #include "nmos/node_behaviour.h" #include "nmos/node_system_behaviour.h" #include "nmos/ocsp_response_handler.h" -#include "nmos/rwnode_api.h" +#include "nmos/annotation_api.h" namespace nmos { @@ -57,7 +57,7 @@ namespace nmos node_implementation& on_connection_activated(nmos::connection_activation_handler connection_activated) { this->connection_activated = std::move(connection_activated); return *this; } node_implementation& on_validate_channelmapping_output_map(nmos::details::channelmapping_output_map_validator validate_map) { this->validate_map = std::move(validate_map); return *this; } node_implementation& on_channelmapping_activated(nmos::channelmapping_activation_handler channelmapping_activated) { this->channelmapping_activated = std::move(channelmapping_activated); return *this; } - node_implementation& on_merge_rwnode_patch(nmos::rwnode_patch_merger merge_rwnode_patch) { this->merge_rwnode_patch = std::move(merge_rwnode_patch); return *this; } + node_implementation& on_merge_annotation_patch(nmos::annotation_patch_merger merge_annotation_patch) { this->merge_annotation_patch = std::move(merge_annotation_patch); return *this; } node_implementation& on_get_ocsp_response(nmos::ocsp_response_handler get_ocsp_response) { this->get_ocsp_response = std::move(get_ocsp_response); return *this; } // deprecated, use on_validate_connection_resource_patch @@ -87,7 +87,7 @@ namespace nmos nmos::channelmapping_activation_handler channelmapping_activated; - nmos::rwnode_patch_merger merge_rwnode_patch; + nmos::annotation_patch_merger merge_annotation_patch; nmos::ocsp_response_handler get_ocsp_response; }; diff --git a/Development/nmos/settings.cpp b/Development/nmos/settings.cpp index 1b546cfd6..9c0fe67cc 100644 --- a/Development/nmos/settings.cpp +++ b/Development/nmos/settings.cpp @@ -70,7 +70,7 @@ namespace nmos if (registry) web::json::insert(settings, std::make_pair(nmos::fields::query_ws_port, ws_port)); if (registry) web::json::insert(settings, std::make_pair(nmos::fields::registration_port, http_port)); web::json::insert(settings, std::make_pair(nmos::fields::node_port, http_port)); - if (!registry) web::json::insert(settings, std::make_pair(nmos::fields::rwnode_port, http_port)); + if (!registry) web::json::insert(settings, std::make_pair(nmos::fields::annotation_port, http_port)); if (registry) web::json::insert(settings, std::make_pair(nmos::fields::system_port, http_port)); if (!registry) web::json::insert(settings, std::make_pair(nmos::fields::connection_port, http_port)); if (!registry) web::json::insert(settings, std::make_pair(nmos::fields::events_port, http_port)); diff --git a/Development/nmos/settings.h b/Development/nmos/settings.h index 02dae4d43..37229e978 100644 --- a/Development/nmos/settings.h +++ b/Development/nmos/settings.h @@ -137,7 +137,7 @@ namespace nmos const web::json::field_as_integer_or events_port{ U("events_port"), 3216 }; const web::json::field_as_integer_or events_ws_port{ U("events_ws_port"), 3217 }; const web::json::field_as_integer_or channelmapping_port{ U("channelmapping_port"), 3215 }; - const web::json::field_as_integer_or rwnode_port{ U("rwnode_port"), 3212 }; + const web::json::field_as_integer_or annotation_port{ U("annotation_port"), 3212 }; // system_port [node]: used to construct request URLs for the System API (if not discovered via DNS-SD) const web::json::field_as_integer_or system_port{ U("system_port"), 10641 }; diff --git a/Development/nmos/test/rwnode_api_test.cpp b/Development/nmos/test/annotation_api_test.cpp similarity index 86% rename from Development/nmos/test/rwnode_api_test.cpp rename to Development/nmos/test/annotation_api_test.cpp index 739b9a376..f471fd34c 100644 --- a/Development/nmos/test/rwnode_api_test.cpp +++ b/Development/nmos/test/annotation_api_test.cpp @@ -1,12 +1,12 @@ // The first "test" is of course whether the header compiles standalone -#include "nmos/rwnode_api.h" +#include "nmos/annotation_api.h" #include "bst/test/test.h" #include "nmos/group_hint.h" #include "nmos/json_fields.h" //////////////////////////////////////////////////////////////////////////////////////////// -BST_TEST_CASE(testMergeRwnodePatch) +BST_TEST_CASE(testMergeAnnotationPatch) { using web::json::value; using web::json::value_of; @@ -23,14 +23,14 @@ BST_TEST_CASE(testMergeRwnodePatch) // empty patch { auto merged(source); - nmos::details::merge_rwnode_patch(merged, value::object()); + nmos::details::merge_annotation_patch(merged, value::object()); BST_REQUIRE_EQUAL(source, merged); } // reset everything { auto merged(source); - nmos::details::merge_rwnode_patch(merged, value_of({ + nmos::details::merge_annotation_patch(merged, value_of({ { nmos::fields::label, {} }, { nmos::fields::description, {} }, { nmos::fields::tags, {} } @@ -47,7 +47,7 @@ BST_TEST_CASE(testMergeRwnodePatch) // try to reset read-only tag { auto merged(source); - BST_REQUIRE_THROW(nmos::details::merge_rwnode_patch(merged, value_of({ + BST_REQUIRE_THROW(nmos::details::merge_annotation_patch(merged, value_of({ { nmos::fields::tags, value_of({ { nmos::fields::group_hint, {} } }) } @@ -57,7 +57,7 @@ BST_TEST_CASE(testMergeRwnodePatch) // try to update read-only tag { auto merged(source); - BST_REQUIRE_THROW(nmos::details::merge_rwnode_patch(merged, value_of({ + BST_REQUIRE_THROW(nmos::details::merge_annotation_patch(merged, value_of({ { nmos::fields::tags, value_of({ { nmos::fields::group_hint, value_of({ nmos::make_group_hint({ U("qux"), U("quux") }) }) } }) } @@ -67,7 +67,7 @@ BST_TEST_CASE(testMergeRwnodePatch) // add and remove tags { auto merged(source); - nmos::details::merge_rwnode_patch(merged, value_of({ + nmos::details::merge_annotation_patch(merged, value_of({ { nmos::fields::tags, value_of({ { U("foo"), {} }, { U("bar"), value_of({ U("woof"), U("bark") }) }, @@ -86,7 +86,7 @@ BST_TEST_CASE(testMergeRwnodePatch) // change label, description and tags { auto merged(source); - nmos::details::merge_rwnode_patch(merged, value_of({ + nmos::details::merge_annotation_patch(merged, value_of({ { nmos::fields::label, U("woof") }, { nmos::fields::description, U("bark") }, { nmos::fields::tags, value_of({ diff --git a/Development/third_party/README.md b/Development/third_party/README.md index 15742001a..fe42ecd63 100644 --- a/Development/third_party/README.md +++ b/Development/third_party/README.md @@ -19,6 +19,6 @@ Third-party source files used by the nmos-cpp libraries - [is-09](is-09) The JSON Schema files used for validation of System API requests and responses - [is-13](is-13) - The JSON Schema files used for validation of Read/Write Node API requests and responses + The JSON Schema files used for validation of Annotation API requests and responses - [WpdPack](WpdPack) Libraries and header files from the [WinPcap](https://www.winpcap.org/) Developer's Pack diff --git a/Development/third_party/is-13/README.md b/Development/third_party/is-13/README.md index 1d0aa096c..d6fa7c7b2 100644 --- a/Development/third_party/is-13/README.md +++ b/Development/third_party/is-13/README.md @@ -1,6 +1,6 @@ -# AMWA IS-13 NMOS Read/Write Node Specification +# AMWA IS-13 NMOS Annotation Specification -This directory contains files from the [AMWA IS-13 NMOS Read/Write Node Specification](https://github.com/AMWA-TV/is-rwnode), in particular tagged versions of the JSON schemas used by the API specifications. +This directory contains files from the [AMWA IS-13 NMOS Annotation Specification](https://github.com/AMWA-TV/is-13), in particular tagged versions of the JSON schemas used by the API specifications. Original source code: diff --git a/Development/third_party/is-13/v1.0-dev/APIs/schemas/annotationapi-base.json b/Development/third_party/is-13/v1.0-dev/APIs/schemas/annotationapi-base.json new file mode 100644 index 000000000..2c846e14f --- /dev/null +++ b/Development/third_party/is-13/v1.0-dev/APIs/schemas/annotationapi-base.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "Describes the Annotation API base resource", + "title": "Annotation API base resource", + "items": { + "type": "string", + "enum": [ + "node/" + ] + }, + "minItems": 1, + "maxItems": 1, + "uniqueItems": true +} diff --git a/Development/third_party/is-13/v1.0-dev/APIs/schemas/rwnodeapi-base.json b/Development/third_party/is-13/v1.0-dev/APIs/schemas/annotationapi-node-base.json similarity index 72% rename from Development/third_party/is-13/v1.0-dev/APIs/schemas/rwnodeapi-base.json rename to Development/third_party/is-13/v1.0-dev/APIs/schemas/annotationapi-node-base.json index ca31ed51f..9d89a6399 100644 --- a/Development/third_party/is-13/v1.0-dev/APIs/schemas/rwnodeapi-base.json +++ b/Development/third_party/is-13/v1.0-dev/APIs/schemas/annotationapi-node-base.json @@ -1,8 +1,8 @@ { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", - "description": "Describes the Read/Write Node API base resource", - "title": "Read/Write Node API base resource", + "description": "Describes the Annotation API node resource", + "title": "Annotation API node resource", "items": { "type": "string", "enum": [ diff --git a/Development/third_party/is-13/v1.0-dev/APIs/schemas/resource_core_patch.json b/Development/third_party/is-13/v1.0-dev/APIs/schemas/resource_core_patch.json index c587640bb..e49745c76 100644 --- a/Development/third_party/is-13/v1.0-dev/APIs/schemas/resource_core_patch.json +++ b/Development/third_party/is-13/v1.0-dev/APIs/schemas/resource_core_patch.json @@ -10,7 +10,7 @@ "type": ["null", "string"] }, "description": { - "description": "Detailed description of the resource. Set to null to restore default label.", + "description": "Detailed description of the resource. Set to null to restore default description.", "type": ["null", "string"] }, "tags": { diff --git a/README.md b/README.md index 191d421c8..214e2f458 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This repository contains an implementation of the [AMWA Networked Media Open Spe - [AMWA IS-07 NMOS Event & Tally Specification](https://specs.amwa.tv/is-07/) - [AMWA IS-08 NMOS Audio Channel Mapping Specification](https://specs.amwa.tv/is-08/) - [AMWA IS-09 NMOS System Parameters Specification](https://specs.amwa.tv/is-09/) (originally defined in JT-NM TR-1001-1:2018 Annex A) -- [AMWA IS-13 NMOS Read/Write Node Specification](https://specs.amwa.tv/is-13/) +- [AMWA IS-13 NMOS Annotation Specification](https://specs.amwa.tv/is-13/) - [AMWA BCP-002-01 NMOS Grouping Recommendations - Natural Grouping](https://specs.amwa.tv/bcp-002-01/) - [AMWA BCP-002-02 NMOS Asset Distinguishing Information](https://specs.amwa.tv/bcp-002-02/) - [AMWA BCP-003-01 Secure Communication in NMOS Systems](https://specs.amwa.tv/bcp-003-01/)