| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef GOOGLE_APIS_DRIVE_GDATA_WAPI_REQUESTS_H_ | 5 #ifndef GOOGLE_APIS_DRIVE_GDATA_WAPI_REQUESTS_H_ |
| 6 #define GOOGLE_APIS_DRIVE_GDATA_WAPI_REQUESTS_H_ | 6 #define GOOGLE_APIS_DRIVE_GDATA_WAPI_REQUESTS_H_ |
| 7 | 7 |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | |
| 10 | 9 |
| 11 #include "google_apis/drive/base_requests.h" | 10 #include "google_apis/drive/base_requests.h" |
| 12 #include "google_apis/drive/drive_common_callbacks.h" | |
| 13 #include "google_apis/drive/gdata_wapi_url_generator.h" | 11 #include "google_apis/drive/gdata_wapi_url_generator.h" |
| 14 | 12 |
| 15 namespace google_apis { | 13 namespace google_apis { |
| 16 | 14 |
| 17 class AccountMetadata; | |
| 18 class GDataWapiUrlGenerator; | |
| 19 class ResourceEntry; | |
| 20 | |
| 21 //============================ GetResourceListRequest ======================== | |
| 22 | |
| 23 // This class performs the request for fetching a resource list. | |
| 24 class GetResourceListRequest : public GetDataRequest { | |
| 25 public: | |
| 26 // override_url: | |
| 27 // If empty, a hard-coded base URL of the WAPI server is used to fetch | |
| 28 // the first page of the feed. This parameter is used for fetching 2nd | |
| 29 // page and onward. | |
| 30 // | |
| 31 // start_changestamp: | |
| 32 // This parameter specifies the starting point of a delta feed or 0 if a | |
| 33 // full feed is necessary. | |
| 34 // | |
| 35 // search_string: | |
| 36 // If non-empty, fetches a list of resources that match the search | |
| 37 // string. | |
| 38 // | |
| 39 // directory_resource_id: | |
| 40 // If non-empty, fetches a list of resources in a particular directory. | |
| 41 // | |
| 42 // callback: | |
| 43 // Called once the feed is fetched. Must not be null. | |
| 44 GetResourceListRequest(RequestSender* sender, | |
| 45 const GDataWapiUrlGenerator& url_generator, | |
| 46 const GURL& override_url, | |
| 47 int64 start_changestamp, | |
| 48 const std::string& search_string, | |
| 49 const std::string& directory_resource_id, | |
| 50 const GetResourceListCallback& callback); | |
| 51 virtual ~GetResourceListRequest(); | |
| 52 | |
| 53 protected: | |
| 54 // UrlFetchRequestBase overrides. | |
| 55 virtual GURL GetURL() const OVERRIDE; | |
| 56 | |
| 57 private: | |
| 58 const GDataWapiUrlGenerator url_generator_; | |
| 59 const GURL override_url_; | |
| 60 const int64 start_changestamp_; | |
| 61 const std::string search_string_; | |
| 62 const std::string directory_resource_id_; | |
| 63 | |
| 64 DISALLOW_COPY_AND_ASSIGN(GetResourceListRequest); | |
| 65 }; | |
| 66 | |
| 67 //============================ SearchByTitleRequest ========================== | |
| 68 | |
| 69 // This class performs the request for searching resources by title. | |
| 70 class SearchByTitleRequest : public GetDataRequest { | |
| 71 public: | |
| 72 // title: the search query. | |
| 73 // | |
| 74 // directory_resource_id: If given (non-empty), the search target is | |
| 75 // directly under the directory with the |directory_resource_id|. | |
| 76 // If empty, the search target is all the existing resources. | |
| 77 // | |
| 78 // callback: | |
| 79 // Called once the feed is fetched. Must not be null. | |
| 80 SearchByTitleRequest(RequestSender* sender, | |
| 81 const GDataWapiUrlGenerator& url_generator, | |
| 82 const std::string& title, | |
| 83 const std::string& directory_resource_id, | |
| 84 const GetResourceListCallback& callback); | |
| 85 virtual ~SearchByTitleRequest(); | |
| 86 | |
| 87 protected: | |
| 88 // UrlFetchRequestBase overrides. | |
| 89 virtual GURL GetURL() const OVERRIDE; | |
| 90 | |
| 91 private: | |
| 92 const GDataWapiUrlGenerator url_generator_; | |
| 93 const std::string title_; | |
| 94 const std::string directory_resource_id_; | |
| 95 | |
| 96 DISALLOW_COPY_AND_ASSIGN(SearchByTitleRequest); | |
| 97 }; | |
| 98 | |
| 99 //========================= GetResourceEntryRequest ========================== | 15 //========================= GetResourceEntryRequest ========================== |
| 100 | 16 |
| 101 // This class performs the request for fetching a single resource entry. | 17 // This class performs the request for fetching a single resource entry. |
| 102 class GetResourceEntryRequest : public GetDataRequest { | 18 class GetResourceEntryRequest : public GetDataRequest { |
| 103 public: | 19 public: |
| 104 // |callback| must not be null. | 20 // |callback| must not be null. |
| 105 GetResourceEntryRequest(RequestSender* sender, | 21 GetResourceEntryRequest(RequestSender* sender, |
| 106 const GDataWapiUrlGenerator& url_generator, | 22 const GDataWapiUrlGenerator& url_generator, |
| 107 const std::string& resource_id, | 23 const std::string& resource_id, |
| 108 const GURL& embed_origin, | 24 const GURL& embed_origin, |
| 109 const GetDataCallback& callback); | 25 const GetDataCallback& callback); |
| 110 virtual ~GetResourceEntryRequest(); | 26 virtual ~GetResourceEntryRequest(); |
| 111 | 27 |
| 112 protected: | 28 protected: |
| 113 // UrlFetchRequestBase overrides. | 29 // UrlFetchRequestBase overrides. |
| 114 virtual GURL GetURL() const OVERRIDE; | 30 virtual GURL GetURL() const OVERRIDE; |
| 115 | 31 |
| 116 private: | 32 private: |
| 117 const GDataWapiUrlGenerator url_generator_; | 33 const GDataWapiUrlGenerator url_generator_; |
| 118 // Resource id of the requested entry. | 34 // Resource id of the requested entry. |
| 119 const std::string resource_id_; | 35 const std::string resource_id_; |
| 120 // Embed origin for an url to the sharing dialog. Can be empty. | 36 // Embed origin for an url to the sharing dialog. Can be empty. |
| 121 const GURL& embed_origin_; | 37 const GURL& embed_origin_; |
| 122 | 38 |
| 123 DISALLOW_COPY_AND_ASSIGN(GetResourceEntryRequest); | 39 DISALLOW_COPY_AND_ASSIGN(GetResourceEntryRequest); |
| 124 }; | 40 }; |
| 125 | 41 |
| 126 //========================= GetAccountMetadataRequest ======================== | |
| 127 | |
| 128 // Callback used for GetAccountMetadata(). | |
| 129 typedef base::Callback<void(GDataErrorCode error, | |
| 130 scoped_ptr<AccountMetadata> account_metadata)> | |
| 131 GetAccountMetadataCallback; | |
| 132 | |
| 133 // This class performs the request for fetching account metadata. | |
| 134 class GetAccountMetadataRequest : public GetDataRequest { | |
| 135 public: | |
| 136 // If |include_installed_apps| is set to true, the result should include | |
| 137 // the list of installed third party applications. | |
| 138 // |callback| must not be null. | |
| 139 GetAccountMetadataRequest(RequestSender* sender, | |
| 140 const GDataWapiUrlGenerator& url_generator, | |
| 141 const GetAccountMetadataCallback& callback, | |
| 142 bool include_installed_apps); | |
| 143 virtual ~GetAccountMetadataRequest(); | |
| 144 | |
| 145 protected: | |
| 146 // UrlFetchRequestBase overrides. | |
| 147 virtual GURL GetURL() const OVERRIDE; | |
| 148 | |
| 149 private: | |
| 150 const GDataWapiUrlGenerator url_generator_; | |
| 151 const bool include_installed_apps_; | |
| 152 | |
| 153 DISALLOW_COPY_AND_ASSIGN(GetAccountMetadataRequest); | |
| 154 }; | |
| 155 | |
| 156 //=========================== DeleteResourceRequest ========================== | |
| 157 | |
| 158 // This class performs the request for deleting a resource. | |
| 159 // | |
| 160 // In WAPI, "gd:deleted" means that the resource was put in the trash, and | |
| 161 // "docs:removed" means its permanently gone. Since what the class does is to | |
| 162 // put the resource into trash, we have chosen "Delete" in the name, even though | |
| 163 // we are preferring the term "Remove" in drive/google_api code. | |
| 164 class DeleteResourceRequest : public EntryActionRequest { | |
| 165 public: | |
| 166 // |callback| must not be null. | |
| 167 DeleteResourceRequest(RequestSender* sender, | |
| 168 const GDataWapiUrlGenerator& url_generator, | |
| 169 const EntryActionCallback& callback, | |
| 170 const std::string& resource_id, | |
| 171 const std::string& etag); | |
| 172 virtual ~DeleteResourceRequest(); | |
| 173 | |
| 174 protected: | |
| 175 // UrlFetchRequestBase overrides. | |
| 176 virtual GURL GetURL() const OVERRIDE; | |
| 177 virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; | |
| 178 virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE; | |
| 179 | |
| 180 private: | |
| 181 const GDataWapiUrlGenerator url_generator_; | |
| 182 const std::string resource_id_; | |
| 183 const std::string etag_; | |
| 184 | |
| 185 DISALLOW_COPY_AND_ASSIGN(DeleteResourceRequest); | |
| 186 }; | |
| 187 | |
| 188 //========================== CreateDirectoryRequest ========================== | |
| 189 | |
| 190 // This class performs the request for creating a directory. | |
| 191 class CreateDirectoryRequest : public GetDataRequest { | |
| 192 public: | |
| 193 // A new directory will be created under a directory specified by | |
| 194 // |parent_resource_id|. If this parameter is empty, a new directory will | |
| 195 // be created in the root directory. | |
| 196 // |callback| must not be null. | |
| 197 CreateDirectoryRequest(RequestSender* sender, | |
| 198 const GDataWapiUrlGenerator& url_generator, | |
| 199 const GetDataCallback& callback, | |
| 200 const std::string& parent_resource_id, | |
| 201 const std::string& directory_title); | |
| 202 virtual ~CreateDirectoryRequest(); | |
| 203 | |
| 204 protected: | |
| 205 // UrlFetchRequestBase overrides. | |
| 206 virtual GURL GetURL() const OVERRIDE; | |
| 207 virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; | |
| 208 virtual bool GetContentData(std::string* upload_content_type, | |
| 209 std::string* upload_content) OVERRIDE; | |
| 210 | |
| 211 private: | |
| 212 const GDataWapiUrlGenerator url_generator_; | |
| 213 const std::string parent_resource_id_; | |
| 214 const std::string directory_title_; | |
| 215 | |
| 216 DISALLOW_COPY_AND_ASSIGN(CreateDirectoryRequest); | |
| 217 }; | |
| 218 | |
| 219 //=========================== RenameResourceRequest ========================== | |
| 220 | |
| 221 // This class performs the request for renaming a document/file/directory. | |
| 222 class RenameResourceRequest : public EntryActionRequest { | |
| 223 public: | |
| 224 // |callback| must not be null. | |
| 225 RenameResourceRequest(RequestSender* sender, | |
| 226 const GDataWapiUrlGenerator& url_generator, | |
| 227 const EntryActionCallback& callback, | |
| 228 const std::string& resource_id, | |
| 229 const std::string& new_title); | |
| 230 virtual ~RenameResourceRequest(); | |
| 231 | |
| 232 protected: | |
| 233 // UrlFetchRequestBase overrides. | |
| 234 virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; | |
| 235 virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE; | |
| 236 virtual GURL GetURL() const OVERRIDE; | |
| 237 virtual bool GetContentData(std::string* upload_content_type, | |
| 238 std::string* upload_content) OVERRIDE; | |
| 239 | |
| 240 private: | |
| 241 const GDataWapiUrlGenerator url_generator_; | |
| 242 const std::string resource_id_; | |
| 243 const std::string new_title_; | |
| 244 | |
| 245 DISALLOW_COPY_AND_ASSIGN(RenameResourceRequest); | |
| 246 }; | |
| 247 | |
| 248 //=========================== AuthorizeAppRequest ========================== | |
| 249 | |
| 250 // This class performs the request for authorizing an application specified | |
| 251 // by |app_id| to access a document specified by |resource_id|. | |
| 252 class AuthorizeAppRequest : public GetDataRequest { | |
| 253 public: | |
| 254 // |callback| must not be null. | |
| 255 AuthorizeAppRequest(RequestSender* sender, | |
| 256 const GDataWapiUrlGenerator& url_generator, | |
| 257 const AuthorizeAppCallback& callback, | |
| 258 const std::string& resource_id, | |
| 259 const std::string& app_id); | |
| 260 virtual ~AuthorizeAppRequest(); | |
| 261 | |
| 262 protected: | |
| 263 // UrlFetchRequestBase overrides. | |
| 264 virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; | |
| 265 virtual bool GetContentData(std::string* upload_content_type, | |
| 266 std::string* upload_content) OVERRIDE; | |
| 267 virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE; | |
| 268 virtual GURL GetURL() const OVERRIDE; | |
| 269 | |
| 270 private: | |
| 271 const GDataWapiUrlGenerator url_generator_; | |
| 272 const std::string resource_id_; | |
| 273 const std::string app_id_; | |
| 274 | |
| 275 DISALLOW_COPY_AND_ASSIGN(AuthorizeAppRequest); | |
| 276 }; | |
| 277 | |
| 278 //======================= AddResourceToDirectoryRequest ====================== | |
| 279 | |
| 280 // This class performs the request for adding a document/file/directory | |
| 281 // to a directory. | |
| 282 class AddResourceToDirectoryRequest : public EntryActionRequest { | |
| 283 public: | |
| 284 // |callback| must not be null. | |
| 285 AddResourceToDirectoryRequest(RequestSender* sender, | |
| 286 const GDataWapiUrlGenerator& url_generator, | |
| 287 const EntryActionCallback& callback, | |
| 288 const std::string& parent_resource_id, | |
| 289 const std::string& resource_id); | |
| 290 virtual ~AddResourceToDirectoryRequest(); | |
| 291 | |
| 292 protected: | |
| 293 // UrlFetchRequestBase overrides. | |
| 294 virtual GURL GetURL() const OVERRIDE; | |
| 295 virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; | |
| 296 virtual bool GetContentData(std::string* upload_content_type, | |
| 297 std::string* upload_content) OVERRIDE; | |
| 298 | |
| 299 private: | |
| 300 const GDataWapiUrlGenerator url_generator_; | |
| 301 const std::string parent_resource_id_; | |
| 302 const std::string resource_id_; | |
| 303 | |
| 304 DISALLOW_COPY_AND_ASSIGN(AddResourceToDirectoryRequest); | |
| 305 }; | |
| 306 | |
| 307 //==================== RemoveResourceFromDirectoryRequest ==================== | |
| 308 | |
| 309 // This class performs the request for removing a document/file/directory | |
| 310 // from a directory. | |
| 311 class RemoveResourceFromDirectoryRequest : public EntryActionRequest { | |
| 312 public: | |
| 313 // |callback| must not be null. | |
| 314 RemoveResourceFromDirectoryRequest(RequestSender* sender, | |
| 315 const GDataWapiUrlGenerator& url_generator, | |
| 316 const EntryActionCallback& callback, | |
| 317 const std::string& parent_resource_id, | |
| 318 const std::string& resource_id); | |
| 319 virtual ~RemoveResourceFromDirectoryRequest(); | |
| 320 | |
| 321 protected: | |
| 322 // UrlFetchRequestBase overrides. | |
| 323 virtual GURL GetURL() const OVERRIDE; | |
| 324 virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; | |
| 325 virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE; | |
| 326 | |
| 327 private: | |
| 328 const GDataWapiUrlGenerator url_generator_; | |
| 329 const std::string resource_id_; | |
| 330 const std::string parent_resource_id_; | |
| 331 | |
| 332 DISALLOW_COPY_AND_ASSIGN(RemoveResourceFromDirectoryRequest); | |
| 333 }; | |
| 334 | |
| 335 //======================= InitiateUploadNewFileRequest ======================= | |
| 336 | |
| 337 // This class performs the request for initiating the upload of a new file. | |
| 338 class InitiateUploadNewFileRequest : public InitiateUploadRequestBase { | |
| 339 public: | |
| 340 // |title| should be set. | |
| 341 // |parent_upload_url| should be the upload_url() of the parent directory. | |
| 342 // (resumable-create-media URL) | |
| 343 // See also the comments of InitiateUploadRequestBase for more details | |
| 344 // about the other parameters. | |
| 345 InitiateUploadNewFileRequest(RequestSender* sender, | |
| 346 const GDataWapiUrlGenerator& url_generator, | |
| 347 const InitiateUploadCallback& callback, | |
| 348 const std::string& content_type, | |
| 349 int64 content_length, | |
| 350 const std::string& parent_resource_id, | |
| 351 const std::string& title); | |
| 352 virtual ~InitiateUploadNewFileRequest(); | |
| 353 | |
| 354 protected: | |
| 355 // UrlFetchRequestBase overrides. | |
| 356 virtual GURL GetURL() const OVERRIDE; | |
| 357 virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; | |
| 358 virtual bool GetContentData(std::string* upload_content_type, | |
| 359 std::string* upload_content) OVERRIDE; | |
| 360 | |
| 361 private: | |
| 362 const GDataWapiUrlGenerator url_generator_; | |
| 363 const std::string parent_resource_id_; | |
| 364 const std::string title_; | |
| 365 | |
| 366 DISALLOW_COPY_AND_ASSIGN(InitiateUploadNewFileRequest); | |
| 367 }; | |
| 368 | |
| 369 //==================== InitiateUploadExistingFileRequest ===================== | |
| 370 | |
| 371 // This class performs the request for initiating the upload of an existing | |
| 372 // file. | |
| 373 class InitiateUploadExistingFileRequest | |
| 374 : public InitiateUploadRequestBase { | |
| 375 public: | |
| 376 // |upload_url| should be the upload_url() of the file | |
| 377 // (resumable-create-media URL) | |
| 378 // |etag| should be set if it is available to detect the upload confliction. | |
| 379 // See also the comments of InitiateUploadRequestBase for more details | |
| 380 // about the other parameters. | |
| 381 InitiateUploadExistingFileRequest(RequestSender* sender, | |
| 382 const GDataWapiUrlGenerator& url_generator, | |
| 383 const InitiateUploadCallback& callback, | |
| 384 const std::string& content_type, | |
| 385 int64 content_length, | |
| 386 const std::string& resource_id, | |
| 387 const std::string& etag); | |
| 388 virtual ~InitiateUploadExistingFileRequest(); | |
| 389 | |
| 390 protected: | |
| 391 // UrlFetchRequestBase overrides. | |
| 392 virtual GURL GetURL() const OVERRIDE; | |
| 393 virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; | |
| 394 virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE; | |
| 395 virtual bool GetContentData(std::string* upload_content_type, | |
| 396 std::string* upload_content) OVERRIDE; | |
| 397 | |
| 398 private: | |
| 399 const GDataWapiUrlGenerator url_generator_; | |
| 400 const std::string resource_id_; | |
| 401 const std::string etag_; | |
| 402 | |
| 403 DISALLOW_COPY_AND_ASSIGN(InitiateUploadExistingFileRequest); | |
| 404 }; | |
| 405 | |
| 406 //============================ ResumeUploadRequest =========================== | |
| 407 | |
| 408 // Performs the request for resuming the upload of a file. | |
| 409 class ResumeUploadRequest : public ResumeUploadRequestBase { | |
| 410 public: | |
| 411 // See also ResumeUploadRequestBase's comment for parameters meaning. | |
| 412 // |callback| must not be null. | |
| 413 ResumeUploadRequest(RequestSender* sender, | |
| 414 const UploadRangeCallback& callback, | |
| 415 const ProgressCallback& progress_callback, | |
| 416 const GURL& upload_location, | |
| 417 int64 start_position, | |
| 418 int64 end_position, | |
| 419 int64 content_length, | |
| 420 const std::string& content_type, | |
| 421 const base::FilePath& local_file_path); | |
| 422 virtual ~ResumeUploadRequest(); | |
| 423 | |
| 424 protected: | |
| 425 // UploadRangeRequestBase overrides. | |
| 426 virtual void OnRangeRequestComplete( | |
| 427 const UploadRangeResponse& response, | |
| 428 scoped_ptr<base::Value> value) OVERRIDE; | |
| 429 // content::UrlFetcherDelegate overrides. | |
| 430 virtual void OnURLFetchUploadProgress(const net::URLFetcher* source, | |
| 431 int64 current, int64 total) OVERRIDE; | |
| 432 | |
| 433 private: | |
| 434 const UploadRangeCallback callback_; | |
| 435 const ProgressCallback progress_callback_; | |
| 436 | |
| 437 DISALLOW_COPY_AND_ASSIGN(ResumeUploadRequest); | |
| 438 }; | |
| 439 | |
| 440 //========================== GetUploadStatusRequest ========================== | |
| 441 | |
| 442 // Performs the request to request the current upload status of a file. | |
| 443 class GetUploadStatusRequest : public GetUploadStatusRequestBase { | |
| 444 public: | |
| 445 // See also GetUploadStatusRequestBase's comment for parameters meaning. | |
| 446 // |callback| must not be null. | |
| 447 GetUploadStatusRequest(RequestSender* sender, | |
| 448 const UploadRangeCallback& callback, | |
| 449 const GURL& upload_url, | |
| 450 int64 content_length); | |
| 451 virtual ~GetUploadStatusRequest(); | |
| 452 | |
| 453 protected: | |
| 454 // UploadRangeRequestBase overrides. | |
| 455 virtual void OnRangeRequestComplete( | |
| 456 const UploadRangeResponse& response, | |
| 457 scoped_ptr<base::Value> value) OVERRIDE; | |
| 458 | |
| 459 private: | |
| 460 const UploadRangeCallback callback_; | |
| 461 | |
| 462 DISALLOW_COPY_AND_ASSIGN(GetUploadStatusRequest); | |
| 463 }; | |
| 464 | |
| 465 | |
| 466 //========================== DownloadFileRequest ========================== | |
| 467 | |
| 468 // This class performs the request for downloading of a specified file. | |
| 469 class DownloadFileRequest : public DownloadFileRequestBase { | |
| 470 public: | |
| 471 // See also DownloadFileRequestBase's comment for parameters meaning. | |
| 472 DownloadFileRequest(RequestSender* sender, | |
| 473 const GDataWapiUrlGenerator& url_generator, | |
| 474 const DownloadActionCallback& download_action_callback, | |
| 475 const GetContentCallback& get_content_callback, | |
| 476 const ProgressCallback& progress_callback, | |
| 477 const std::string& resource_id, | |
| 478 const base::FilePath& output_file_path); | |
| 479 virtual ~DownloadFileRequest(); | |
| 480 | |
| 481 DISALLOW_COPY_AND_ASSIGN(DownloadFileRequest); | |
| 482 }; | |
| 483 | |
| 484 } // namespace google_apis | 42 } // namespace google_apis |
| 485 | 43 |
| 486 #endif // GOOGLE_APIS_DRIVE_GDATA_WAPI_REQUESTS_H_ | 44 #endif // GOOGLE_APIS_DRIVE_GDATA_WAPI_REQUESTS_H_ |
| OLD | NEW |