diff options
author | Jacob Keeler <jacob.keeler@livioradio.com> | 2018-10-11 12:15:43 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-11 12:15:43 -0400 |
commit | 8da2a76d7dbde7845c1116034f8a60490f4fad0c (patch) | |
tree | 0dfb877361830f95dacfdf2174163de4335a03cb | |
parent | 74a6624e3d87ab3c0a6606f4d825a8e8b9c57041 (diff) | |
parent | 7ce7731d58ac59eb561af17881f3fba29a5f7dc8 (diff) | |
download | sdl_core-8da2a76d7dbde7845c1116034f8a60490f4fad0c.tar.gz |
Merge pull request #2667 from smartdevicelink/fix/merge_interior_vehicle_data_cache
Merge module data instead of outright replacing each element
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc index 0eb175aa25..780aab537b 100644 --- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc @@ -34,6 +34,7 @@ #include <thread> #include <chrono> #include "rc_rpc_plugin/interior_data_cache_impl.h" +#include "application_manager/smart_object_keys.h" #include "utils/date_time.h" #include "utils/logger.h" @@ -46,7 +47,7 @@ InteriorDataCacheImpl::InteriorDataCacheImpl() {} InteriorDataCacheImpl::~InteriorDataCacheImpl() {} /** - * @brief MergeModuleData key all keys and values from first parameter and + * @brief MergeModuleData all keys and values from first parameter and * update and append keys and values from the second * @param data1 - initial data * @param data2 - updated data @@ -54,17 +55,87 @@ InteriorDataCacheImpl::~InteriorDataCacheImpl() {} */ smart_objects::SmartObject MergeModuleData( const smart_objects::SmartObject& data1, + const smart_objects::SmartObject& data2); + +/** + * @brief MergeArray merge two arrays if their elements contain an `id` + * parameter + * @param data1 - initial data + * @param data2 - updated data + * @return updated data1 with any values in data2 if the arrays can be merged, + * otherwise data2 + */ +smart_objects::SmartObject MergeArray(const smart_objects::SmartObject& data1, + const smart_objects::SmartObject& data2); + +smart_objects::SmartObject MergeModuleData( + const smart_objects::SmartObject& data1, const smart_objects::SmartObject& data2) { smart_objects::SmartObject result = data1; auto it = data2.map_begin(); for (; it != data2.map_end(); ++it) { const std::string& key = it->first; - const smart_objects::SmartObject& value = it->second; + smart_objects::SmartObject& value = it->second; + if (!result.keyExists(key) || value.getType() != result[key].getType()) { + result[key] = value; + continue; + } + + // Merge maps and arrays with `id` param included, replace other types + if (value.getType() == smart_objects::SmartType::SmartType_Map) { + value = MergeModuleData(result[key], value); + } else if (value.getType() == smart_objects::SmartType::SmartType_Array) { + value = MergeArray(result[key], value); + } result[key] = value; } return result; } +smart_objects::SmartObject MergeArray(const smart_objects::SmartObject& data1, + const smart_objects::SmartObject& data2) { + // Merge data only in the case where each value in the array is an Object with + // an ID included, otherwise replace + bool array_contains_objects = + !data2.empty() && + data2.getElement(0).getType() != smart_objects::SmartType::SmartType_Map; + bool can_merge_arrays = + array_contains_objects && + data2.getElement(0).keyExists(application_manager::strings::id); + if (!can_merge_arrays) { + return data2; + } + + smart_objects::SmartObject result = data1; + smart_objects::SmartArray* result_array = result.asArray(); + smart_objects::SmartArray* data_array = data2.asArray(); + auto data_it = data_array->begin(); + auto find_by_id = + [](smart_objects::SmartArray* array, const smart_objects::SmartObject& id) + -> smart_objects::SmartArray::iterator { + auto it = std::find_if( + array->begin(), + array->end(), + [&id](smart_objects::SmartObject& obj) -> bool { + return obj[application_manager::strings::id] == id; + }); + return it; + }; + + for (; data_it != data_array->end(); ++data_it) { + const smart_objects::SmartObject element_id = + (*data_it)[application_manager::strings::id]; + auto result_it = find_by_id(result_array, element_id); + + if (result_it != result_array->end()) { + *result_it = MergeModuleData(*result_it, *data_it); + } else { + result_array->push_back(*data_it); + } + } + return result; +} + void InteriorDataCacheImpl::Add(const std::string& module_type, const smart_objects::SmartObject& module_data) { LOG4CXX_TRACE(logger_, "module_type : " << module_type); |