Helper function - GetOneOrMany 68/50268/3
authorTomasz Iwanek <t.iwanek@samsung.com>
Fri, 23 Oct 2015 12:19:11 +0000 (14:19 +0200)
committerPawel Sikorski <p.sikorski@samsung.com>
Thu, 29 Oct 2015 15:04:25 +0000 (08:04 -0700)
Refactored part of code to avoid copy paste of checking element
type - list or dictionary.

Change-Id: I685da172f32964296884280e5b50f595ae6da6c2

src/manifest_handlers/service_handler.cc
src/manifest_handlers/widget_handler.cc
src/manifest_parser/manifest_handler.cc
src/manifest_parser/manifest_handler.h
src/tpk_manifest_handlers/ui_application_handler.cc

index f8355b1..8115243 100644 (file)
@@ -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<std::string> 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<parser::ManifestData>* 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<ServiceList> 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<parser::ManifestData>(services_data);
   return true;
 }
index 4055a79..c767931 100644 (file)
@@ -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<parser::ManifestData>(widget_info);
index 1d3ca2a..82c80b2 100644 (file)
@@ -38,6 +38,38 @@ bool VerifyElementNamespace(
   return element_namespace == requested_namespace;
 }
 
+const std::vector<const DictionaryValue*> GetOneOrMany(
+    const DictionaryValue* dict, const std::string& path,
+    const std::string& namespace_prefix) {
+  std::vector<const DictionaryValue*> 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;
 }
index 8ebf9fa..124c96b 100644 (file)
@@ -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<const DictionaryValue*> GetOneOrMany(
+    const DictionaryValue* dict, const std::string& path,
+    const std::string& namespace_prefix);
 
 typedef std::map<std::string, ManifestHandler*> ManifestHandlerMap;
 typedef std::map<ManifestHandler*, int> ManifestHandlerOrderMap;
index af96367..2a718e8 100644 (file)
@@ -475,40 +475,16 @@ bool UIApplicationHandler::Parse(
     std::string* error) {
   std::shared_ptr<UIApplicationInfoList>
                   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<parser::ManifestData>(uiapplicationinfo);
   return true;
 }