From: Tomasz Iwanek Date: Fri, 23 Oct 2015 12:19:11 +0000 (+0200) Subject: Helper function - GetOneOrMany X-Git-Tag: accepted/tizen/mobile/20151105.020208~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c8ad6e8e6a3f17f853bfd402b032a44b25bb34b4;p=platform%2Fcore%2Fappfw%2Fmanifest-parser.git Helper function - GetOneOrMany Refactored part of code to avoid copy paste of checking element type - list or dictionary. Change-Id: I685da172f32964296884280e5b50f595ae6da6c2 --- diff --git a/src/manifest_handlers/service_handler.cc b/src/manifest_handlers/service_handler.cc index f8355b1..8115243 100644 --- a/src/manifest_handlers/service_handler.cc +++ b/src/manifest_handlers/service_handler.cc @@ -21,52 +21,21 @@ namespace { bool ParseServiceContent(const parser::DictionaryValue* dict, wgt::parse::ServiceInfo* service_info, std::string* error) { - const parser::Value* value = nullptr; - if (!dict->Get(keys::kTizenServiceContentKey, &value)) { - *error = "Missing tizen:content tag in tizen:service"; - return false; - } std::string content; bool found = false; - if (value->GetType() == parser::Value::TYPE_LIST) { - const parser::ListValue* list = nullptr; - value->GetAsList(&list); - for (auto& item : *list) { - const parser::DictionaryValue* dict = nullptr; - if (!item->GetAsDictionary(&dict)) { - *error = "Failed to parse tizen:content"; - return false; - } - if (!parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - continue; - } - if (found) { - *error = "tizen:content element of tizen:service " - "should be declared only once"; - return false; - } - found = true; - if (!dict->GetString(keys::kTizenServiceContentSrcKey, &content)) { - *error = - "Missing 'src' attribute in tizen:content tag in tizen:service"; - return false; - } - } - } else if (value->GetType() == parser::Value::TYPE_DICTIONARY) { - const parser::DictionaryValue* dict = nullptr; - value->GetAsDictionary(&dict); - if (!parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - *error = "Missing tizen:content tag in tizen:service"; + for (auto& item : parser::GetOneOrMany(dict, keys::kTizenServiceContentKey, + keys::kTizenNamespacePrefix)) { + if (found) { + *error = "tizen:content element of tizen:service " + "should be declared only once"; return false; } - if (!dict->GetString(keys::kTizenServiceContentSrcKey, &content)) { - *error = "Missing 'src' attribute in tizen:content tag in tizen:service"; + found = true; + if (!item->GetString(keys::kTizenServiceContentSrcKey, &content)) { + *error = + "Missing 'src' attribute in tizen:content tag in tizen:service"; return false; } - found = true; - } else { - *error = "Failed to parse tizen:content element of service"; - return false; } if (!found) { *error = "Missing tizen:content tag in tizen:service"; @@ -77,51 +46,23 @@ bool ParseServiceContent(const parser::DictionaryValue* dict, } bool ParseServiceIcon(const parser::DictionaryValue* dict, - wgt::parse::ServiceInfo* service_info, - std::string* error) { - const parser::Value* value = nullptr; - if (!dict->Get(keys::kTizenServiceIconKey, &value)) - return true; + wgt::parse::ServiceInfo* service_info, + std::string* error) { std::string icon; - if (value->GetType() == parser::Value::TYPE_LIST) { - const parser::ListValue* list = nullptr; - value->GetAsList(&list); - bool found = true; - for (auto& item : *list) { - const parser::DictionaryValue* dict = nullptr; - if (!item->GetAsDictionary(&dict)) { - *error = "Failed to parse tizen:icon"; - return false; - } - if (!parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - continue; - } - if (found) { - *error = "tizen:icon element of tizen:service " - "should be declared only once"; - return false; - } - found = true; - if (!dict->GetString(keys::kTizenServiceIconSrcKey, &icon)) { - *error = - "Missing 'src' attribute in tizen:icon tag in tizen:service"; - return false; - } + const auto& items = parser::GetOneOrMany(dict, keys::kTizenServiceIconKey, + keys::kTizenNamespacePrefix); + if (!items.empty()) { + if (items.size() > 1) { + *error = "tizen:icon element of tizen:service " + "should be declared only once"; + return false; } - } else if (value->GetType() == parser::Value::TYPE_DICTIONARY) { - const parser::DictionaryValue* dict = nullptr; - value->GetAsDictionary(&dict); - if (parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - if (!dict->GetString(keys::kTizenServiceIconSrcKey, &icon)) { - *error = "Missing 'src' attribute in tizen:icon tag in tizen:service"; - return false; - } + if (!items[0]->GetString(keys::kTizenServiceIconSrcKey, &icon)) { + *error = "Missing 'src' attribute in tizen:icon tag in tizen:service"; + return false; } - } else { - *error = "Failed to parse tizen:icon element of service"; - return false; + service_info->set_icon(icon); } - service_info->set_icon(icon); return true; } @@ -132,83 +73,34 @@ bool ParseServiceDescription(const parser::DictionaryValue* dict, if (!dict->Get(keys::kTizenServiceDescriptionKey, &value)) return true; std::string description; - if (value->GetType() == parser::Value::TYPE_LIST) { - const parser::ListValue* list = nullptr; - value->GetAsList(&list); - bool found = true; - for (auto& item : *list) { - const parser::DictionaryValue* dict = nullptr; - if (!item->GetAsDictionary(&dict)) { - *error = "Failed to parse tizen:description"; - return false; - } - if (!parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - continue; - } - if (found) { - *error = "tizen:description element of tizen:service " - "should be declared only once"; - return false; - } - found = true; - dict->GetString(keys::kXmlTextKey, &description); - } - } else if (value->GetType() == parser::Value::TYPE_DICTIONARY) { - const parser::DictionaryValue* dict = nullptr; - value->GetAsDictionary(&dict); - if (parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - dict->GetString(keys::kXmlTextKey, &description); + const auto& items = parser::GetOneOrMany(dict, + keys::kTizenServiceDescriptionKey, + keys::kTizenNamespacePrefix); + if (!items.empty()) { + if (items.size() > 1) { + *error = "tizen:description element of tizen:service " + "should be declared only once"; + return false; } - } else { - *error = "Failed to parse tizen:description element of service"; - return false; + items[0]->GetString(keys::kXmlTextKey, &description); + service_info->set_description(description); } - service_info->set_description(description); return true; } bool ParseServiceCategory(const parser::DictionaryValue* dict, wgt::parse::ServiceInfo* service_info, std::string* error) { - const parser::Value* value = nullptr; - if (!dict->Get(keys::kTizenServiceCategoryKey, &value)) - return true; std::vector categories; - if (value->GetType() == parser::Value::TYPE_LIST) { - const parser::ListValue* list = nullptr; - value->GetAsList(&list); - for (auto& item : *list) { - const parser::DictionaryValue* dict = nullptr; - if (!item->GetAsDictionary(&dict)) { - *error = "Failed to parse tizen:category"; - return false; - } - if (!parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - continue; - } - std::string category; - if (!dict->GetString(keys::kTizenServiceCategoryNameKey, &category)) { - *error = - "Missing 'name' attribute of tizen:category tag in tizen:service"; - return false; - } - categories.push_back(category); - } - } else if (value->GetType() == parser::Value::TYPE_DICTIONARY) { - const parser::DictionaryValue* dict = nullptr; - value->GetAsDictionary(&dict); - if (parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - std::string category; - if (!dict->GetString(keys::kTizenServiceCategoryNameKey, &category)) { - *error = - "Missing 'name' attribute of tizen:category tag in tizen:service"; - return false; - } - categories.push_back(category); + for (auto& item : parser::GetOneOrMany(dict, keys::kTizenServiceCategoryKey, + keys::kTizenNamespacePrefix)) { + std::string category; + if (!item->GetString(keys::kTizenServiceCategoryNameKey, &category)) { + *error = + "Missing 'name' attribute of tizen:category tag in tizen:service"; + return false; } - } else { - *error = "Failed to parse tizen:category element of service"; - return false; + categories.push_back(category); } service_info->set_categories(categories); return true; @@ -217,47 +109,18 @@ bool ParseServiceCategory(const parser::DictionaryValue* dict, bool ParseServiceName(const parser::DictionaryValue* dict, wgt::parse::ServiceInfo* service_info, std::string* error) { - const parser::Value* value = nullptr; - if (!dict->Get(keys::kTizenServiceNameKey, &value)) { - *error = "Missing tizen:name tag in tizen:service. " - "At least one must be declared"; - return false; - } wgt::parse::LangNameVector names; - if (value->GetType() == parser::Value::TYPE_LIST) { - const parser::ListValue* list = nullptr; - value->GetAsList(&list); - for (auto& item : *list) { - const parser::DictionaryValue* dict = nullptr; - if (!item->GetAsDictionary(&dict)) { - *error = "Failed to parse tizen:name"; - return false; - } - if (!parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - continue; - } - std::string lang; - std::string name; - dict->GetString(keys::kXmlLangKey, &lang); - dict->GetString(keys::kXmlTextKey, &name); - names.emplace_back(lang, name); - } - } else if (value->GetType() == parser::Value::TYPE_DICTIONARY) { - const parser::DictionaryValue* dict = nullptr; - value->GetAsDictionary(&dict); - if (parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - std::string lang; - std::string name; - dict->GetString(keys::kXmlLangKey, &lang); - dict->GetString(keys::kXmlTextKey, &name); - names.emplace_back(lang, name); - } - } else { - *error = "Failed to parse tizen:name element of service"; - return false; + for (auto& item : parser::GetOneOrMany(dict, keys::kTizenServiceNameKey, + keys::kTizenNamespacePrefix)) { + std::string lang; + std::string name; + item->GetString(keys::kXmlLangKey, &lang); + item->GetString(keys::kXmlTextKey, &name); + names.emplace_back(lang, name); } if (names.empty()) { - *error = "Cannot find tizen:name element for tizen:service"; + *error = "Cannot find tizen:name element for tizen:service. " + "At least one must be provided."; return false; } service_info->set_names(names); @@ -267,41 +130,17 @@ bool ParseServiceName(const parser::DictionaryValue* dict, bool ParseServiceMetadata(const parser::DictionaryValue* dict, wgt::parse::ServiceInfo* service_info, std::string* error) { - const parser::Value* value = nullptr; - if (!dict->Get(keys::kTizenServiceMetadataKey, &value)) - return true; wgt::parse::KeyValueVector metadata_set; - if (value->GetType() == parser::Value::TYPE_LIST) { - const parser::ListValue* list = nullptr; - value->GetAsList(&list); - for (auto& item : *list) { - const parser::DictionaryValue* dict = nullptr; - if (!item->GetAsDictionary(&dict)) { - *error = "Failed to parse tizen:metadata"; - return false; - } - if (!parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - continue; - } - std::string key; - std::string value; - dict->GetString(keys::kTizenServiceMetadataKeyKey, &key); - dict->GetString(keys::kTizenServiceMetadataValueKey, &value); - metadata_set.emplace_back(key, value); - } - } else if (value->GetType() == parser::Value::TYPE_DICTIONARY) { - const parser::DictionaryValue* dict = nullptr; - value->GetAsDictionary(&dict); - if (parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - std::string key; - std::string value; - dict->GetString(keys::kTizenServiceMetadataKeyKey, &key); - dict->GetString(keys::kTizenServiceMetadataValueKey, &value); - metadata_set.emplace_back(key, value); + for (auto& item : parser::GetOneOrMany(dict, keys::kTizenServiceMetadataKey, + keys::kTizenNamespacePrefix)) { + std::string key; + std::string value; + if (!item->GetString(keys::kTizenServiceMetadataKeyKey, &key)) { + *error = "'key' attribute of metadata is obligatory"; + return false; } - } else { - *error = "Failed to parse tizen:metadata element of service"; - return false; + item->GetString(keys::kTizenServiceMetadataValueKey, &value); + metadata_set.emplace_back(key, value); } service_info->set_metadata_set(metadata_set); return true; @@ -367,39 +206,17 @@ bool ServiceHandler::Parse( const parser::Manifest& manifest, std::shared_ptr* output, std::string* error) { - const parser::Value* services = nullptr; - if (!manifest.Get(keys::kTizenServiceKey, &services)) { + if (!manifest.HasPath(keys::kTizenServiceKey)) { return true; } - std::shared_ptr services_data(new ServiceList()); - - if (services->IsType(parser::Value::TYPE_DICTIONARY)) { - const parser::DictionaryValue* dict = nullptr; - services->GetAsDictionary(&dict); - if (parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) { - auto service = ParseService(dict, error); - if (!service) - return false; - services_data->services.push_back(*service); - } - } else if (services->IsType(parser::Value::TYPE_LIST)) { - const parser::ListValue* list; - services->GetAsList(&list); - for (parser::ListValue::const_iterator it = list->begin(); - it != list->end(); ++it) { - const parser::DictionaryValue* dict = nullptr; - if (!(**it).GetAsDictionary(&dict)) - continue; - if (!parser::VerifyElementNamespace(*dict, keys::kTizenNamespacePrefix)) - continue; - auto service = ParseService(dict, error); - if (!service) - return false; - services_data->services.push_back(*service); - } + for (auto& item : parser::GetOneOrMany(manifest.value(), + keys::kTizenServiceKey, keys::kTizenNamespacePrefix)) { + auto service = ParseService(item, error); + if (!service) + return false; + services_data->services.push_back(*service); } - *output = std::static_pointer_cast(services_data); return true; } diff --git a/src/manifest_handlers/widget_handler.cc b/src/manifest_handlers/widget_handler.cc index 4055a79..c767931 100644 --- a/src/manifest_handlers/widget_handler.cc +++ b/src/manifest_handlers/widget_handler.cc @@ -222,30 +222,10 @@ void WidgetHandler::ParseAuthorElements( if (manifest.HasPath(keys::kAuthorKey)) { const parser::Value* author_value = nullptr; manifest.Get(keys::kAuthorKey, &author_value); - if (author_value->GetType() == parser::Value::TYPE_DICTIONARY) { - const parser::DictionaryValue* author_dict = nullptr; - author_value->GetAsDictionary(&author_dict); - if (!parser::VerifyElementNamespace(*author_dict, - keys::kWidgetNamespacePrefix)) - return; - ParseSingleAuthorElement(author_dict, info); - } else if (author_value->GetType() == parser::Value::TYPE_LIST) { - const parser::ListValue* author_list = nullptr; - author_value->GetAsList(&author_list); - for (auto& item : *author_list) { - const parser::DictionaryValue* author_dict = nullptr; - if (item->GetAsDictionary(&author_dict)) { - if (!parser::VerifyElementNamespace(*author_dict, - keys::kWidgetNamespacePrefix)) { - // not W3C author - continue; - } else { - ParseSingleAuthorElement(author_dict, info); - break; - } - } - } - } + auto& authors = parser::GetOneOrMany(manifest.value(), keys::kAuthorKey, + keys::kWidgetNamespacePrefix); + if (!authors.empty()) + ParseSingleAuthorElement(authors[0], info); } } @@ -298,32 +278,13 @@ bool WidgetHandler::Parse( if (manifest.HasPath(keys::kViewModesKey)) manifest.GetString(keys::kViewModesKey, &widget_info->viewmodes_); - if (manifest.HasPath(keys::kPreferencesKey)) { - const parser::Value* val = nullptr; - if (manifest.Get(keys::kPreferencesKey, &val)) { - if (val->GetType() == parser::Value::TYPE_LIST) { - // list of preferences - const parser::ListValue* pref_list; - if (val->GetAsList(&pref_list)) { - // get all preferences - for (const auto& pref : *pref_list) { - Preference* preference; - if (!ParserPreferenceItem(pref, &preference, error)) - return false; - widget_info->preferences_.push_back(preference); - } - } else { - *error = "Preference list exists in manifest, but is not accessible."; - return false; - } - } else if (val->GetType() == parser::Value::TYPE_DICTIONARY) { - // only one preference - Preference* pref; - if (!ParserPreferenceItem(val, &pref, error)) - return false; - widget_info->preferences_.push_back(pref); - } - } + for (auto& pref_dict : parser::GetOneOrMany(manifest.value(), + keys::kPreferencesKey, + keys::kWidgetNamespacePrefix)) { + Preference* preference = nullptr; + if (!ParserPreferenceItem(pref_dict, &preference, error)) + return false; + widget_info->preferences_.push_back(preference); } *output = std::static_pointer_cast(widget_info); diff --git a/src/manifest_parser/manifest_handler.cc b/src/manifest_parser/manifest_handler.cc index 1d3ca2a..82c80b2 100644 --- a/src/manifest_parser/manifest_handler.cc +++ b/src/manifest_parser/manifest_handler.cc @@ -38,6 +38,38 @@ bool VerifyElementNamespace( return element_namespace == requested_namespace; } +const std::vector GetOneOrMany( + const DictionaryValue* dict, const std::string& path, + const std::string& namespace_prefix) { + std::vector nodes; + const parser::Value* value = nullptr; + if (dict->Get(path, &value)) { + if (value->GetType() == parser::Value::TYPE_LIST) { + const parser::ListValue* list = nullptr; + value->GetAsList(&list); + for (auto& item : *list) { + const parser::DictionaryValue* dict = nullptr; + item->GetAsDictionary(&dict); + if (!namespace_prefix.empty() && + !VerifyElementNamespace(*dict, namespace_prefix)) + continue; + nodes.push_back(dict); + } + } else if (value->GetType() == parser::Value::TYPE_DICTIONARY) { + const parser::DictionaryValue* dict = nullptr; + value->GetAsDictionary(&dict); + if (namespace_prefix.empty() || + VerifyElementNamespace(*dict, namespace_prefix)) { + nodes.push_back(dict); + } + } else { + assert(false && + "This should not happen. Only element node can be resolved."); + } + } + return nodes; +} + bool ManifestHandler::AlwaysParseForKey() const { return false; } diff --git a/src/manifest_parser/manifest_handler.h b/src/manifest_parser/manifest_handler.h index 8ebf9fa..124c96b 100644 --- a/src/manifest_parser/manifest_handler.h +++ b/src/manifest_parser/manifest_handler.h @@ -82,6 +82,23 @@ class ManifestHandler { bool VerifyElementNamespace(const parser::DictionaryValue& dict, const std::string& requested_namespace); +/** + * @brief GetOneOrMany + * Provides vector of dictionary value pointers for given key + * + * This function is shortcut for query zero, one or more elements of given key. + * Client code receives "unified" type - list of items so that it do not need + * to check if underlaying values are lists or dictionaries. + * + * @param dict root dictionary where lookup should start + * @param path path to be resolved in tree + * @param namespace_prefix value of namespace which will be used to filter + * elements + * @return elements matching parameters + */ +const std::vector GetOneOrMany( + const DictionaryValue* dict, const std::string& path, + const std::string& namespace_prefix); typedef std::map ManifestHandlerMap; typedef std::map ManifestHandlerOrderMap; diff --git a/src/tpk_manifest_handlers/ui_application_handler.cc b/src/tpk_manifest_handlers/ui_application_handler.cc index af96367..2a718e8 100644 --- a/src/tpk_manifest_handlers/ui_application_handler.cc +++ b/src/tpk_manifest_handlers/ui_application_handler.cc @@ -475,40 +475,16 @@ bool UIApplicationHandler::Parse( std::string* error) { std::shared_ptr uiapplicationinfo(new UIApplicationInfoList()); - parser::Value* value = nullptr; - if (!manifest.Get(keys::kUIApplicationKey, &value)) + if (!manifest.HasPath(keys::kUIApplicationKey)) return true; - if (value->GetType() == parser::Value::TYPE_LIST) { - // multiple entries - const parser::ListValue* list = nullptr; - value->GetAsList(&list); - for (const auto& item : *list) { - const parser::DictionaryValue* ui_dict = nullptr; - if (!item->GetAsDictionary(&ui_dict)) { - *error = "Parsing ui-application element failed"; - return false; - } - - UIApplicationSingleEntry uiappentry; - if (!ParseUIApplicationAndStore(*ui_dict, &uiappentry, error)) - return false; - uiapplicationinfo->items.push_back(uiappentry); - } - } else if (value->GetType() == parser::Value::TYPE_DICTIONARY) { - // single entry - const parser::DictionaryValue* ui_dict = nullptr; - value->GetAsDictionary(&ui_dict); - + for (const auto& ui_dict : parser::GetOneOrMany( + manifest.value(), keys::kUIApplicationKey, "")) { UIApplicationSingleEntry uiappentry; if (!ParseUIApplicationAndStore(*ui_dict, &uiappentry, error)) return false; uiapplicationinfo->items.push_back(uiappentry); - } else { - *error = "Cannot parse ui-application element"; - return false; } - *output = std::static_pointer_cast(uiapplicationinfo); return true; }