1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef GOOGLE_APIS_DRIVE_GDATA_WAPI_PARSER_H_
6 #define GOOGLE_APIS_DRIVE_GDATA_WAPI_PARSER_H_
12 #include "base/compiler_specific.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/strings/string_piece.h"
16 #include "base/time/time.h"
21 class DictionaryValue
;
24 template <class StructType
>
25 class JSONValueConverter
;
28 template <class NestedType
>
29 class RepeatedMessageConverter
;
30 } // namespace internal
34 // Defines data elements of Google Documents API as described in
35 // http://code.google.com/apis/documents/.
36 namespace google_apis
{
38 // Defines link (URL) of an entity (document, file, feed...). Each entity could
39 // have more than one link representing it.
55 LINK_RESUMABLE_EDIT_MEDIA
,
56 LINK_RESUMABLE_CREATE_MEDIA
,
69 // Registers the mapping between JSON field names and the members in
71 static void RegisterJSONConverter(base::JSONValueConverter
<Link
>* converter
);
74 LinkType
type() const { return type_
; }
77 const GURL
& href() const { return href_
; }
80 const std::string
& title() const { return title_
; }
82 // For OPEN_WITH links, this contains the application ID. For all other link
83 // types, it is the empty string.
84 const std::string
& app_id() const { return app_id_
; }
87 const std::string
& mime_type() const { return mime_type_
; }
89 void set_type(LinkType type
) { type_
= type
; }
90 void set_href(const GURL
& href
) { href_
= href
; }
91 void set_title(const std::string
& title
) { title_
= title
; }
92 void set_app_id(const std::string
& app_id
) { app_id_
= app_id
; }
93 void set_mime_type(const std::string
& mime_type
) { mime_type_
= mime_type
; }
96 friend class ResourceEntry
;
97 // Converts value of link.rel into LinkType. Outputs to |type| and returns
98 // true when |rel| has a valid value. Otherwise does nothing and returns
100 static bool GetLinkType(const base::StringPiece
& rel
, LinkType
* type
);
102 // Converts value of link.rel to application ID, if there is one embedded in
103 // the link.rel field. Outputs to |app_id| and returns true when |rel| has a
104 // valid value. Otherwise does nothing and returns false.
105 static bool GetAppID(const base::StringPiece
& rel
, std::string
* app_id
);
111 std::string mime_type_
;
113 DISALLOW_COPY_AND_ASSIGN(Link
);
116 // Feed links define links (URLs) to special list of entries (i.e. list of
117 // previous document revisions).
120 enum ResourceLinkType
{
127 // Registers the mapping between JSON field names and the members in
129 static void RegisterJSONConverter(
130 base::JSONValueConverter
<ResourceLink
>* converter
);
132 // MIME type of the feed.
133 ResourceLinkType
type() const { return type_
; }
136 const GURL
& href() const { return href_
; }
138 void set_type(ResourceLinkType type
) { type_
= type
; }
139 void set_href(const GURL
& href
) { href_
= href
; }
142 friend class ResourceEntry
;
143 // Converts value of gd$feedLink.rel into ResourceLinkType enum.
144 // Outputs to |result| and returns true when |rel| has a valid
145 // value. Otherwise does nothing and returns false.
146 static bool GetFeedLinkType(
147 const base::StringPiece
& rel
, ResourceLinkType
* result
);
149 ResourceLinkType type_
;
152 DISALLOW_COPY_AND_ASSIGN(ResourceLink
);
155 // Author represents an author of an entity.
160 // Registers the mapping between JSON field names and the members in
162 static void RegisterJSONConverter(
163 base::JSONValueConverter
<Author
>* converter
);
166 const std::string
& name() const { return name_
; }
167 const std::string
& email() const { return email_
; }
169 void set_name(const std::string
& name
) { name_
= name
; }
170 void set_email(const std::string
& email
) { email_
= email
; }
173 friend class ResourceEntry
;
178 DISALLOW_COPY_AND_ASSIGN(Author
);
193 // Registers the mapping between JSON field names and the members in
195 static void RegisterJSONConverter(
196 base::JSONValueConverter
<Category
>* converter
);
199 const std::string
& label() const { return label_
; }
202 CategoryType
type() const { return type_
; }
205 const std::string
& term() const { return term_
; }
207 void set_label(const std::string
& label
) { label_
= label
; }
208 void set_type(CategoryType type
) { type_
= type
; }
209 void set_term(const std::string
& term
) { term_
= term
; }
212 friend class ResourceEntry
;
213 // Converts category scheme into CategoryType enum. For example,
214 // http://schemas.google.com/g/2005#kind => Category::CATEGORY_KIND
215 // Returns false and does not change |result| when |scheme| has an
216 // unrecognizable value.
217 static bool GetCategoryTypeFromScheme(
218 const base::StringPiece
& scheme
, CategoryType
* result
);
224 DISALLOW_COPY_AND_ASSIGN(Category
);
227 // Content details of a resource: mime-type, url, and so on.
232 // Registers the mapping between JSON field names and the members in
234 static void RegisterJSONConverter(
235 base::JSONValueConverter
<Content
>* converter
);
237 // The URL to download the file content.
238 // Note that the url can expire, so we'll fetch the latest resource
239 // entry before starting a download to get the download URL.
240 const GURL
& url() const { return url_
; }
241 const std::string
& mime_type() const { return mime_type_
; }
243 void set_url(const GURL
& url
) { url_
= url
; }
244 void set_mime_type(const std::string
& mime_type
) { mime_type_
= mime_type
; }
247 friend class ResourceEntry
;
250 std::string mime_type_
;
253 // Base class for feed entries. This class defines fields commonly used by
255 class CommonMetadata
{
258 virtual ~CommonMetadata();
260 // Returns a link of a given |type| for this entry. If not found, it returns
262 const Link
* GetLinkByType(Link::LinkType type
) const;
264 // Entry update time.
265 base::Time
updated_time() const { return updated_time_
; }
268 const std::string
& etag() const { return etag_
; }
270 // List of entry authors.
271 const ScopedVector
<Author
>& authors() const { return authors_
; }
273 // List of entry links.
274 const ScopedVector
<Link
>& links() const { return links_
; }
275 ScopedVector
<Link
>* mutable_links() { return &links_
; }
277 // List of entry categories.
278 const ScopedVector
<Category
>& categories() const { return categories_
; }
280 void set_etag(const std::string
& etag
) { etag_
= etag
; }
281 void set_authors(ScopedVector
<Author
> authors
) {
282 authors_
= authors
.Pass();
284 void set_links(ScopedVector
<Link
> links
) {
285 links_
= links
.Pass();
287 void set_categories(ScopedVector
<Category
> categories
) {
288 categories_
= categories
.Pass();
290 void set_updated_time(const base::Time
& updated_time
) {
291 updated_time_
= updated_time
;
295 // Registers the mapping between JSON field names and the members in
297 template<typename CommonMetadataDescendant
>
298 static void RegisterJSONConverter(
299 base::JSONValueConverter
<CommonMetadataDescendant
>* converter
);
302 ScopedVector
<Author
> authors_
;
303 ScopedVector
<Link
> links_
;
304 ScopedVector
<Category
> categories_
;
305 base::Time updated_time_
;
307 DISALLOW_COPY_AND_ASSIGN(CommonMetadata
);
310 // This class represents a resource entry. A resource is a generic term which
311 // refers to a file and a directory.
312 class ResourceEntry
: public CommonMetadata
{
314 enum ResourceEntryKind
{
320 ~ResourceEntry() override
;
322 // Extracts "entry" dictionary from the JSON value, and parse the contents,
323 // using CreateFrom(). Returns NULL on failure. The input JSON data, coming
324 // from the gdata server, looks like:
327 // "encoding": "UTF-8",
328 // "entry": { ... }, // This function will extract this and parse.
332 // The caller should delete the returned object.
333 static scoped_ptr
<ResourceEntry
> ExtractAndParse(const base::Value
& value
);
335 // Creates resource entry from parsed JSON Value. You should call
336 // this instead of instantiating JSONValueConverter by yourself
337 // because this method does some post-process for some fields. See
338 // FillRemainingFields comment and implementation for the details.
339 static scoped_ptr
<ResourceEntry
> CreateFrom(const base::Value
& value
);
341 // Returns name of entry node.
342 static std::string
GetEntryNodeName();
344 // Registers the mapping between JSON field names and the members in
346 static void RegisterJSONConverter(
347 base::JSONValueConverter
<ResourceEntry
>* converter
);
349 // Sets true to |result| if the field exists.
350 // Always returns true even when the field does not exist.
351 static bool HasFieldPresent(const base::Value
* value
, bool* result
);
353 // Parses |value| as int64 and sets it to |result|. If the field does not
354 // exist, sets 0 to |result| as default value.
355 // Returns true if |value| is NULL or it is parsed as int64 successfully.
356 static bool ParseChangestamp(const base::Value
* value
, int64
* result
);
358 // The resource ID is used to identify a resource, which looks like:
359 // file:d41d8cd98f00b204e9800998ecf8
360 const std::string
& resource_id() const { return resource_id_
; }
362 // This is a URL looks like:
363 // https://docs.google.com/feeds/id/file%3Ad41d8cd98f00b204e9800998ecf8.
364 // The URL is currently not used.
365 const std::string
& id() const { return id_
; }
367 ResourceEntryKind
kind() const { return kind_
; }
368 const std::string
& title() const { return title_
; }
369 base::Time
published_time() const { return published_time_
; }
370 base::Time
last_viewed_time() const { return last_viewed_time_
; }
371 const std::vector
<std::string
>& labels() const { return labels_
; }
373 // The URL to download a file content.
374 // Search for 'download_url' in gdata_wapi_requests.h for details.
375 const GURL
& download_url() const { return content_
.url(); }
377 const std::string
& content_mime_type() const { return content_
.mime_type(); }
379 // The resource links contain extra links for revisions and access control,
380 // etc. Note that links() contain more basic links like edit URL,
381 // alternative URL, etc.
382 const ScopedVector
<ResourceLink
>& resource_links() const {
383 return resource_links_
;
386 // File name (exists only for kinds FILE and PDF).
387 const std::string
& filename() const { return filename_
; }
389 // Suggested file name (exists only for kinds FILE and PDF).
390 const std::string
& suggested_filename() const { return suggested_filename_
; }
392 // File content MD5 (exists only for kinds FILE and PDF).
393 const std::string
& file_md5() const { return file_md5_
; }
395 // File size (exists only for kinds FILE and PDF).
396 int64
file_size() const { return file_size_
; }
398 // True if the file or directory is deleted (applicable to change list only).
399 bool deleted() const { return deleted_
|| removed_
; }
401 // Changestamp (exists only for change query results).
402 // If not exists, defaults to 0.
403 int64
changestamp() const { return changestamp_
; }
405 // Image width (exists only for images).
406 // If doesn't exist, then equals -1.
407 int64
image_width() const { return image_width_
; }
409 // Image height (exists only for images).
410 // If doesn't exist, then equals -1.
411 int64
image_height() const { return image_height_
; }
413 // Image rotation in clockwise degrees (exists only for images).
414 // If doesn't exist, then equals -1.
415 int64
image_rotation() const { return image_rotation_
; }
417 // The time of this modification.
418 // Note: This property is filled only when converted from ChangeResource.
419 const base::Time
& modification_date() const { return modification_date_
; }
421 // Text version of resource entry kind. Returns an empty string for
422 // unknown entry kind.
423 std::string
GetEntryKindText() const;
425 // True if resource entry is a folder (collection).
426 bool is_folder() const {
427 return kind_
== ENTRY_KIND_FOLDER
;
429 // True if resource entry is regular file.
430 bool is_file() const {
431 return kind_
== ENTRY_KIND_FILE
;
434 void set_resource_id(const std::string
& resource_id
) {
435 resource_id_
= resource_id
;
437 void set_id(const std::string
& id
) { id_
= id
; }
438 void set_kind(ResourceEntryKind kind
) { kind_
= kind
; }
439 void set_title(const std::string
& title
) { title_
= title
; }
440 void set_published_time(const base::Time
& published_time
) {
441 published_time_
= published_time
;
443 void set_last_viewed_time(const base::Time
& last_viewed_time
) {
444 last_viewed_time_
= last_viewed_time
;
446 void set_labels(const std::vector
<std::string
>& labels
) {
449 void set_content(const Content
& content
) {
452 void set_resource_links(ScopedVector
<ResourceLink
> resource_links
) {
453 resource_links_
= resource_links
.Pass();
455 void set_filename(const std::string
& filename
) { filename_
= filename
; }
456 void set_suggested_filename(const std::string
& suggested_filename
) {
457 suggested_filename_
= suggested_filename
;
459 void set_file_md5(const std::string
& file_md5
) { file_md5_
= file_md5
; }
460 void set_file_size(int64 file_size
) { file_size_
= file_size
; }
461 void set_deleted(bool deleted
) { deleted_
= deleted
; }
462 void set_removed(bool removed
) { removed_
= removed
; }
463 void set_changestamp(int64 changestamp
) { changestamp_
= changestamp
; }
464 void set_image_width(int64 image_width
) { image_width_
= image_width
; }
465 void set_image_height(int64 image_height
) { image_height_
= image_height
; }
466 void set_image_rotation(int64 image_rotation
) {
467 image_rotation_
= image_rotation
;
469 void set_modification_date(const base::Time
& modification_date
) {
470 modification_date_
= modification_date
;
473 // Fills the remaining fields where JSONValueConverter cannot catch.
474 // Currently, sets |kind_| and |labels_| based on the |categories_| in the
476 void FillRemainingFields();
479 friend class base::internal::RepeatedMessageConverter
<ResourceEntry
>;
480 friend class ResourceList
;
481 friend class ResumeUploadRequest
;
483 // Converts categories.term into ResourceEntryKind enum.
484 static ResourceEntryKind
GetEntryKindFromTerm(const std::string
& term
);
486 std::string resource_id_
;
488 ResourceEntryKind kind_
;
490 base::Time published_time_
;
491 // Last viewed value may be unreliable. See: crbug.com/152628.
492 base::Time last_viewed_time_
;
493 std::vector
<std::string
> labels_
;
495 ScopedVector
<ResourceLink
> resource_links_
;
496 // Optional fields for files only.
497 std::string filename_
;
498 std::string suggested_filename_
;
499 std::string file_md5_
;
506 int64 image_rotation_
;
508 base::Time modification_date_
;
510 DISALLOW_COPY_AND_ASSIGN(ResourceEntry
);
513 // This class represents a list of resource entries with some extra metadata
514 // such as the root upload URL. The feed is paginated and the rest of the
515 // feed can be fetched by retrieving the remaining parts of the feed from
516 // URLs provided by GetNextFeedURL() method.
517 class ResourceList
: public CommonMetadata
{
520 ~ResourceList() override
;
522 // Extracts "feed" dictionary from the JSON value, and parse the contents,
523 // using CreateFrom(). Returns NULL on failure. The input JSON data, coming
524 // from the gdata server, looks like:
527 // "encoding": "UTF-8",
528 // "feed": { ... }, // This function will extract this and parse.
531 static scoped_ptr
<ResourceList
> ExtractAndParse(const base::Value
& value
);
533 // Creates feed from parsed JSON Value. You should call this
534 // instead of instantiating JSONValueConverter by yourself because
535 // this method does some post-process for some fields. See
536 // FillRemainingFields comment and implementation in ResourceEntry
537 // class for the details.
538 static scoped_ptr
<ResourceList
> CreateFrom(const base::Value
& value
);
540 // Registers the mapping between JSON field names and the members in
542 static void RegisterJSONConverter(
543 base::JSONValueConverter
<ResourceList
>* converter
);
545 // Returns true and passes|url| of the next feed if the current entry list
546 // does not completed this feed.
547 bool GetNextFeedURL(GURL
* url
) const;
549 // List of resource entries.
550 const ScopedVector
<ResourceEntry
>& entries() const { return entries_
; }
551 ScopedVector
<ResourceEntry
>* mutable_entries() { return &entries_
; }
553 // Releases entries_ into |entries|. This is a transfer of ownership, so the
554 // caller is responsible for deleting the elements of |entries|.
555 void ReleaseEntries(std::vector
<ResourceEntry
*>* entries
);
557 // Start index of the resource entry list.
558 int start_index() const { return start_index_
; }
560 // Number of items per feed of the resource entry list.
561 int items_per_page() const { return items_per_page_
; }
563 // The largest changestamp. Next time the resource list should be fetched
564 // from this changestamp.
565 int64
largest_changestamp() const { return largest_changestamp_
; }
567 // Resource entry list title.
568 const std::string
& title() { return title_
; }
570 void set_entries(ScopedVector
<ResourceEntry
> entries
) {
571 entries_
= entries
.Pass();
573 void set_start_index(int start_index
) {
574 start_index_
= start_index
;
576 void set_items_per_page(int items_per_page
) {
577 items_per_page_
= items_per_page
;
579 void set_title(const std::string
& title
) {
582 void set_largest_changestamp(int64 largest_changestamp
) {
583 largest_changestamp_
= largest_changestamp
;
587 // Parses and initializes data members from content of |value|.
588 // Return false if parsing fails.
589 bool Parse(const base::Value
& value
);
591 ScopedVector
<ResourceEntry
> entries_
;
595 int64 largest_changestamp_
;
597 DISALLOW_COPY_AND_ASSIGN(ResourceList
);
600 } // namespace google_apis
602 #endif // GOOGLE_APIS_DRIVE_GDATA_WAPI_PARSER_H_