diff options
author | JackLivio <jack@livio.io> | 2018-08-01 14:06:34 -0400 |
---|---|---|
committer | JackLivio <jack@livio.io> | 2018-08-01 14:06:34 -0400 |
commit | ea4a1731986b7f420c31f978edc7219edde448be (patch) | |
tree | 15fb0a6a4543c58f04cd3bc180b1e6e7834cc8ed | |
parent | 9727cd2cd185d2ea3ea028aab89cb419d1ad4a87 (diff) | |
download | sdl_core-ea4a1731986b7f420c31f978edc7219edde448be.tar.gz |
Add support for mandatory and removed versioning
32 files changed, 775 insertions, 53 deletions
diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index 844b08071b..c5dec86eee 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -51,6 +51,7 @@ #include "protocol_handler/protocol_handler.h" #include "smart_objects/smart_object.h" #include "utils/macro.h" +#include "utils/semantic_version.h" namespace application_manager { @@ -115,6 +116,7 @@ class InitialApplicationData { virtual const smart_objects::SmartObject* ngn_media_screen_name() const = 0; virtual const mobile_api::Language::eType& language() const = 0; virtual const mobile_api::Language::eType& ui_language() const = 0; + virtual const utils::SemanticVersion& msg_version() const = 0; virtual void set_app_types(const smart_objects::SmartObject& app_types) = 0; virtual void set_vr_synonyms( const smart_objects::SmartObject& vr_synonyms) = 0; @@ -125,6 +127,7 @@ class InitialApplicationData { virtual void set_language(const mobile_api::Language::eType& language) = 0; virtual void set_ui_language( const mobile_api::Language::eType& ui_language) = 0; + virtual void set_msg_version(const uint16_t major, const uint16_t minor, const uint16_t patch) = 0; }; /* diff --git a/src/components/application_manager/include/application_manager/application_data_impl.h b/src/components/application_manager/include/application_manager/application_data_impl.h index 8da8dec8f1..71d2c53d5b 100644 --- a/src/components/application_manager/include/application_manager/application_data_impl.h +++ b/src/components/application_manager/include/application_manager/application_data_impl.h @@ -35,6 +35,7 @@ #include <string> #include "utils/lock.h" +#include "utils/semantic_version.h" #include "smart_objects/smart_object.h" #include "application_manager/application.h" #include "interfaces/MOBILE_API.h" @@ -55,6 +56,7 @@ class InitialApplicationDataImpl : public virtual Application { const smart_objects::SmartObject* ngn_media_screen_name() const; const mobile_api::Language::eType& language() const; const mobile_api::Language::eType& ui_language() const; + const utils::SemanticVersion& msg_version() const; void set_app_types(const smart_objects::SmartObject& app_types); void set_vr_synonyms(const smart_objects::SmartObject& vr_synonyms); @@ -63,6 +65,7 @@ class InitialApplicationDataImpl : public virtual Application { void set_ngn_media_screen_name(const smart_objects::SmartObject& ngn_name); void set_language(const mobile_api::Language::eType& language); void set_ui_language(const mobile_api::Language::eType& ui_language); + void set_msg_version(const uint16_t major, const uint16_t minor, const uint16_t patch); void set_perform_interaction_layout( mobile_api::LayoutMode::eType layout) OVERRIDE; @@ -77,6 +80,7 @@ class InitialApplicationDataImpl : public virtual Application { mobile_api::Language::eType language_; mobile_api::Language::eType ui_language_; mobile_apis::LayoutMode::eType perform_interaction_layout_; + utils::SemanticVersion msg_version_; private: DISALLOW_COPY_AND_ASSIGN(InitialApplicationDataImpl); diff --git a/src/components/application_manager/include/application_manager/rpc_handler_impl.h b/src/components/application_manager/include/application_manager/rpc_handler_impl.h index 44954d41f7..7f61c7b034 100644 --- a/src/components/application_manager/include/application_manager/rpc_handler_impl.h +++ b/src/components/application_manager/include/application_manager/rpc_handler_impl.h @@ -57,6 +57,7 @@ #include "interfaces/v4_protocol_v1_2_no_extra_schema.h" #include "utils/threads/message_loop_thread.h" +#include "utils/semantic_version.h" namespace application_manager { namespace rpc_handler { diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc index 78a92d360a..672864c422 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/register_app_interface_request.cc @@ -293,12 +293,26 @@ void RegisterAppInterfaceRequest::Run() { return; } + uint16_t major = msg_params[strings::sync_msg_version][strings::major_version].asUInt(); + uint16_t minor = msg_params[strings::sync_msg_version][strings::minor_version].asUInt(); + uint16_t patch = 0; + if(msg_params[strings::sync_msg_version].keyExists(strings::patch_version)) { + patch = msg_params[strings::sync_msg_version][strings::patch_version].asUInt(); + } + if (major < minimum_major_version || (major == minimum_major_version && minor < minimum_minor_version) + || (major == minimum_major_version && minor == minimum_minor_version && patch < minimum_patch_version)) { + SendResponse(false, mobile_apis::Result::REJECTED); + } + application = application_manager_.RegisterApplication(message_); if (!application) { LOG4CXX_ERROR(logger_, "Application hasn't been registered!"); return; } + + application->set_msg_version(major, minor, patch); + // For resuming application need to restore hmi_app_id from resumeCtrl resumption::ResumeCtrl& resumer = application_manager_.resume_controller(); const std::string& device_mac = application->mac_address(); diff --git a/src/components/application_manager/src/application_data_impl.cc b/src/components/application_manager/src/application_data_impl.cc index f271b7ff6a..4f26ce5ef5 100644 --- a/src/components/application_manager/src/application_data_impl.cc +++ b/src/components/application_manager/src/application_data_impl.cc @@ -103,6 +103,12 @@ const mobile_api::Language::eType& InitialApplicationDataImpl::ui_language() return ui_language_; } +const utils::SemanticVersion& InitialApplicationDataImpl::msg_version() + const { + return msg_version_; +} + + void InitialApplicationDataImpl::set_app_types( const smart_objects::SmartObject& app_types) { if (app_types_) { @@ -153,6 +159,13 @@ void InitialApplicationDataImpl::set_ui_language( ui_language_ = ui_language; } +void InitialApplicationDataImpl::set_msg_version( + const uint16_t major, const uint16_t minor, const uint16_t patch) { + msg_version_.major_version = major; + msg_version_.minor_version = minor; + msg_version_.patch_version = patch; +} + void InitialApplicationDataImpl::set_perform_interaction_layout( mobile_apis::LayoutMode::eType layout) { perform_interaction_layout_ = layout; diff --git a/src/components/application_manager/src/rpc_handler_impl.cc b/src/components/application_manager/src/rpc_handler_impl.cc index b374147968..7b3645ddf1 100644 --- a/src/components/application_manager/src/rpc_handler_impl.cc +++ b/src/components/application_manager/src/rpc_handler_impl.cc @@ -218,9 +218,23 @@ bool RPCHandlerImpl::ConvertMessageToSO( rpc::ValidationReport report("RPC"); + //Attach RPC version to SmartObject if it does not exist yet. + auto app_ptr = app_manager_.application(message.connection_key()); + utils::SemanticVersion msg_version(2, 0, 0); + if (app_ptr && (output[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS].keyExists(NsSmartDeviceLink::NsJSONHandler::strings::S_RPC_MSG_VERSION) == false)) { + printf("Getting app msg version\n"); + msg_version = app_ptr->msg_version(); + output[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS][NsSmartDeviceLink::NsJSONHandler::strings::S_RPC_MSG_VERSION] = msg_version.toString(); + } else if (mobile_apis::FunctionID::RegisterAppInterfaceID == static_cast<mobile_apis::FunctionID::eType>(output[strings::params][strings::function_id].asInt())) { + //Assume default version 1.0.0 until properly set in RAI + printf("Setting default msg version\n"); + output[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS][NsSmartDeviceLink::NsJSONHandler::strings::S_RPC_MSG_VERSION] = msg_version.toString(); + printf("%s\n", output[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS][NsSmartDeviceLink::NsJSONHandler::strings::S_RPC_MSG_VERSION].asString().c_str()); + } + if (!conversion_result || !mobile_so_factory().attachSchema(output, true) || - ((output.validate(&report) != smart_objects::Errors::OK))) { + ((output.validate(&report, msg_version) != smart_objects::Errors::OK))) { LOG4CXX_WARN(logger_, "Failed to parse string to smart object :" << message.json_message()); diff --git a/src/components/formatters/include/formatters/CSmartFactory.h b/src/components/formatters/include/formatters/CSmartFactory.h index 9fed89253b..c2037e7adc 100644 --- a/src/components/formatters/include/formatters/CSmartFactory.h +++ b/src/components/formatters/include/formatters/CSmartFactory.h @@ -82,6 +82,10 @@ extern const std::string S_PROTOCOL_TYPE; extern const std::string S_CORRELATION_ID; /** + * @brief String constant for RPC_MSG_VERSION. + */ +extern const std::string S_RPC_MSG_VERSION; +/** * @brief String constant for "code" param name. */ extern const std::string kCode; @@ -295,7 +299,13 @@ bool CSmartFactory<FunctionIdEnum, MessageTypeEnum, StructIdEnum>::attachSchema( } object.setSchema(schemaIterator->second); - schemaIterator->second.applySchema(object, RemoveFakeParameters); + + utils::SemanticVersion msg_version; + if (object[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS].keyExists(NsSmartDeviceLink::NsJSONHandler::strings::S_RPC_MSG_VERSION)) { + msg_version = object[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS][NsSmartDeviceLink::NsJSONHandler::strings::S_RPC_MSG_VERSION].asString(); + } + + schemaIterator->second.applySchema(object, RemoveFakeParameters, msg_version); return true; } diff --git a/src/components/formatters/src/CSmartFactory.cc b/src/components/formatters/src/CSmartFactory.cc index 6b0808fbfa..27e2064fee 100644 --- a/src/components/formatters/src/CSmartFactory.cc +++ b/src/components/formatters/src/CSmartFactory.cc @@ -47,6 +47,7 @@ const std::string NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_TYPE( "protocol_type"); const std::string NsSmartDeviceLink::NsJSONHandler::strings::S_CORRELATION_ID( "correlation_id"); +const std::string NsSmartDeviceLink::NsJSONHandler::strings::S_RPC_MSG_VERSION("rpc_msg_version"); const std::string NsSmartDeviceLink::NsJSONHandler::strings::kCode("code"); const std::string NsSmartDeviceLink::NsJSONHandler::strings::kMessage( "message"); diff --git a/src/components/include/utils/semantic_version.h b/src/components/include/utils/semantic_version.h new file mode 100644 index 0000000000..aca61f4810 --- /dev/null +++ b/src/components/include/utils/semantic_version.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2018, Livio + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_INCLUDE_UTILS_SEMANTIC_VERSION_H_ +#define SRC_COMPONENTS_INCLUDE_UTILS_SEMANTIC_VERSION_H_ + +#include <boost/algorithm/string.hpp> + +namespace utils { + +struct SemanticVersion { + + SemanticVersion(uint16_t major = 0, uint16_t minor = 0, uint16_t patch = 0) { + major_version = major; + minor_version = minor; + patch_version = patch; + } + + SemanticVersion(const std::string& str_version) { + std::vector<std::string> str_array; + boost::split(str_array, str_version, boost::is_any_of(".")); + if(str_array.size() == 3) { + major_version = atoi(str_array[0].c_str()); + minor_version = atoi(str_array[1].c_str()); + patch_version = atoi(str_array[2].c_str()); + } else { + exit(1); + } + } + + bool operator==(const SemanticVersion& version) const { + if (major_version == version.major_version && minor_version == version.minor_version && patch_version == version.patch_version) { + return true; + } else { + return false; + } + } + + bool operator<(const SemanticVersion& version) const { + if(major_version < version.major_version) { + return true; + } else if (minor_version < version.minor_version) { + return true; + } else if (patch_version < version.patch_version) { + return true; + } else { + return false; + } + } + + bool operator<=(const SemanticVersion& version) const { + if (this->operator==(version)) { + return true; + } else if (this->operator<(version)) { + return true; + } else { + return false; + } + } + + bool operator>(const SemanticVersion& version) const { + if(major_version > version.major_version) { + return true; + } else if (minor_version > version.minor_version) { + return true; + } else if (patch_version > version.patch_version) { + return true; + } else { + return false; + } + } + + bool operator>=(const SemanticVersion& version) const { + if (this->operator==(version)) { + return true; + } else if (this->operator>(version)) { + return true; + } else { + return false; + } + } + + const std::string toString() { + std::string result = ""; + result += std::to_string(major_version); + result += "."; + result += std::to_string(minor_version); + result += "."; + result += std::to_string(patch_version); + printf("toString Result!!!: %s\n", result.c_str()); + return result; + } + + bool isValid() const{ + return major_version > 0 || minor_version > 0 || patch_version > 0; + } + + uint16_t major_version = 0; + uint16_t minor_version = 0; + uint16_t patch_version = 0; + +}; + +} + +#endif // SRC_COMPONENTS_INCLUDE_UTILS_CALLABLE_H
\ No newline at end of file diff --git a/src/components/smart_objects/include/smart_objects/always_false_schema_item.h b/src/components/smart_objects/include/smart_objects/always_false_schema_item.h index 4510f2292a..3a8a309b8d 100644 --- a/src/components/smart_objects/include/smart_objects/always_false_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/always_false_schema_item.h @@ -62,6 +62,15 @@ class CAlwaysFalseSchemaItem : public ISchemaItem { **/ Errors::eType validate(const SmartObject& Object, rpc::ValidationReport* report__) OVERRIDE; + /** + * @brief Validate smart object. + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * @param MessageVersion to check mobile RPC version against RPC Spec History + * @return NsSmartObjects::Errors::eType + **/ + Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) OVERRIDE; private: CAlwaysFalseSchemaItem(); diff --git a/src/components/smart_objects/include/smart_objects/always_true_schema_item.h b/src/components/smart_objects/include/smart_objects/always_true_schema_item.h index 8a211339ba..9fe7878811 100644 --- a/src/components/smart_objects/include/smart_objects/always_true_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/always_true_schema_item.h @@ -63,6 +63,16 @@ class CAlwaysTrueSchemaItem : public ISchemaItem { Errors::eType validate(const SmartObject& Object, rpc::ValidationReport* report__) OVERRIDE; + /** + * @brief Validate smart object. + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * @param MessageVersion to check mobile RPC version against RPC Spec History + * @return NsSmartObjects::Errors::eType + **/ + Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) OVERRIDE; + private: CAlwaysTrueSchemaItem(); DISALLOW_COPY_AND_ASSIGN(CAlwaysTrueSchemaItem); diff --git a/src/components/smart_objects/include/smart_objects/array_schema_item.h b/src/components/smart_objects/include/smart_objects/array_schema_item.h index 3e8be98ee0..af21dd9b65 100644 --- a/src/components/smart_objects/include/smart_objects/array_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/array_schema_item.h @@ -38,6 +38,8 @@ #include "smart_objects/always_true_schema_item.h" #include "smart_objects/schema_item_parameter.h" +#include "utils/semantic_version.h" + namespace NsSmartDeviceLink { namespace NsSmartObjects { /** @@ -83,6 +85,15 @@ class CArraySchemaItem : public ISchemaItem { **/ Errors::eType validate(const SmartObject& Object, rpc::ValidationReport* report__) OVERRIDE; + /** + * @brief Validate smart object. + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * @param MessageVersion to check mobile RPC version against RPC Spec History + * @return NsSmartObjects::Errors::eType + **/ + Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) OVERRIDE; /** * @brief Apply schema. @@ -93,7 +104,7 @@ class CArraySchemaItem : public ISchemaItem { * from smart object otherwise contains false. **/ void applySchema(SmartObject& Object, - const bool RemoveFakeParameters) OVERRIDE; + const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion()) OVERRIDE; /** * @brief Unapply schema. diff --git a/src/components/smart_objects/include/smart_objects/default_shema_item.h b/src/components/smart_objects/include/smart_objects/default_shema_item.h index fdac77d029..75dbcaf67d 100644 --- a/src/components/smart_objects/include/smart_objects/default_shema_item.h +++ b/src/components/smart_objects/include/smart_objects/default_shema_item.h @@ -65,6 +65,16 @@ class CDefaultSchemaItem : public ISchemaItem { rpc::ValidationReport* report__) OVERRIDE; /** + * @brief Validate smart object. + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * @param MessageVersion to check mobile RPC version against RPC Spec History + * @return NsSmartObjects::Errors::eType + **/ + Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) OVERRIDE; + + /** * @brief Set default value to an object. * @param Object Object to set default value. * @return true if default value was successfully set, false otherwise. @@ -127,6 +137,12 @@ Errors::eType CDefaultSchemaItem<Type>::validate( } template <typename Type> +Errors::eType CDefaultSchemaItem<Type>::validate( + const SmartObject& Object, rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) { + return validate(Object, report__); +} + +template <typename Type> bool CDefaultSchemaItem<Type>::setDefaultValue(SmartObject& Object) { Type value; if (mDefaultValue.getValue(value)) { diff --git a/src/components/smart_objects/include/smart_objects/enum_schema_item.h b/src/components/smart_objects/include/smart_objects/enum_schema_item.h index 450bbc6c40..787960659f 100644 --- a/src/components/smart_objects/include/smart_objects/enum_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/enum_schema_item.h @@ -41,6 +41,8 @@ #include "smart_objects/default_shema_item.h" +#include "utils/semantic_version.h" + namespace NsSmartDeviceLink { namespace NsSmartObjects { @@ -78,6 +80,16 @@ class TEnumSchemaItem : public CDefaultSchemaItem<EnumType> { **/ Errors::eType validate(const SmartObject& Object, rpc::ValidationReport* report__) OVERRIDE; + + /** + * @brief Validate smart object. + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * @param MessageVersion to check mobile RPC version against RPC Spec History + * @return NsSmartObjects::Errors::eType + **/ + Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) OVERRIDE; /** * @brief Apply schema. * This implementation checks if enumeration is represented as string @@ -88,7 +100,7 @@ class TEnumSchemaItem : public CDefaultSchemaItem<EnumType> { * from smart object otherwise contains false. **/ void applySchema(SmartObject& Object, - const bool RemoveFakeParameters) OVERRIDE; + const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion()) OVERRIDE; /** * @brief Unapply schema. * @param Object Object to unapply schema. @@ -248,8 +260,14 @@ Errors::eType TEnumSchemaItem<EnumType>::validate( } template <typename EnumType> +Errors::eType TEnumSchemaItem<EnumType>::validate( + const SmartObject& Object, rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) { + return validate(Object, report__); +} + +template <typename EnumType> void TEnumSchemaItem<EnumType>::applySchema(SmartObject& Object, - const bool RemoveFakeParameters) { + const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion) { if (SmartType_String == Object.getType()) { EnumType enum_val = static_cast<EnumType>(-1); if (ConversionHelper::StringToEnum(Object.asString(), &enum_val)) { diff --git a/src/components/smart_objects/include/smart_objects/number_schema_item.h b/src/components/smart_objects/include/smart_objects/number_schema_item.h index 2c64538953..e1d294779d 100644 --- a/src/components/smart_objects/include/smart_objects/number_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/number_schema_item.h @@ -81,6 +81,16 @@ class TNumberSchemaItem : public CDefaultSchemaItem<NumberType> { Errors::eType validate(const SmartObject& Object, rpc::ValidationReport* report__) OVERRIDE; + /** + * @brief Validate smart object. + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * @param MessageVersion to check mobile RPC version against RPC Spec History + * @return NsSmartObjects::Errors::eType + **/ + Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) OVERRIDE; + private: /** * @brief Get smart type for this NumberType. @@ -194,6 +204,12 @@ Errors::eType TNumberSchemaItem<NumberType>::validate( } template <typename NumberType> +Errors::eType TNumberSchemaItem<NumberType>::validate( + const SmartObject& Object, rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) { + return validate(Object, report__); +} + +template <typename NumberType> TNumberSchemaItem<NumberType>::TNumberSchemaItem( const TSchemaItemParameter<NumberType>& MinValue, const TSchemaItemParameter<NumberType>& MaxValue, diff --git a/src/components/smart_objects/include/smart_objects/object_schema_item.h b/src/components/smart_objects/include/smart_objects/object_schema_item.h index 4c0def558b..df5a34a25a 100644 --- a/src/components/smart_objects/include/smart_objects/object_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/object_schema_item.h @@ -37,6 +37,8 @@ #include <set> #include "utils/macro.h" +#include "utils/semantic_version.h" +#include <boost/optional.hpp> #include "smart_objects/schema_item.h" #include "smart_objects/schema_item_parameter.h" @@ -62,7 +64,20 @@ class CObjectSchemaItem : public ISchemaItem { * @param IsMandatory true if member is mandatory, false * otherwise. Defaults to true. **/ - SMember(const ISchemaItemPtr SchemaItem, const bool IsMandatory = true); + //SMember(const ISchemaItemPtr SchemaItem, const bool IsMandatory = true); + + SMember(const ISchemaItemPtr SchemaItem, + const bool IsMandatory = true, + const std::string& Since = "", + const std::string& Until = "", + const bool IsDeprecated = false, + const bool IsRemoved = false); + /** + * @brief Checks the version a parameter was removed (until) + * If the mobile's msg version is greater than or + **/ + bool CheckHistoryFieldVersion(const utils::SemanticVersion& MessageVersion) const; + /** * @brief Member schema item. **/ @@ -71,6 +86,11 @@ class CObjectSchemaItem : public ISchemaItem { * @brief true if member is mandatory, false otherwise. **/ bool mIsMandatory; + boost::optional<utils::SemanticVersion> mSince; + boost::optional<utils::SemanticVersion> mUntil; + bool mIsDeprecated; + bool mIsRemoved; + }; typedef std::map<std::string, SMember> Members; /** @@ -98,13 +118,22 @@ class CObjectSchemaItem : public ISchemaItem { Errors::eType validate(const SmartObject& Object, rpc::ValidationReport* report__) OVERRIDE; /** + * @brief Validate smart object. + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * @param MessageVersion to check mobile RPC version against RPC Spec History + * @return NsSmartObjects::Errors::eType + **/ + Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) OVERRIDE; + /** * @brief Apply schema. * @param Object Object to apply schema. * @param RemoveFakeParameters contains true if need to remove fake parameters * from smart object otherwise contains false. **/ void applySchema(SmartObject& Object, - const bool RemoveFakeParameters) OVERRIDE; + const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion()) OVERRIDE; /** * @brief Unapply schema. * @param Object Object to unapply schema. @@ -136,7 +165,14 @@ class CObjectSchemaItem : public ISchemaItem { * @brief Removes fake parameters from object. * @param Object Object to remove fake parameters. **/ - void RemoveFakeParams(SmartObject& Object); + void RemoveFakeParams(SmartObject& Object, const utils::SemanticVersion& MessageVersion); + + /** + * @brief Checks mandatory and version fields to see + * if a member is required. + * @param Object Object to remove fake parameters. + **/ + bool IsMandatory(const SMember& member); /** * @brief Map of member name to SMember structure describing the object diff --git a/src/components/smart_objects/include/smart_objects/schema_item.h b/src/components/smart_objects/include/smart_objects/schema_item.h index 2b15a1d47a..4e126b2bec 100644 --- a/src/components/smart_objects/include/smart_objects/schema_item.h +++ b/src/components/smart_objects/include/smart_objects/schema_item.h @@ -40,6 +40,7 @@ #include <memory> #include "utils/macro.h" +#include "utils/semantic_version.h" namespace NsSmartDeviceLink { namespace NsSmartObjects { @@ -74,6 +75,18 @@ class ISchemaItem { rpc::ValidationReport* report__); /** + * @brief Validate smart object. + * + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * message if an error occurs + * @param MessageVersion to check mobile RPC version against RPC Spec Histor + * @return NsSmartObjects::Errors::eType + **/ + virtual Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion); + + /** * @brief Set default value to an object. * * @param Object Object to set default value. @@ -100,7 +113,7 @@ class ISchemaItem { **/ virtual void applySchema( NsSmartDeviceLink::NsSmartObjects::SmartObject& Object, - const bool RemoveFakeParameters); + const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion()); /** * @brief Unapply schema. diff --git a/src/components/smart_objects/include/smart_objects/smart_object.h b/src/components/smart_objects/include/smart_objects/smart_object.h index 6a2cbdb911..5853c9bb3f 100644 --- a/src/components/smart_objects/include/smart_objects/smart_object.h +++ b/src/components/smart_objects/include/smart_objects/smart_object.h @@ -687,6 +687,15 @@ class SmartObject FINAL { Errors::eType validate(rpc::ValidationReport* report__); /** + * @brief Validates object according to attached schema. + * + * @param report__ object for reporting errors during validation + * @param messageVersion of the mobile app to check against RPC Spec Schema + * @return Result of validation. + */ + Errors::eType validate(rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion); + + /** * @brief Sets new schema * * @param schema Schema for object validation diff --git a/src/components/smart_objects/include/smart_objects/smart_schema.h b/src/components/smart_objects/include/smart_objects/smart_schema.h index ada5646043..08595d311c 100644 --- a/src/components/smart_objects/include/smart_objects/smart_schema.h +++ b/src/components/smart_objects/include/smart_objects/smart_schema.h @@ -83,6 +83,17 @@ class CSmartSchema FINAL { rpc::ValidationReport* report__) const; /** + * @brief Validate smart object. + * + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * @param MessageVersion to check mobile RPC version against RPC Spec History + * @return NsSmartObjects::Errors::eType + **/ + Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& messageVersion) const; + + /** * @brief Set new root schema item. * * @param SchemaItem Root schema item. @@ -97,7 +108,7 @@ class CSmartSchema FINAL { * @param RemoveFakeParameters contains true if need to remove fake parameters * from smart object otherwise contains false. **/ - void applySchema(SmartObject& Object, const bool RemoveFakeParameters); + void applySchema(SmartObject& Object, const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion()); /** * @brief The reverse SmartObject conversion using schema. diff --git a/src/components/smart_objects/include/smart_objects/string_schema_item.h b/src/components/smart_objects/include/smart_objects/string_schema_item.h index 50418debc0..0bf21a6449 100644 --- a/src/components/smart_objects/include/smart_objects/string_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/string_schema_item.h @@ -74,7 +74,15 @@ class CStringSchemaItem : public CDefaultSchemaItem<std::string> { **/ Errors::eType validate(const SmartObject& Object, rpc::ValidationReport* report__) OVERRIDE; - + /** + * @brief Validate smart object. + * @param Object Object to validate. + * @param report__ object for reporting errors during validation + * @param MessageVersion to check mobile RPC version against RPC Spec History + * @return NsSmartObjects::Errors::eType + **/ + Errors::eType validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) OVERRIDE; private: /** * @brief Constructor. diff --git a/src/components/smart_objects/src/always_false_schema_item.cc b/src/components/smart_objects/src/always_false_schema_item.cc index 203ae11236..18d0d36323 100644 --- a/src/components/smart_objects/src/always_false_schema_item.cc +++ b/src/components/smart_objects/src/always_false_schema_item.cc @@ -51,5 +51,12 @@ Errors::eType CAlwaysFalseSchemaItem::validate( report__->set_validation_info("Generic error"); return Errors::ERROR; } + +Errors::eType CAlwaysFalseSchemaItem::validate( + const SmartObject& Object, rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) { + report__->set_validation_info("Generic error"); + return Errors::ERROR; +} + } // namespace NsSmartObjects } // namespace NsSmartDeviceLink diff --git a/src/components/smart_objects/src/always_true_schema_item.cc b/src/components/smart_objects/src/always_true_schema_item.cc index 774bcea121..0402fa0d10 100644 --- a/src/components/smart_objects/src/always_true_schema_item.cc +++ b/src/components/smart_objects/src/always_true_schema_item.cc @@ -48,5 +48,10 @@ Errors::eType CAlwaysTrueSchemaItem::validate(const SmartObject& object, return Errors::OK; } +Errors::eType CAlwaysTrueSchemaItem::validate( + const SmartObject& Object, rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) { + return Errors::OK; +} + } // namespace NsSmartObjects } // namespace NsSmartDeviceLink diff --git a/src/components/smart_objects/src/array_schema_item.cc b/src/components/smart_objects/src/array_schema_item.cc index f006267f10..78619050e0 100644 --- a/src/components/smart_objects/src/array_schema_item.cc +++ b/src/components/smart_objects/src/array_schema_item.cc @@ -89,11 +89,53 @@ Errors::eType CArraySchemaItem::validate(const SmartObject& Object, return Errors::OK; } +Errors::eType CArraySchemaItem::validate(const SmartObject& Object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) { + if (SmartType_Array != Object.getType()) { + std::string validation_info = "Incorrect type, expected: " + + SmartObject::typeToString(SmartType_Array) + + ", got: " + + SmartObject::typeToString(Object.getType()); + report__->set_validation_info(validation_info); + return Errors::INVALID_VALUE; + } + size_t sizeLimit; + const size_t array_len = Object.length(); + + if (mMinSize.getValue(sizeLimit) && (array_len < sizeLimit)) { + std::stringstream stream; + stream << "Got array of size: " << array_len + << ", minimum allowed: " << sizeLimit; + std::string validation_info = stream.str(); + report__->set_validation_info(validation_info); + return Errors::OUT_OF_RANGE; + } + if (mMaxSize.getValue(sizeLimit) && (array_len > sizeLimit)) { + std::stringstream stream; + stream << "Got array of size: " << array_len + << ", maximum allowed: " << sizeLimit; + std::string validation_info = stream.str(); + report__->set_validation_info(validation_info); + return Errors::OUT_OF_RANGE; + } + + for (size_t i = 0u; i < array_len; ++i) { + std::stringstream strVal; + strVal << i; + const Errors::eType result = mElementSchemaItem->validate( + Object.getElement(i), &report__->ReportSubobject(strVal.str()), MessageVersion); + if (Errors::OK != result) { + return result; + } + } + return Errors::OK; +} + void CArraySchemaItem::applySchema(SmartObject& Object, - const bool RemoveFakeParameters) { + const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion) { if (SmartType_Array == Object.getType()) { for (size_t i = 0U; i < Object.length(); ++i) { - mElementSchemaItem->applySchema(Object[i], RemoveFakeParameters); + mElementSchemaItem->applySchema(Object[i], RemoveFakeParameters, MessageVersion); } } } diff --git a/src/components/smart_objects/src/object_schema_item.cc b/src/components/smart_objects/src/object_schema_item.cc index c79b97689d..bab952411b 100644 --- a/src/components/smart_objects/src/object_schema_item.cc +++ b/src/components/smart_objects/src/object_schema_item.cc @@ -33,6 +33,8 @@ #include <algorithm> +#include <boost/algorithm/string.hpp> + #include "smart_objects/always_false_schema_item.h" #include "smart_objects/smart_object.h" @@ -48,8 +50,66 @@ CObjectSchemaItem::SMember::SMember() : mSchemaItem(CAlwaysFalseSchemaItem::create()), mIsMandatory(true) {} CObjectSchemaItem::SMember::SMember(const ISchemaItemPtr SchemaItem, - const bool IsMandatory) - : mSchemaItem(SchemaItem), mIsMandatory(IsMandatory) {} + const bool IsMandatory, + const std::string& Since, + const std::string& Until, + const bool IsDeprecated, + const bool IsRemoved) + : mSchemaItem(SchemaItem), mIsMandatory(IsMandatory) { + + if (Since.size() > 0) { + utils::SemanticVersion since_struct; + std::vector<std::string> since_fields; + boost::split(since_fields, Since, boost::is_any_of(".")); + if(since_fields.size() == 3) { + since_struct.major_version = atoi(since_fields[0].c_str()); + since_struct.minor_version = atoi(since_fields[1].c_str()); + since_struct.patch_version = atoi(since_fields[2].c_str()); + mSince = since_struct; + } + } + + if (Until.size() > 0) { + utils::SemanticVersion until_struct; + std::vector<std::string> until_fields; + boost::split(until_fields, Until, boost::is_any_of(".")); + if(until_fields.size() == 3) { + until_struct.major_version = atoi(until_fields[0].c_str()); + until_struct.minor_version = atoi(until_fields[1].c_str()); + until_struct.patch_version = atoi(until_fields[2].c_str()); + mUntil = until_struct; + } + } + + mIsDeprecated = IsDeprecated; + mIsRemoved = IsRemoved; + + } + +bool CObjectSchemaItem::SMember::CheckHistoryFieldVersion(const utils::SemanticVersion& MessageVersion) const { + if (MessageVersion.isValid()) { + if (mSince.is_initialized()) { + if (MessageVersion < mSince.get()) { + return false; //Msg version predates `since` field + } else { + if (mUntil.is_initialized() && (MessageVersion >= mUntil.get())) { + return false; //Msg version newer than `until` field + } else { + return true; //Mobile msg version falls within specified version range + } + } + } + + if (mUntil.is_initialized() && (MessageVersion >= mUntil.get())) { + return false; //Msg version newer than `until` field + } else { + return true; //Mobile msg version falls within specified version range + } + } + + printf("Final true of check history version\n"); + return true; //Not enough version information. Default true. +} std::shared_ptr<CObjectSchemaItem> CObjectSchemaItem::create( const Members& members) { @@ -99,14 +159,52 @@ Errors::eType CObjectSchemaItem::validate(const SmartObject& object, return Errors::OK; } +Errors::eType CObjectSchemaItem::validate(const SmartObject& object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) { + if (SmartType_Map != object.getType()) { + std::string validation_info = "Incorrect type, expected: " + + SmartObject::typeToString(SmartType_Map) + + ", got: " + + SmartObject::typeToString(object.getType()); + report__->set_validation_info(validation_info); + return Errors::INVALID_VALUE; + } + + std::set<std::string> object_keys = object.enumerate(); + + for (Members::const_iterator it = mMembers.begin(); it != mMembers.end(); + ++it) { + const std::string& key = it->first; + const SMember& member = it->second; + printf("key: %s\n", key.c_str()); + std::set<std::string>::const_iterator key_it = object_keys.find(key); + if (object_keys.end() == key_it) { + if (member.mIsMandatory && member.CheckHistoryFieldVersion(MessageVersion)) { + std::string validation_info = "Missing mandatory parameter: " + key; + report__->set_validation_info(validation_info); + return Errors::MISSING_MANDATORY_PARAMETER; + } + continue; + } + const SmartObject& field = object.getElement(key); + const Errors::eType result = + member.mSchemaItem->validate(field, &report__->ReportSubobject(key), MessageVersion); + if (Errors::OK != result) { + return result; + } + object_keys.erase(key_it); + } + return Errors::OK; +} + void CObjectSchemaItem::applySchema(SmartObject& Object, - const bool RemoveFakeParameters) { + const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion) { if (SmartType_Map != Object.getType()) { return; } if (RemoveFakeParameters) { - RemoveFakeParams(Object); + RemoveFakeParams(Object, MessageVersion); } SmartObject default_value; @@ -117,10 +215,10 @@ void CObjectSchemaItem::applySchema(SmartObject& Object, if (!Object.keyExists(key)) { if (member.mSchemaItem->setDefaultValue(default_value)) { Object[key] = default_value; - member.mSchemaItem->applySchema(Object[key], RemoveFakeParameters); + member.mSchemaItem->applySchema(Object[key], RemoveFakeParameters, MessageVersion); } } else { - member.mSchemaItem->applySchema(Object[key], RemoveFakeParameters); + member.mSchemaItem->applySchema(Object[key], RemoveFakeParameters, MessageVersion); } } } @@ -173,22 +271,30 @@ size_t CObjectSchemaItem::GetMemberSize() { CObjectSchemaItem::CObjectSchemaItem(const Members& members) : mMembers(members) {} -void CObjectSchemaItem::RemoveFakeParams(SmartObject& Object) { +void CObjectSchemaItem::RemoveFakeParams(SmartObject& Object, const utils::SemanticVersion& MessageVersion) { for (SmartMap::const_iterator it = Object.map_begin(); it != Object.map_end();) { const std::string& key = it->first; - if (mMembers.end() == mMembers.find(key) + std::map<std::string, SMember>::const_iterator members_it = mMembers.find(key); + if (mMembers.end() == members_it // FIXME(EZamakhov): Remove illegal usage of filed in AM && key.compare(connection_key) != 0 && key.compare(binary_data) != 0 && key.compare(app_id) != 0) { ++it; Object.erase(key); + } else if (members_it->second.mIsRemoved && members_it->second.CheckHistoryFieldVersion(MessageVersion)) { + ++it; + Object.erase(key); } else { it++; } } } +bool CObjectSchemaItem::IsMandatory(const SMember& member) { + return true; +} + } // namespace NsSmartObjects } // namespace NsSmartDeviceLink diff --git a/src/components/smart_objects/src/schema_item.cc b/src/components/smart_objects/src/schema_item.cc index 22735d40d5..685cd3a79f 100644 --- a/src/components/smart_objects/src/schema_item.cc +++ b/src/components/smart_objects/src/schema_item.cc @@ -44,6 +44,12 @@ Errors::eType ISchemaItem::validate(const SmartObject& object, return Errors::ERROR; } +Errors::eType ISchemaItem::validate(const SmartObject& object, + rpc::ValidationReport* report__, + const utils::SemanticVersion& MessageVersion) { + return Errors::ERROR; +} + bool ISchemaItem::setDefaultValue(SmartObject& Object) { return false; } @@ -53,7 +59,7 @@ bool ISchemaItem::hasDefaultValue(SmartObject& Object) { } void ISchemaItem::applySchema(SmartObject& Object, - const bool RemoveFakeParameters) {} + const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion) {} void ISchemaItem::unapplySchema(SmartObject& Object) {} diff --git a/src/components/smart_objects/src/smart_object.cc b/src/components/smart_objects/src/smart_object.cc index a0925eef05..a1d769dff7 100644 --- a/src/components/smart_objects/src/smart_object.cc +++ b/src/components/smart_objects/src/smart_object.cc @@ -882,6 +882,10 @@ Errors::eType SmartObject::validate(rpc::ValidationReport* report__) { return m_schema.validate(*this, report__); } +Errors::eType SmartObject::validate(rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) { + return m_schema.validate(*this, report__, MessageVersion); +} + void SmartObject::setSchema(const CSmartSchema& schema) { m_schema = schema; } diff --git a/src/components/smart_objects/src/smart_schema.cc b/src/components/smart_objects/src/smart_schema.cc index 7509ea80f1..7e2aaed974 100644 --- a/src/components/smart_objects/src/smart_schema.cc +++ b/src/components/smart_objects/src/smart_schema.cc @@ -50,13 +50,18 @@ Errors::eType CSmartSchema::validate(const SmartObject& object, return mSchemaItem->validate(object, report__); } +Errors::eType CSmartSchema::validate(const SmartObject& object, + rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) const { + return mSchemaItem->validate(object, report__, MessageVersion); +} + void CSmartSchema::setSchemaItem(const ISchemaItemPtr schemaItem) { mSchemaItem = schemaItem; } void CSmartSchema::applySchema(SmartObject& Object, - const bool RemoveFakeParameters) { - mSchemaItem->applySchema(Object, RemoveFakeParameters); + const bool RemoveFakeParameters, const utils::SemanticVersion& MessageVersion) { + mSchemaItem->applySchema(Object, RemoveFakeParameters, MessageVersion); } void CSmartSchema::unapplySchema(SmartObject& Object) { diff --git a/src/components/smart_objects/src/string_schema_item.cc b/src/components/smart_objects/src/string_schema_item.cc index b403607ede..05ed196717 100644 --- a/src/components/smart_objects/src/string_schema_item.cc +++ b/src/components/smart_objects/src/string_schema_item.cc @@ -84,6 +84,11 @@ Errors::eType CStringSchemaItem::validate(const SmartObject& Object, return Errors::OK; } +Errors::eType CStringSchemaItem::validate( + const SmartObject& Object, rpc::ValidationReport* report__, const utils::SemanticVersion& MessageVersion) { + return validate(Object, report__); +} + SmartType CStringSchemaItem::getSmartType() const { return SmartType_String; } diff --git a/tools/InterfaceGenerator/MsgVersionGenerate.py b/tools/InterfaceGenerator/MsgVersionGenerate.py index 86251cd419..4a24a3239f 100644 --- a/tools/InterfaceGenerator/MsgVersionGenerate.py +++ b/tools/InterfaceGenerator/MsgVersionGenerate.py @@ -12,14 +12,25 @@ def generate_msg_version(file_name, path_to_storage): """ tree = xml.etree.ElementTree.parse(file_name) root = tree.getroot() - if (root.tag == "interface" and "version" in root.attrib): + if (root.tag == "interface" and "version" and "minVersion" in root.attrib): check_version_format(root.attrib["version"]) array = (root.attrib["version"]).split(".") major_version = array[0] minor_version = array[1] patch_version = array[2] - if (major_version.isdigit() and minor_version.isdigit() and patch_version.isdigit): - data_for_storage = prepare_data_for_storage(major_version, minor_version, patch_version) + + check_minimum_version_format(root.attrib["minVersion"]) + minimum_version_array = (root.attrib["minVersion"]).split(".") + if (len(minimum_version_array) == 2): + minimum_version_array.append("0") + minimum_major_version = minimum_version_array[0] + minimum_minor_version = minimum_version_array[1] + minimum_patch_version = minimum_version_array[2] + + if (major_version.isdigit() and minor_version.isdigit() and patch_version.isdigit() and + minimum_major_version.isdigit() and minimum_minor_version.isdigit() and minimum_patch_version.isdigit()): + data_for_storage = prepare_data_for_storage(major_version, minor_version, patch_version, + minimum_major_version, minimum_minor_version, minimum_patch_version) store_data_to_file(path_to_storage, data_for_storage) else: raise RPCBase.ParseError("Attribute version has incorect value in MOBILE_API.xml") @@ -45,7 +56,16 @@ def check_version_format(version): raise RPCBase.ParseError("Incorrect format of version please check MOBILE_API.xml. " "Need format of version major_version.minor_version.patch_version") -def prepare_data_for_storage(major_version, minor_version, patch_version): + +def check_minimum_version_format(version): + """Checks correctness of format of version + """ + p = re.compile('\d+\\.\d+\\.\d+|\d+\\.\d+') + result = p.match(version) + if result == None or (result.end() != len(version)): + raise RPCBase.ParseError("Incorrect format of version please check MOBILE_API.xml. " + "Need format of minVersion major_version.minor_version or major_version.minor_version.patch_version") +def prepare_data_for_storage(major_version, minor_version, patch_version, minimum_major_version, minimum_minor_version, minimum_patch_version): """Prepares data to store to file. """ temp = Template( @@ -80,8 +100,12 @@ def prepare_data_for_storage(major_version, minor_version, patch_version): u'''const uint16_t major_version = $m_version;\n''' u'''const uint16_t minor_version = $min_version;\n''' u'''const uint16_t patch_version = $p_version;\n''' + u'''const uint16_t minimum_major_version = $min_major_version;\n''' + u'''const uint16_t minimum_minor_version = $min_minor_version;\n''' + u'''const uint16_t minimum_patch_version = $min_patch_version;\n''' u'''} // namespace application_manager\n''' u'''#endif // GENERATED_MSG_VERSION_H''') - data_to_file = temp.substitute(m_version = major_version, min_version = minor_version, p_version = patch_version) + data_to_file = temp.substitute(m_version = major_version, min_version = minor_version, p_version = patch_version, + min_major_version = minimum_major_version, min_minor_version = minimum_minor_version, min_patch_version = minimum_patch_version) return data_to_file diff --git a/tools/InterfaceGenerator/generator/Model.py b/tools/InterfaceGenerator/generator/Model.py index ee458d934a..c4d2eca0bd 100755 --- a/tools/InterfaceGenerator/generator/Model.py +++ b/tools/InterfaceGenerator/generator/Model.py @@ -124,7 +124,8 @@ class InterfaceItemBase(object): """ def __init__(self, name, description=None, design_description=None, - issues=None, todos=None, platform=None, default_value=None, scope=None): + issues=None, todos=None, platform=None, default_value=None, scope=None, + since=None, until=None, deprecated=None, removed=None): self.name = name self.description = description if description is not None else [] self.design_description = \ @@ -134,6 +135,10 @@ class InterfaceItemBase(object): self.platform = platform self.default_value = default_value self.scope = scope + self.since = since + self.until = until + self.deprecated = deprecated + self.removed = removed class EnumElement(InterfaceItemBase): @@ -149,13 +154,18 @@ class EnumElement(InterfaceItemBase): def __init__(self, name, description=None, design_description=None, issues=None, todos=None, platform=None, internal_name=None, - value=None): + value=None, since=None, until=None, deprecated=None, removed=None): super(EnumElement, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, platform=platform) self.internal_name = internal_name self.value = value + self.since = since + self.until = until + self.deprecated = deprecated + self.removed = removed + @property def primary_name(self): @@ -180,7 +190,7 @@ class Enum(InterfaceItemBase): def __init__(self, name, description=None, design_description=None, issues=None, todos=None, platform=None, internal_scope=None, - elements=None, scope=None): + elements=None, scope=None, since=None, until=None, deprecated=None, removed=None): super(Enum, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, @@ -189,6 +199,10 @@ class Enum(InterfaceItemBase): self.internal_scope = internal_scope self.elements = \ elements if elements is not None else collections.OrderedDict() + self.since = since + self.until = until + self.deprecated = deprecated + self.removed = removed class EnumSubset(InterfaceItemBase): @@ -204,7 +218,7 @@ class EnumSubset(InterfaceItemBase): def __init__(self, name, enum, description=None, design_description=None, issues=None, todos=None, platform=None, - allowed_elements=None): + allowed_elements=None, since=None, until=None, deprecated=None, removed=None): super(EnumSubset, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, @@ -213,6 +227,10 @@ class EnumSubset(InterfaceItemBase): self.enum = enum self.allowed_elements = \ allowed_elements if allowed_elements is not None else {} + self.since = since + self.until = until + self.deprecated = deprecated + self.removed = removed class Param(InterfaceItemBase): @@ -229,7 +247,8 @@ class Param(InterfaceItemBase): def __init__(self, name, param_type, description=None, design_description=None, issues=None, todos=None, - platform=None, is_mandatory=True, default_value=None, scope=None): + platform=None, is_mandatory=True, default_value=None, scope=None, + since=None, until=None, deprecated=None, removed=None): super(Param, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, @@ -238,6 +257,10 @@ class Param(InterfaceItemBase): self.is_mandatory = is_mandatory self.param_type = param_type self.default_value = default_value + self.since = since + self.until = until + self.deprecated = deprecated + self.removed=removed class FunctionParam(Param): @@ -251,11 +274,13 @@ class FunctionParam(Param): def __init__(self, name, param_type, description=None, design_description=None, issues=None, todos=None, - platform=None, is_mandatory=True, default_value=None, scope=None): + platform=None, is_mandatory=True, default_value=None, scope=None, + since=None, until=None, deprecated=None, removed=None): super(FunctionParam, self).__init__( name, param_type=param_type, description=description, design_description=design_description, issues=issues, todos=todos, - platform=platform, is_mandatory=is_mandatory, default_value=default_value, scope=scope) + platform=platform, is_mandatory=is_mandatory, default_value=default_value, + scope=scope, since=since, until=until, deprecated=deprecated, removed=removed) self.default_value = default_value @@ -270,12 +295,15 @@ class Struct(InterfaceItemBase): """ def __init__(self, name, description=None, design_description=None, - issues=None, todos=None, platform=None, members=None, scope=None): + issues=None, todos=None, platform=None, members=None, scope=None, + since=None, until=None, deprecated=None, removed=None): super(Struct, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, - platform=platform, scope=scope) + platform=platform, scope=scope, since=since, until=until, + deprecated=deprecated, removed=removed) + print since self.members = \ members if members is not None else collections.OrderedDict() @@ -293,11 +321,11 @@ class Function(InterfaceItemBase): def __init__(self, name, function_id, message_type, description=None, design_description=None, issues=None, todos=None, - platform=None, params=None, scope=None): + platform=None, params=None, scope=None, since=None, until=None, deprecated=None, removed=None): super(Function, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, - platform=platform, scope=scope) + platform=platform, scope=scope, since=None, until=None, deprecated=None, removed=None) self.function_id = function_id self.message_type = message_type diff --git a/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py index 0c500dee8e..05dd939ad0 100755 --- a/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py +++ b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py @@ -505,7 +505,8 @@ class CodeGenerator(object): String with structs implementation source code. """ - + #print struct.name + #print struct.since processed_enums = [] return self._struct_impl_template.substitute( namespace=namespace, @@ -518,7 +519,7 @@ class CodeGenerator(object): schema_items_decl=self._gen_schema_items_decls( struct.members.values()), schema_item_fill=self._gen_schema_items_fill( - struct.members.values())), + struct.members.values(), struct.since, struct.until, struct.deprecated, struct.removed)), 1)) def _gen_schema_loc_decls(self, members, processed_enums): @@ -746,7 +747,7 @@ class CodeGenerator(object): return result - def _gen_schema_items_fill(self, members): + def _gen_schema_items_fill(self, members=None, since=None, until=None, deprecated=None, removed=None): """Generate schema items fill code. Generates source code that fills new schema with items. @@ -760,7 +761,7 @@ class CodeGenerator(object): """ result = u"\n".join( - [self._gen_schema_item_fill(x) for x in members]) + [self._gen_schema_item_fill(x, since, until, deprecated, removed) for x in members]) return u"".join([result, u"\n\n"]) if result else u"" @@ -781,7 +782,7 @@ class CodeGenerator(object): raise GenerateError("Unexpected call to the unimplemented function.") - def _gen_schema_item_fill(self, member): + def _gen_schema_item_fill(self, member, since, until, deprecated, removed): """Generate schema item fill code. Generates source code that fills new schema with item. @@ -793,11 +794,29 @@ class CodeGenerator(object): String with schema item fill code. """ - - return self._impl_code_item_fill_template.substitute( - name=member.name, - var_name=self._gen_schema_item_var_name(member), - is_mandatory=u"true" if member.is_mandatory is True else u"false") + #print(member.since) + #print member.name + if (since is not None or + until is not None or + deprecated is not None or + removed is not None or + member.since is not None or + member.until is not None or + member.deprecated is not None or + member.removed is not None): + return self._impl_code_item_fill_template_with_version.substitute( + name=member.name, + var_name=self._gen_schema_item_var_name(member), + is_mandatory=u"true" if member.is_mandatory is True else u"false", + since=member.since if member.since is not None else since if since is not None else "", + until=member.until if member.until is not None else until if until is not None else "", + deprecated=member.deprecated if member.deprecated is not None else deprecated if deprecated is not None else u"false", + removed=member.removed if member.removed is not None else removed if removed is not None else u"false") + else: + return self._impl_code_item_fill_template.substitute( + name=member.name, + var_name=self._gen_schema_item_var_name(member), + is_mandatory=u"true" if member.is_mandatory is True else u"false") @staticmethod def _gen_schema_item_var_name(member): @@ -899,7 +918,7 @@ class CodeGenerator(object): schema_items_decl=self._gen_schema_items_decls( function.params.values()), schema_item_fill=self._gen_schema_items_fill( - function.params.values()), + function.params.values(), function.since, function.until, function.deprecated, function.removed), schema_params_fill=self._gen_schema_params_fill( function.message_type.name)), 1)) @@ -1531,6 +1550,10 @@ class CodeGenerator(object): u'''schema_members["${name}"] = CObjectSchemaItem::''' u'''SMember(${var_name}, ${is_mandatory});''') + _impl_code_item_fill_template_with_version = string.Template( + u'''schema_members["${name}"] = CObjectSchemaItem::''' + u'''SMember(${var_name}, ${is_mandatory}, "${since}", "${until}", ${deprecated}, ${removed});''') + _function_impl_template = string.Template( u'''CSmartSchema $namespace::$class_name::''' u'''InitFunction_${function_id}_${message_type}(\n''' diff --git a/tools/InterfaceGenerator/generator/parsers/RPCBase.py b/tools/InterfaceGenerator/generator/parsers/RPCBase.py index 4853916dad..d3e103ce7a 100755 --- a/tools/InterfaceGenerator/generator/parsers/RPCBase.py +++ b/tools/InterfaceGenerator/generator/parsers/RPCBase.py @@ -6,7 +6,7 @@ Contains base parser for SDLRPC v1/v2 and JSON RPC XML format. import collections import xml.etree.ElementTree - +import re from generator import Model @@ -203,16 +203,35 @@ class Parser(object): internal_scope = None scope = None + since = None + until = None + deprecated = None + removed = None + result = None for attribute in attributes: if attribute == "internal_scope": internal_scope = attributes[attribute] elif attribute == "scope": scope = attributes[attribute] + elif attribute == "since": + result = self._parse_version(attributes[attribute]) + since = result + elif attribute == "until": + result = self._parse_version(attributes[attribute]) + until = result + elif attribute == "deprecated": + deprecated = attributes[attribute] + elif attribute == "removed": + removed = attributes[attribute] else: raise ParseError("Unexpected attribute '" + attribute + "' in enum '" + params["name"] + "'") params["internal_scope"] = internal_scope params["scope"] = scope + params["since"] = since + params["until"] = until + params["deprecated"] = deprecated + params["removed"] = removed elements = collections.OrderedDict() for subelement in subelements: @@ -236,13 +255,32 @@ class Parser(object): params, subelements, attrib = self._parse_base_item(element, prefix) scope = None + since = None + until = None + deprecated = None + removed = None + result = None for attribute in attrib: if attribute == "scope": scope = attrib[attribute] + elif attribute == "since": + result = self._parse_version(attrib[attribute]) + since = result + elif attribute == "until": + result = self._parse_version(attrib[attribute]) + until = result + elif attribute == "deprecated": + deprecated = attributes[attribute] + elif attribute == "removed": + removed = attrib[attribute] else: raise ParseError("Unexpected attribute '" + attribute + "' in struct '" + params["name"] + "'") params["scope"] = scope + params["since"] = since + params["until"] = until + params["deprecated"] = deprecated + params["removed"] = removed members = collections.OrderedDict() for subelement in subelements: @@ -271,13 +309,32 @@ class Parser(object): attributes) scope = None + since = None + until = None + deprecated = None + removed = None + result = None for attribute in attributes: if attribute == "scope": scope = attributes[attribute] + elif attribute == "since": + result = self._parse_version(attributes[attribute]) + since = result + elif attribute == "until": + result = self._parse_version(attributes[attribute]) + until = result + elif attribute == "deprecated": + deprecated = attributes[attribute] + elif attribute == "removed": + removed = attributes[attribute] params["function_id"] = function_id params["message_type"] = message_type params["scope"] = scope + params["since"] = since + params["until"] = until + params["deprecated"] = deprecated + params["removed"] = removed function_params = collections.OrderedDict() for subelement in subelements: @@ -443,6 +500,11 @@ class Parser(object): internal_name = None value = None + since = None + until = None + deprecated = None + removed = None + result = None for attribute in attributes: if attribute == "internal_name": internal_name = attributes[attribute] @@ -452,9 +514,22 @@ class Parser(object): except: raise ParseError("Invalid value for enum element: '" + attributes[attribute] + "'") + elif attribute == "since": + result = self._parse_version(attributes[attribute]) + since = result + elif attribute == "until": + result = self._parse_version(attributes[attribute]) + until = result + elif attribute == "deprecated": + deprecated = attributes[attribute] + elif attribute == "removed": + removed = attributes[attribute] params["internal_name"] = internal_name params["value"] = value - + params["since"] = since + params["until"] = until + params["deprecated"] = deprecated + params["removed"] = removed # Magic usage is correct # pylint: disable=W0142 return Model.EnumElement(**params) @@ -548,6 +623,27 @@ class Parser(object): """ params, subelements, attrib = self._parse_base_item(element, "") + since_version = self._extract_attrib(attrib, "since") + if since_version is not None: + result = self._parse_version(since_version) + params["since"] = result + + until_version = self._extract_attrib(attrib, "until") + if until_version is not None: + result = self._parse_version(until_version) + params["until"] = result + + deprecated = self._extract_attrib(attrib, "deprecated") + if deprecated is not None: + params["deprecated"] = deprecated + + removed = self._extract_attrib(attrib, "removed") + if removed is not None: + params["removed"] = removed + print("FOUND REMOVED!!!!!") + print(params["name"]) + + is_mandatory = self._extract_attrib(attrib, "mandatory") if is_mandatory is None: raise ParseError("'mandatory' is not specified for parameter '" + @@ -765,3 +861,22 @@ class Parser(object): print ("Ignoring attribute '" + name + "'") return True + + def _parse_version(self, version): + """ + Validates if a version supplied is in the correct + format of Major.Minor.Patch. If Major.Minor format + is supplied, a patch version of 0 will be added to + the end. + """ + p = re.compile('\d+\\.\d+\\.\d+|\d+\\.\d+') + result = p.match(version) + if result == None or (result.end() != len(version)): + raise RPCBase.ParseError("Incorrect format of version please check MOBILE_API.xml. " + "Need format of major_version.minor_version or major_version.minor_version.patch_version") + + version_array = version.split(".") + if (len(version_array) == 2): + version_array.append("0") + dot_str = "." + return dot_str.join(version_array) |