Index: chrome/browser/chromeos/gdata/gdata_parser.cc |
diff --git a/chrome/browser/chromeos/gdata/gdata_parser.cc b/chrome/browser/chromeos/gdata/gdata_parser.cc |
index 8abd841be3c2903bbe6acb144633b459844be024..07fae117d3e699e17bbf031754b8e72f19703b7c 100644 |
--- a/chrome/browser/chromeos/gdata/gdata_parser.cc |
+++ b/chrome/browser/chromeos/gdata/gdata_parser.cc |
@@ -5,8 +5,10 @@ |
#include "chrome/browser/chromeos/gdata/gdata_parser.h" |
#include "base/basictypes.h" |
-#include "base/scoped_ptr.h" |
+#include "base/json/json_value_converter.h" |
+#include "base/memory/scoped_ptr.h" |
#include "base/string_number_conversions.h" |
+#include "base/string_piece.h" |
#include "base/string_util.h" |
#include "base/values.h" |
@@ -31,10 +33,12 @@ const char kPresentationTerm[] = "presentation"; |
const char kSchemeLabels[] = "http://schemas.google.com/g/2005/labels"; |
-const struct { |
+struct EntryKindMap { |
DocumentEntry::EntryKind kind; |
const char* entry; |
-} kEntryKindMap[] = { |
+}; |
+ |
+const EntryKindMap kEntryKindMap[] = { |
{ DocumentEntry::ITEM, "item" }, |
{ DocumentEntry::DOCUMENT, "document"}, |
{ DocumentEntry::SPREADSHEET, "spreadsheet" }, |
@@ -42,13 +46,14 @@ const struct { |
{ DocumentEntry::FOLDER, "folder"}, |
{ DocumentEntry::FILE, "file"}, |
{ DocumentEntry::PDF, "pdf"}, |
- { DocumentEntry::UNKNOWN, NULL} |
}; |
-const struct { |
+struct LinkTypeMap { |
Link::LinkType type; |
const char* rel; |
-} kLinkTypeMap[] = { |
+}; |
+ |
+const LinkTypeMap kLinkTypeMap[] = { |
{ Link::SELF, |
"self" }, |
{ Link::NEXT, |
@@ -77,34 +82,40 @@ const struct { |
"http://schemas.google.com/spreadsheets/2006#tablesfeed"}, |
{ Link::WORKSHEET_FEED, |
"http://schemas.google.com/spreadsheets/2006#worksheetsfeed"}, |
- { Link::UNKNOWN, |
- NULL} |
}; |
-const struct { |
+struct FeedLinkTypeMap { |
FeedLink::FeedLinkType type; |
const char* rel; |
-} kFeedLinkTypeMap[] = { |
+}; |
+ |
+const FeedLinkTypeMap kFeedLinkTypeMap[] = { |
{ FeedLink::ACL, |
"http://schemas.google.com/acl/2007#accessControlList" }, |
{ FeedLink::REVISIONS, |
"http://schemas.google.com/docs/2007/revisions" }, |
- { FeedLink::UNKNOWN, |
- NULL} |
}; |
-const struct { |
+struct CategoryTypeMap { |
Category::CategoryType type; |
const char* scheme; |
-} kCategoryTypeMap[] = { |
+}; |
+ |
+const CategoryTypeMap kCategoryTypeMap[] = { |
{ Category::KIND, |
"http://schemas.google.com/g/2005#kind" }, |
{ Category::LABEL, |
"http://schemas.google.com/g/2005/labels" }, |
- { Category::UNKNOWN, |
- NULL} |
}; |
+// Converts |url_string| to |result|. Always returns true to be used |
+// for JSONValueConverter::RegisterCustomField method. |
+// TODO(mukai): make it return false in case of invalid |url_string|. |
+bool GetGURLFromString(const base::StringPiece& url_string, GURL* result) { |
+ *result = GURL(url_string.as_string()); |
+ return true; |
+} |
+ |
} // namespace |
const char Author::kNameField[] = "name.$t"; |
@@ -113,12 +124,11 @@ const char Author::kEmailField[] = "email.$t"; |
Author::Author() { |
} |
-bool Author::Parse(const DictionaryValue* dictionary) { |
- if (dictionary->GetString(kNameField, &name_) && |
- dictionary->GetString(kEmailField, &email_)) { |
- return true; |
- } |
- return false; |
+// static |
+void Author::RegisterJSONConverter( |
+ base::JSONValueConverter<Author>* converter) { |
+ converter->RegisterStringField(kNameField, &Author::name_); |
+ converter->RegisterStringField(kEmailField, &Author::email_); |
} |
const char Link::kHrefField[] = "href"; |
@@ -129,31 +139,25 @@ const char Link::kTypeField[] = "type"; |
Link::Link() : type_(Link::UNKNOWN) { |
} |
-bool Link::Parse(const DictionaryValue* dictionary) { |
- std::string rel; |
- std::string href; |
- if (dictionary->GetString(kRelField, &rel) && |
- dictionary->GetString(kHrefField, &href) && |
- dictionary->GetString(kTypeField, &mime_type_)) { |
- href_ = GURL(href); |
- type_ = GetLinkType(rel); |
- if (type_ == Link::PARENT) |
- dictionary->GetString(kTitleField, &title_); |
- |
- if (type_ != Link::UNKNOWN) |
+// static. |
+bool Link::GetLinkType(const base::StringPiece& rel, Link::LinkType* result) { |
+ for (size_t i = 0; i < arraysize(kLinkTypeMap); i++) { |
+ if (rel == kLinkTypeMap[i].rel) { |
+ *result = kLinkTypeMap[i].type; |
return true; |
+ } |
} |
+ DVLOG(1) << "Unknown link type for rel " << rel; |
return false; |
} |
-// static. |
-Link::LinkType Link::GetLinkType(const std::string& rel) { |
- for (size_t i = 0; kLinkTypeMap[i].rel; i++) { |
- if (rel == kLinkTypeMap[i].rel) |
- return kLinkTypeMap[i].type; |
- } |
- DVLOG(1) << "Unknown link type for rel " << rel; |
- return Link::UNKNOWN; |
+// static |
+void Link::RegisterJSONConverter(base::JSONValueConverter<Link>* converter) { |
+ converter->RegisterCustomField<Link::LinkType>( |
+ kRelField, &Link::type_, &Link::GetLinkType); |
+ converter->RegisterCustomField(kHrefField, &Link::href_, &GetGURLFromString); |
+ converter->RegisterStringField(kTitleField, &Link::title_); |
+ converter->RegisterStringField(kTypeField, &Link::mime_type_); |
} |
const char FeedLink::kHrefField[] = "href"; |
@@ -162,78 +166,84 @@ const char FeedLink::kRelField[] = "rel"; |
FeedLink::FeedLink() : type_(FeedLink::UNKNOWN) { |
} |
-bool FeedLink::Parse(const DictionaryValue* dictionary) { |
- std::string rel; |
- std::string href; |
- if (dictionary->GetString(kRelField, &rel) && |
- dictionary->GetString(kHrefField, &href)) { |
- href_ = GURL(href); |
- type_ = GetFeedLinkType(rel); |
- if (type_ != FeedLink::UNKNOWN) |
+// static. |
+bool FeedLink::GetFeedLinkType( |
+ const base::StringPiece& rel, FeedLink::FeedLinkType* result) { |
+ for (size_t i = 0; i < arraysize(kFeedLinkTypeMap); i++) { |
+ if (rel == kFeedLinkTypeMap[i].rel) { |
+ *result = kFeedLinkTypeMap[i].type; |
return true; |
+ } |
} |
+ DVLOG(1) << "Unknown feed link type for rel " << rel; |
return false; |
} |
-// static. |
-FeedLink::FeedLinkType FeedLink::GetFeedLinkType(const std::string& rel) { |
- for (size_t i = 0; kFeedLinkTypeMap[i].rel; i++) { |
- if (rel == kFeedLinkTypeMap[i].rel) |
- return kFeedLinkTypeMap[i].type; |
- } |
- DVLOG(1) << "Unknown feed link type for rel " << rel; |
- return FeedLink::UNKNOWN; |
+// static |
+void FeedLink::RegisterJSONConverter( |
+ base::JSONValueConverter<FeedLink>* converter) { |
+ converter->RegisterCustomField<FeedLink::FeedLinkType>( |
+ kRelField, &FeedLink::type_, &FeedLink::GetFeedLinkType); |
+ converter->RegisterCustomField( |
+ kHrefField, &FeedLink::href_, &GetGURLFromString); |
} |
const char Category::kLabelField[] = "label"; |
const char Category::kSchemeField[] = "scheme"; |
const char Category::kTermField[] = "term"; |
-Category::Category() { |
+Category::Category() : type_(UNKNOWN) { |
} |
-bool Category::Parse(const DictionaryValue* dictionary) { |
- std::string scheme; |
- if (dictionary->GetString(kLabelField, &label_) && |
- dictionary->GetString(kSchemeField, &scheme) && |
- dictionary->GetString(kTermField, &term_)) { |
- type_ = GetCategoryTypeFromScheme(scheme); |
- if (type_ != Category::UNKNOWN) |
+// Converts category.scheme into CategoryType enum. |
+bool Category::GetCategoryTypeFromScheme( |
+ const base::StringPiece& scheme, Category::CategoryType* result) { |
+ for (size_t i = 0; i < arraysize(kCategoryTypeMap); i++) { |
+ if (scheme == kCategoryTypeMap[i].scheme) { |
+ *result = kCategoryTypeMap[i].type; |
return true; |
- |
- DVLOG(1) << "Unknown category:" |
- << "\n label = " << label_ |
- << "\n scheme = " << scheme |
- << "\n term = " << term_; |
+ } |
} |
+ DVLOG(1) << "Unknown feed link type for scheme " << scheme; |
return false; |
} |
-// Converts category.scheme into CategoryType enum. |
-Category::CategoryType Category::GetCategoryTypeFromScheme( |
- const std::string& scheme) { |
- for (size_t i = 0; kCategoryTypeMap[i].scheme; i++) { |
- if (scheme == kCategoryTypeMap[i].scheme) |
- return kCategoryTypeMap[i].type; |
- } |
- DVLOG(1) << "Unknown feed link type for scheme " << scheme; |
- return Category::UNKNOWN; |
+// static |
+void Category::RegisterJSONConverter( |
+ base::JSONValueConverter<Category>* converter) { |
+ converter->RegisterStringField(kLabelField, &Category::label_); |
+ converter->RegisterCustomField<Category::CategoryType>( |
+ kSchemeField, &Category::type_, &Category::GetCategoryTypeFromScheme); |
+ converter->RegisterStringField(kTermField, &Category::term_); |
} |
- |
const Link* GDataEntry::GetLinkByType(Link::LinkType type) const { |
- for (ScopedVector<Link>::const_iterator iter = links_.begin(); |
- iter != links_.end(); ++iter) { |
- if ((*iter)->type() == type) |
- return (*iter); |
+ for (size_t i = 0; i < links_.size(); ++i) { |
+ if (links_[i]->type() == type) |
+ return links_[i]; |
} |
return NULL; |
} |
+const char Content::kSrcField[] = "src"; |
+const char Content::kTypeField[] = "type"; |
+ |
+Content::Content() { |
+} |
+ |
+// static |
+void Content::RegisterJSONConverter( |
+ base::JSONValueConverter<Content>* converter) { |
+ converter->RegisterCustomField(kSrcField, &Content::url_, &GetGURLFromString); |
+ converter->RegisterStringField(kTypeField, &Content::mime_type_); |
+} |
+ |
const char GDataEntry::kTimeParsingDelimiters[] = "-:.TZ"; |
const char GDataEntry::kAuthorField[] = "author"; |
const char GDataEntry::kLinkField[] = "link"; |
const char GDataEntry::kCategoryField[] = "category"; |
+const char GDataEntry::kETagField[] = "gd$etag"; |
+const char GDataEntry::kUpdatedField[] = "updated.$t"; |
GDataEntry::GDataEntry() { |
} |
@@ -241,55 +251,23 @@ GDataEntry::GDataEntry() { |
GDataEntry::~GDataEntry() { |
} |
-bool GDataEntry::ParseAuthors(const DictionaryValue* value_dict) { |
- ListValue* authors = NULL; |
- if (value_dict->GetList(kAuthorField, &authors)) { |
- for (ListValue::iterator iter = authors->begin(); |
- iter != authors->end(); |
- ++iter) { |
- if ((*iter)->GetType() != Value::TYPE_DICTIONARY) { |
- DVLOG(1) << "Invalid author list element"; |
- return false; |
- } |
- DictionaryValue* author_dict = |
- reinterpret_cast<DictionaryValue*>(*iter); |
- scoped_ptr<Author> author(new Author()); |
- if (author->Parse(author_dict)) { |
- authors_.push_back(author.release()); |
- } else { |
- DVLOG(1) << "Invalid author etag = " << etag_; |
- } |
- } |
- } |
- return true; |
-} |
- |
-bool GDataEntry::ParseLinks(const DictionaryValue* value_dict) { |
- ListValue* links = NULL; |
- if (value_dict->GetList(kLinkField, &links)) { |
- for (ListValue::iterator iter = links->begin(); |
- iter != links->end(); |
- ++iter) { |
- if ((*iter)->GetType() != Value::TYPE_DICTIONARY) { |
- DVLOG(1) << "Invalid link list element"; |
- return false; |
- } |
- DictionaryValue* link_dict = |
- reinterpret_cast<DictionaryValue*>(*iter); |
- scoped_ptr<Link> link(new Link()); |
- if (link->Parse(link_dict)) |
- links_.push_back(link.release()); |
- else |
- DVLOG(1) << "Invalid link etag = " << etag_; |
- } |
- } |
- return true; |
+// static |
+void GDataEntry::RegisterJSONConverter( |
+ base::JSONValueConverter<GDataEntry>* converter) { |
+ converter->RegisterStringField(kETagField, &GDataEntry::etag_); |
+ converter->RegisterRepeatedMessage(kAuthorField, &GDataEntry::authors_); |
+ converter->RegisterRepeatedMessage(kLinkField, &GDataEntry::links_); |
+ converter->RegisterRepeatedMessage(kCategoryField, &GDataEntry::categories_); |
+ converter->RegisterCustomField<base::Time>( |
+ kUpdatedField, |
+ &GDataEntry::updated_time_, |
+ &GDataEntry::GetTimeFromString); |
} |
-// static. |
-bool GDataEntry::GetTimeFromString(const std::string& raw_value, |
+// static |
+bool GDataEntry::GetTimeFromString(const base::StringPiece& raw_value, |
base::Time* time) { |
- std::vector<std::string> parts; |
+ std::vector<base::StringPiece> parts; |
if (Tokenize(raw_value, kTimeParsingDelimiters, &parts) != 7) |
return false; |
@@ -312,55 +290,16 @@ bool GDataEntry::GetTimeFromString(const std::string& raw_value, |
return true; |
} |
-bool GDataEntry::ParseCategories(const DictionaryValue* value_dict) { |
- ListValue* categories = NULL; |
- if (value_dict->GetList(kCategoryField, &categories)) { |
- for (ListValue::iterator iter = categories->begin(); |
- iter != categories->end(); |
- ++iter) { |
- if ((*iter)->GetType() != Value::TYPE_DICTIONARY) { |
- DVLOG(1) << "Invalid category list element"; |
- return false; |
- } |
- DictionaryValue* category_dict = |
- reinterpret_cast<DictionaryValue*>(*iter); |
- scoped_ptr<Category> category(new Category()); |
- if (category->Parse(category_dict)) { |
- OnAddCategory(category.get()); |
- categories_->push_back(category.release()); |
- } else { |
- DVLOG(1) << "Invalid category etag = " << etag_; |
- } |
- } |
- } |
- return true; |
-} |
- |
-// static. |
-bool GDataEntry::ParseDateTime(const DictionaryValue* dict, |
- const std::string& field, |
- base::Time* time) { |
- std::string raw_value; |
- if (!dict->GetString(field, &raw_value)) |
- return false; |
- |
- return GetTimeFromString(raw_value, time); |
-} |
- |
const char DocumentEntry::kFeedLinkField[] = "gd$feedLink"; |
const char DocumentEntry::kContentField[] = "content"; |
-const char DocumentEntry::kSrcField[] = "src"; |
-const char DocumentEntry::kTypeField[] = "type"; |
const char DocumentEntry::kFileNameField[] = "docs$filename.$t"; |
const char DocumentEntry::kMD5Field[] = "docs$md5Checksum.$t"; |
const char DocumentEntry::kSizeField[] = "docs$size.$t"; |
const char DocumentEntry::kSuggestedFileNameField[] = |
"docs$suggestedFilename.$t"; |
-const char DocumentEntry::kETagField[] = "gd$etag"; |
const char DocumentEntry::kResourceIdField[] = "gd$resourceId.$t"; |
const char DocumentEntry::kIDField[] = "id.$t"; |
const char DocumentEntry::kTitleField[] = "title.$t"; |
-const char DocumentEntry::kUpdatedField[] = "updated.$t"; |
const char DocumentEntry::kPublishedField[] = "published.$t"; |
DocumentEntry::DocumentEntry() : kind_(DocumentEntry::UNKNOWN), file_size_(0) { |
@@ -369,128 +308,35 @@ DocumentEntry::DocumentEntry() : kind_(DocumentEntry::UNKNOWN), file_size_(0) { |
DocumentEntry::~DocumentEntry() { |
} |
-bool DocumentEntry::ParseFeedLinks(const DictionaryValue* value_dict) { |
- ListValue* links = NULL; |
- if (value_dict->GetList(kFeedLinkField, &links)) { |
- for (ListValue::iterator iter = links->begin(); |
- iter != links->end(); |
- ++iter) { |
- if ((*iter)->GetType() != Value::TYPE_DICTIONARY) { |
- DVLOG(1) << "Invalid feed link list element"; |
- return false; |
- } |
- DictionaryValue* link_dict = |
- reinterpret_cast<DictionaryValue*>(*iter); |
- scoped_ptr<FeedLink> link(new FeedLink()); |
- if (link->Parse(link_dict)) { |
- feed_links_.push_back(link.release()); |
- } else { |
- DVLOG(1) << "Invalid feed link etag = " << etag_; |
- } |
- } |
- } |
- return true; |
-} |
- |
-bool DocumentEntry::ParseContent(const DictionaryValue* value_dict) { |
- base::DictionaryValue* content = NULL; |
- if (value_dict->GetDictionary(kContentField, &content)) { |
- std::string src; |
- if (content->GetString(kSrcField, &src) && |
- content->GetString(kTypeField, &content_mime_type_)) { |
- content_url_ = GURL(src); |
- return true; |
- } |
- } |
- DVLOG(1) << "Invalid item content etag = " << etag_; |
- return false; |
-} |
- |
-bool DocumentEntry::ParseFileProperties(const DictionaryValue* value_dict) { |
- if (!value_dict->GetString(kFileNameField, &filename_)) { |
- DVLOG(1) << "File item with no name! " << etag_; |
- return false; |
- } |
- |
- if (!value_dict->GetString(kMD5Field, &file_md5_)) { |
- DVLOG(1) << "File item with no md5! " << etag_; |
- return false; |
- } |
- |
- std::string file_size; |
- if (!value_dict->GetString(kSizeField, &file_size) || |
- !file_size.length()) { |
- DVLOG(1) << "File item with no size! " << etag_; |
- return false; |
- } |
- |
- if (!base::StringToInt64(file_size, &file_size_)) { |
- DVLOG(1) << "Invalid file size '" << file_size << "' for " << etag_; |
- return false; |
- } |
- |
- if (!value_dict->GetString(kSuggestedFileNameField, &suggested_filename_)) |
- DVLOG(1) << "File item with no docs$suggestedFilename! " << etag_; |
- |
- return true; |
-} |
- |
-bool DocumentEntry::Parse(const DictionaryValue* value_dict) { |
- if (!value_dict->GetString(kETagField, &etag_)) { |
- DVLOG(1) << "Item with no etag!"; |
- return false; |
- } |
- |
- if (!value_dict->GetString(kResourceIdField, &resource_id_)) { |
- DVLOG(1) << "Item with no resource id! " << etag_; |
- return false; |
- } |
- |
- if (!value_dict->GetString(kIDField, &id_)) { |
- DVLOG(1) << "Item with no id! " << etag_; |
- return false; |
- } |
- |
- if (!value_dict->GetString(kTitleField, &title_)) { |
- DVLOG(1) << "Item with no title! " << etag_; |
- return false; |
- } |
- |
- if (!ParseDateTime(value_dict, kUpdatedField, &updated_time_)) { |
- DVLOG(1) << "Item with no updated date! " << etag_; |
- return false; |
- } |
- |
- if (!ParseDateTime(value_dict, kPublishedField, &published_time_)) { |
- DVLOG(1) << "Item with no published date! " << etag_; |
- return false; |
- } |
- |
- // Parse categories, will set up entry->kind as well. |
- if (!ParseCategories(value_dict)) |
- return false; |
- |
- if (kind_ == DocumentEntry::FILE || kind_ == DocumentEntry::PDF) { |
- if (!ParseFileProperties(value_dict)) |
- return false; |
- } |
- |
- if (!ParseAuthors(value_dict)) |
- return false; |
- |
- if (!ParseContent(value_dict)) |
- return false; |
- |
- if (!ParseLinks(value_dict)) |
- return false; |
- |
- if (!ParseFeedLinks(value_dict)) |
- return false; |
- |
- return true; |
-} |
- |
-// static. |
+// static |
+void DocumentEntry::RegisterJSONConverter( |
+ base::JSONValueConverter<DocumentEntry>* converter) { |
+ // inheritant the parent registrations. |
+ GDataEntry::RegisterJSONConverter( |
+ reinterpret_cast<base::JSONValueConverter<GDataEntry>*>(converter)); |
+ converter->RegisterStringField( |
+ kResourceIdField, &DocumentEntry::resource_id_); |
+ converter->RegisterStringField(kIDField, &DocumentEntry::id_); |
+ converter->RegisterStringField(kTitleField, &DocumentEntry::title_); |
+ converter->RegisterCustomField<base::Time>( |
+ kPublishedField, &DocumentEntry::published_time_, |
+ &GDataEntry::GetTimeFromString); |
+ converter->RegisterRepeatedMessage( |
+ kFeedLinkField, &DocumentEntry::feed_links_); |
+ converter->RegisterNestedField(kContentField, &DocumentEntry::content_); |
+ |
+ // File properties. If the document type is not a normal file, then |
+ // that's no problem because those feed must not have these fields |
+ // themselves, which does not report errors. |
+ converter->RegisterStringField(kFileNameField, &DocumentEntry::filename_); |
+ converter->RegisterStringField(kMD5Field, &DocumentEntry::file_md5_); |
+ converter->RegisterCustomField<int64>( |
+ kSizeField, &DocumentEntry::file_size_, &base::StringToInt64); |
+ converter->RegisterStringField( |
+ kSuggestedFileNameField, &DocumentEntry::suggested_filename_); |
+} |
+ |
+// static |
DocumentEntry::EntryKind DocumentEntry::GetEntryKindFromTerm( |
const std::string& term) { |
if (!StartsWithASCII(term, kTermPrefix, false)) { |
@@ -499,7 +345,7 @@ DocumentEntry::EntryKind DocumentEntry::GetEntryKindFromTerm( |
} |
std::string type = term.substr(strlen(kTermPrefix)); |
- for (size_t i = 0; kEntryKindMap[i].entry; i++) { |
+ for (size_t i = 0; i < arraysize(kEntryKindMap); i++) { |
if (type == kEntryKindMap[i].entry) |
return kEntryKindMap[i].kind; |
} |
@@ -507,19 +353,23 @@ DocumentEntry::EntryKind DocumentEntry::GetEntryKindFromTerm( |
return DocumentEntry::UNKNOWN; |
} |
-void DocumentEntry::OnAddCategory(Category* category) { |
- if (category->type() == Category::KIND) |
- kind_ = GetEntryKindFromTerm(category->term()); |
- else if (category->type() == Category::LABEL) |
- labels_.push_back(category->label()); |
+void DocumentEntry::FillRemainingFields() { |
+ // Set |kind_| and |labels_| based on the |categories_| in the class. |
+ // JSONValueConverter does not have the ability to catch an element in a list |
+ // based on a predicate. Thus we need to iterate over |categories_| and |
+ // find the elements to set these fields as a post-process. |
+ for (size_t i = 0; i < categories_.size(); ++i) { |
+ const Category* category = categories_[i]; |
+ if (category->type() == Category::KIND) |
+ kind_ = GetEntryKindFromTerm(category->term()); |
+ else if (category->type() == Category::LABEL) |
+ labels_.push_back(category->label()); |
+ } |
} |
- |
-const char DocumentFeed::kETagField[] = "gd$etag"; |
const char DocumentFeed::kStartIndexField[] = "openSearch$startIndex.$t"; |
const char DocumentFeed::kItemsPerPageField[] = |
"openSearch$itemsPerPage.$t"; |
-const char DocumentFeed::kUpdatedField[] = "updated.$t"; |
const char DocumentFeed::kTitleField[] = "title.$t"; |
const char DocumentFeed::kEntryField[] = "entry"; |
@@ -529,88 +379,53 @@ DocumentFeed::DocumentFeed() : start_index_(0), items_per_page_(0) { |
DocumentFeed::~DocumentFeed() { |
} |
-bool DocumentFeed::Parse(const DictionaryValue* value_dict) { |
- if (!value_dict->GetString(kETagField, &etag_)) { |
- DVLOG(1) << "Feed with no etag!"; |
- return false; |
- } |
- |
+// static |
+void DocumentFeed::RegisterJSONConverter( |
+ base::JSONValueConverter<DocumentFeed>* converter) { |
+ // inheritance |
+ GDataEntry::RegisterJSONConverter( |
+ reinterpret_cast<base::JSONValueConverter<GDataEntry>*>(converter)); |
// TODO(zelidrag): Once we figure out where these will be used, we should |
// check for valid start_index_ and items_per_page_ values. |
- std::string start_index; |
- if (!value_dict->GetString(kStartIndexField, &start_index) || |
- !base::StringToInt(start_index, &start_index_)) { |
- DVLOG(1) << "Feed with no startIndex! " << etag_; |
- return false; |
- } |
- |
- std::string items_per_page; |
- if (!value_dict->GetString(kItemsPerPageField, &items_per_page) || |
- !base::StringToInt(items_per_page, &items_per_page_)) { |
- DVLOG(1) << "Feed with no itemsPerPage! " << etag_; |
- return false; |
- } |
- |
- if (!ParseDateTime(value_dict, kUpdatedField, &updated_time_)) { |
- DVLOG(1) << "Feed with no updated date! " << etag_; |
- return false; |
- } |
- |
- if (!value_dict->GetString(kTitleField, &title_)) { |
- DVLOG(1) << "Feed with no title!"; |
- return false; |
- } |
- |
- ListValue* entries = NULL; |
- if (value_dict->GetList(kEntryField, &entries)) { |
- for (ListValue::iterator iter = entries->begin(); |
- iter != entries->end(); |
- ++iter) { |
- DocumentEntry* entry = DocumentEntry::CreateFrom(*iter); |
- if (entry) |
- entries_.push_back(entry); |
- } |
- } |
- |
- // Parse categories. |
- if (!ParseCategories(value_dict)) |
- return false; |
- |
- // Parse author list. |
- if (!ParseAuthors(value_dict)) |
- return false; |
- |
- if (!ParseLinks(value_dict)) |
- return false; |
- |
- return true; |
+ converter->RegisterCustomField<int>( |
+ kStartIndexField, &DocumentFeed::start_index_, &base::StringToInt); |
+ converter->RegisterCustomField<int>( |
+ kItemsPerPageField, &DocumentFeed::items_per_page_, &base::StringToInt); |
+ converter->RegisterStringField(kTitleField, &DocumentFeed::title_); |
+ converter->RegisterRepeatedMessage(kEntryField, &DocumentFeed::entries_); |
} |
-// static. |
+// static |
DocumentEntry* DocumentEntry::CreateFrom(base::Value* value) { |
- if (!value || value->GetType() != Value::TYPE_DICTIONARY) |
- return NULL; |
- |
- DictionaryValue* root = reinterpret_cast<DictionaryValue*>(value); |
+ base::JSONValueConverter<DocumentEntry> converter; |
scoped_ptr<DocumentEntry> entry(new DocumentEntry()); |
- if (!entry->Parse(root)) { |
+ if (!converter.Convert(*value, entry.get())) { |
DVLOG(1) << "Invalid document entry!"; |
return NULL; |
} |
+ entry->FillRemainingFields(); |
return entry.release(); |
} |
-// static. |
-DocumentFeed* DocumentFeed::CreateFrom(base::Value* value) { |
- if (!value || value->GetType() != Value::TYPE_DICTIONARY) |
- return NULL; |
+bool DocumentFeed::Parse(base::Value* value) { |
+ base::JSONValueConverter<DocumentFeed> converter; |
+ if (!converter.Convert(*value, this)) { |
+ DVLOG(1) << "Invalid document feed!"; |
+ return false; |
+ } |
- DictionaryValue* root_entry_dict = |
- reinterpret_cast<DictionaryValue*>(value); |
+ for (size_t i = 0; i < entries_.size(); ++i) { |
+ entries_[i]->FillRemainingFields(); |
+ } |
+ return true; |
+} |
+ |
+// static |
+DocumentFeed* DocumentFeed::CreateFrom(base::Value* value) { |
scoped_ptr<DocumentFeed> feed(new DocumentFeed()); |
- if (!feed->Parse(root_entry_dict)) { |
+ if (!feed->Parse(value)) { |
DVLOG(1) << "Invalid document feed!"; |
return NULL; |
} |
@@ -620,10 +435,9 @@ DocumentFeed* DocumentFeed::CreateFrom(base::Value* value) { |
bool DocumentFeed::GetNextFeedURL(GURL* url) { |
DCHECK(url); |
- for (ScopedVector<Link>::iterator iter = links_.begin(); |
- iter != links_.end(); ++iter) { |
- if ((*iter)->type() == Link::NEXT) { |
- *url = (*iter)->href(); |
+ for (size_t i = 0; i < links_.size(); ++i) { |
+ if (links_[i]->type() == Link::NEXT) { |
+ *url = links_[i]->href(); |
return true; |
} |
} |