001package com.box.sdk; 002 003import java.io.IOException; 004import java.io.InputStream; 005import java.io.OutputStream; 006import java.net.MalformedURLException; 007import java.net.URL; 008import java.util.ArrayList; 009import java.util.Collection; 010import java.util.Date; 011import java.util.EnumSet; 012import java.util.List; 013 014import com.eclipsesource.json.JsonArray; 015import com.eclipsesource.json.JsonObject; 016import com.eclipsesource.json.JsonValue; 017 018 019/** 020 * Represents an individual file on Box. This class can be used to download a file's contents, upload new versions, and 021 * perform other common file operations (move, copy, delete, etc.). 022 * 023 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked 024 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error 025 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p> 026 */ 027public class BoxFile extends BoxItem { 028 029 /** 030 * An array of all possible file fields that can be requested when calling {@link #getInfo()}. 031 */ 032 public static final String[] ALL_FIELDS = {"type", "id", "sequence_id", "etag", "sha1", "name", 033 "description", "size", "path_collection", "created_at", "modified_at", "trashed_at", "purged_at", 034 "content_created_at", "content_modified_at", "created_by", "modified_by", "owned_by", "shared_link", "parent", 035 "item_status", "version_number", "comment_count", "permissions", "tags", "lock", "extension", "is_package", 036 "file_version", "expiring_embed_link"}; 037 038 private static final URLTemplate FILE_URL_TEMPLATE = new URLTemplate("files/%s"); 039 private static final URLTemplate CONTENT_URL_TEMPLATE = new URLTemplate("files/%s/content"); 040 private static final URLTemplate VERSIONS_URL_TEMPLATE = new URLTemplate("files/%s/versions"); 041 private static final URLTemplate COPY_URL_TEMPLATE = new URLTemplate("files/%s/copy"); 042 private static final URLTemplate ADD_COMMENT_URL_TEMPLATE = new URLTemplate("comments"); 043 private static final URLTemplate GET_COMMENTS_URL_TEMPLATE = new URLTemplate("files/%s/comments"); 044 private static final URLTemplate METADATA_URL_TEMPLATE = new URLTemplate("files/%s/metadata/%s"); 045 private static final URLTemplate ADD_TASK_URL_TEMPLATE = new URLTemplate("tasks"); 046 private static final URLTemplate GET_TASKS_URL_TEMPLATE = new URLTemplate("files/%s/tasks"); 047 private static final String DEFAULT_METADATA_TYPE = "properties"; 048 private static final int BUFFER_SIZE = 8192; 049 050 051 /** 052 * Constructs a BoxFile for a file with a given ID. 053 * @param api the API connection to be used by the file. 054 * @param id the ID of the file. 055 */ 056 public BoxFile(BoxAPIConnection api, String id) { 057 super(api, id); 058 } 059 060 @Override 061 public BoxSharedLink createSharedLink(BoxSharedLink.Access access, Date unshareDate, 062 BoxSharedLink.Permissions permissions) { 063 064 BoxSharedLink sharedLink = new BoxSharedLink(access, unshareDate, permissions); 065 Info info = new Info(); 066 info.setSharedLink(sharedLink); 067 068 this.updateInfo(info); 069 return info.getSharedLink(); 070 } 071 072 /** 073 * Adds a comment to this file. The message can contain @mentions by using the string @[userid:username] anywhere 074 * within the message, where userid and username are the ID and username of the person being mentioned. 075 * @see <a href="https://developers.box.com/docs/#comments-add-a-comment-to-an-item">the tagged_message field 076 * for including @mentions.</a> 077 * @param message the comment's message. 078 * @return information about the newly added comment. 079 */ 080 public BoxComment.Info addComment(String message) { 081 JsonObject itemJSON = new JsonObject(); 082 itemJSON.add("type", "file"); 083 itemJSON.add("id", this.getID()); 084 085 JsonObject requestJSON = new JsonObject(); 086 requestJSON.add("item", itemJSON); 087 if (BoxComment.messageContainsMention(message)) { 088 requestJSON.add("tagged_message", message); 089 } else { 090 requestJSON.add("message", message); 091 } 092 093 URL url = ADD_COMMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL()); 094 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 095 request.setBody(requestJSON.toString()); 096 BoxJSONResponse response = (BoxJSONResponse) request.send(); 097 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 098 099 BoxComment addedComment = new BoxComment(this.getAPI(), responseJSON.get("id").asString()); 100 return addedComment.new Info(responseJSON); 101 } 102 103 /** 104 * Adds a new task to this file. The task can have an optional message to include, and a due date. 105 * @param action the action the task assignee will be prompted to do. 106 * @param message an optional message to include with the task. 107 * @param dueAt the day at which this task is due. 108 * @return information about the newly added task. 109 */ 110 public BoxTask.Info addTask(BoxTask.Action action, String message, Date dueAt) { 111 JsonObject itemJSON = new JsonObject(); 112 itemJSON.add("type", "file"); 113 itemJSON.add("id", this.getID()); 114 115 JsonObject requestJSON = new JsonObject(); 116 requestJSON.add("item", itemJSON); 117 requestJSON.add("action", action.toJSONString()); 118 119 if (message != null && !message.isEmpty()) { 120 requestJSON.add("message", message); 121 } 122 123 if (dueAt != null) { 124 requestJSON.add("due_at", dueAt.toString()); 125 } 126 127 URL url = ADD_TASK_URL_TEMPLATE.build(this.getAPI().getBaseURL()); 128 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 129 request.setBody(requestJSON.toString()); 130 BoxJSONResponse response = (BoxJSONResponse) request.send(); 131 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 132 133 BoxTask addedTask = new BoxTask(this.getAPI(), responseJSON.get("id").asString()); 134 return addedTask.new Info(responseJSON); 135 } 136 137 /** 138 * Downloads the contents of this file to a given OutputStream. 139 * @param output the stream to where the file will be written. 140 */ 141 public void download(OutputStream output) { 142 this.download(output, null); 143 } 144 145 /** 146 * Downloads the contents of this file to a given OutputStream while reporting the progress to a ProgressListener. 147 * @param output the stream to where the file will be written. 148 * @param listener a listener for monitoring the download's progress. 149 */ 150 public void download(OutputStream output, ProgressListener listener) { 151 URL url = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 152 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 153 BoxAPIResponse response = request.send(); 154 InputStream input = response.getBody(listener); 155 156 byte[] buffer = new byte[BUFFER_SIZE]; 157 try { 158 int n = input.read(buffer); 159 while (n != -1) { 160 output.write(buffer, 0, n); 161 n = input.read(buffer); 162 } 163 } catch (IOException e) { 164 throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e); 165 } finally { 166 response.disconnect(); 167 } 168 } 169 170 /** 171 * Downloads a part of this file's contents, starting at specified byte offset. 172 * @param output the stream to where the file will be written. 173 * @param offset the byte offset at which to start the download. 174 */ 175 public void downloadRange(OutputStream output, long offset) { 176 this.downloadRange(output, offset, -1); 177 } 178 179 /** 180 * Downloads a part of this file's contents, starting at rangeStart and stopping at rangeEnd. 181 * @param output the stream to where the file will be written. 182 * @param rangeStart the byte offset at which to start the download. 183 * @param rangeEnd the byte offset at which to stop the download. 184 */ 185 public void downloadRange(OutputStream output, long rangeStart, long rangeEnd) { 186 this.downloadRange(output, rangeStart, rangeEnd, null); 187 } 188 189 /** 190 * Downloads a part of this file's contents, starting at rangeStart and stopping at rangeEnd, while reporting the 191 * progress to a ProgressListener. 192 * @param output the stream to where the file will be written. 193 * @param rangeStart the byte offset at which to start the download. 194 * @param rangeEnd the byte offset at which to stop the download. 195 * @param listener a listener for monitoring the download's progress. 196 */ 197 public void downloadRange(OutputStream output, long rangeStart, long rangeEnd, ProgressListener listener) { 198 URL url = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 199 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 200 if (rangeEnd > 0) { 201 request.addHeader("Range", String.format("bytes=%s-%s", Long.toString(rangeStart), 202 Long.toString(rangeEnd))); 203 } else { 204 request.addHeader("Range", String.format("bytes=%s-", Long.toString(rangeStart))); 205 } 206 207 BoxAPIResponse response = request.send(); 208 InputStream input = response.getBody(listener); 209 210 byte[] buffer = new byte[BUFFER_SIZE]; 211 try { 212 int n = input.read(buffer); 213 while (n != -1) { 214 output.write(buffer, 0, n); 215 n = input.read(buffer); 216 } 217 } catch (IOException e) { 218 throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e); 219 } finally { 220 response.disconnect(); 221 } 222 } 223 224 @Override 225 public BoxFile.Info copy(BoxFolder destination) { 226 return this.copy(destination, null); 227 } 228 229 @Override 230 public BoxFile.Info copy(BoxFolder destination, String newName) { 231 URL url = COPY_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 232 233 JsonObject parent = new JsonObject(); 234 parent.add("id", destination.getID()); 235 236 JsonObject copyInfo = new JsonObject(); 237 copyInfo.add("parent", parent); 238 if (newName != null) { 239 copyInfo.add("name", newName); 240 } 241 242 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 243 request.setBody(copyInfo.toString()); 244 BoxJSONResponse response = (BoxJSONResponse) request.send(); 245 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 246 BoxFile copiedFile = new BoxFile(this.getAPI(), responseJSON.get("id").asString()); 247 return copiedFile.new Info(responseJSON); 248 } 249 250 /** 251 * Deletes this file by moving it to the trash. 252 */ 253 public void delete() { 254 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 255 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 256 BoxAPIResponse response = request.send(); 257 response.disconnect(); 258 } 259 260 @Override 261 public BoxItem.Info move(BoxFolder destination) { 262 return this.move(destination, null); 263 } 264 265 @Override 266 public BoxItem.Info move(BoxFolder destination, String newName) { 267 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 268 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 269 270 JsonObject parent = new JsonObject(); 271 parent.add("id", destination.getID()); 272 273 JsonObject updateInfo = new JsonObject(); 274 updateInfo.add("parent", parent); 275 if (newName != null) { 276 updateInfo.add("name", newName); 277 } 278 279 request.setBody(updateInfo.toString()); 280 BoxJSONResponse response = (BoxJSONResponse) request.send(); 281 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 282 BoxFile movedFile = new BoxFile(this.getAPI(), responseJSON.get("id").asString()); 283 return movedFile.new Info(responseJSON); 284 } 285 286 /** 287 * Renames this file. 288 * @param newName the new name of the file. 289 */ 290 public void rename(String newName) { 291 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 292 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 293 294 JsonObject updateInfo = new JsonObject(); 295 updateInfo.add("name", newName); 296 297 request.setBody(updateInfo.toString()); 298 BoxAPIResponse response = request.send(); 299 response.disconnect(); 300 } 301 302 @Override 303 public BoxFile.Info getInfo() { 304 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 305 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 306 BoxJSONResponse response = (BoxJSONResponse) request.send(); 307 return new Info(response.getJSON()); 308 } 309 310 @Override 311 public BoxFile.Info getInfo(String... fields) { 312 String queryString = new QueryStringBuilder().appendParam("fields", fields).toString(); 313 URL url = FILE_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 314 315 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 316 BoxJSONResponse response = (BoxJSONResponse) request.send(); 317 return new Info(response.getJSON()); 318 } 319 320 /** 321 * Updates the information about this file with any info fields that have been modified locally. 322 * 323 * <p>The only fields that will be updated are the ones that have been modified locally. For example, the following 324 * code won't update any information (or even send a network request) since none of the info's fields were 325 * changed:</p> 326 * 327 * <pre>BoxFile file = new File(api, id); 328 *BoxFile.Info info = file.getInfo(); 329 *file.updateInfo(info);</pre> 330 * 331 * @param info the updated info. 332 */ 333 public void updateInfo(BoxFile.Info info) { 334 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 335 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 336 request.setBody(info.getPendingChanges()); 337 BoxJSONResponse response = (BoxJSONResponse) request.send(); 338 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 339 info.update(jsonObject); 340 } 341 342 /** 343 * Gets any previous versions of this file. Note that only users with premium accounts will be able to retrieve 344 * previous versions of their files. 345 * @return a list of previous file versions. 346 */ 347 public Collection<BoxFileVersion> getVersions() { 348 URL url = VERSIONS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 349 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 350 BoxJSONResponse response = (BoxJSONResponse) request.send(); 351 352 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 353 JsonArray entries = jsonObject.get("entries").asArray(); 354 Collection<BoxFileVersion> versions = new ArrayList<BoxFileVersion>(); 355 for (JsonValue entry : entries) { 356 versions.add(new BoxFileVersion(this.getAPI(), entry.asObject(), this.getID())); 357 } 358 359 return versions; 360 } 361 362 /** 363 * Checks if the file can be successfully uploaded by using the preflight check. 364 * @param name the name to give the uploaded file or null to use existing name. 365 * @param fileSize the size of the file used for account capacity calculations. 366 * @param parentID the ID of the parent folder that the new version is being uploaded to. 367 */ 368 public void canUploadVersion(String name, long fileSize, String parentID) { 369 URL url = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 370 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "OPTIONS"); 371 372 JsonObject parent = new JsonObject(); 373 parent.add("id", parentID); 374 375 JsonObject preflightInfo = new JsonObject(); 376 preflightInfo.add("parent", parent); 377 if (name != null) { 378 preflightInfo.add("name", name); 379 } 380 381 preflightInfo.add("size", fileSize); 382 383 request.setBody(preflightInfo.toString()); 384 BoxAPIResponse response = request.send(); 385 response.disconnect(); 386 } 387 388 /** 389 * Uploads a new version of this file, replacing the current version. Note that only users with premium accounts 390 * will be able to view and recover previous versions of the file. 391 * @param fileContent a stream containing the new file contents. 392 */ 393 public void uploadVersion(InputStream fileContent) { 394 this.uploadVersion(fileContent, null); 395 } 396 397 /** 398 * Uploads a new version of this file, replacing the current version. Note that only users with premium accounts 399 * will be able to view and recover previous versions of the file. 400 * @param fileContent a stream containing the new file contents. 401 * @param modified the date that the new version was modified. 402 */ 403 public void uploadVersion(InputStream fileContent, Date modified) { 404 this.uploadVersion(fileContent, modified, 0, null); 405 } 406 407 /** 408 * Uploads a new version of this file, replacing the current version, while reporting the progress to a 409 * ProgressListener. Note that only users with premium accounts will be able to view and recover previous versions 410 * of the file. 411 * @param fileContent a stream containing the new file contents. 412 * @param modified the date that the new version was modified. 413 * @param fileSize the size of the file used for determining the progress of the upload. 414 * @param listener a listener for monitoring the upload's progress. 415 */ 416 public void uploadVersion(InputStream fileContent, Date modified, long fileSize, ProgressListener listener) { 417 URL uploadURL = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL(), this.getID()); 418 BoxMultipartRequest request = new BoxMultipartRequest(getAPI(), uploadURL); 419 if (fileSize > 0) { 420 request.setFile(fileContent, "", fileSize); 421 } else { 422 request.setFile(fileContent, ""); 423 } 424 425 if (modified != null) { 426 request.putField("content_modified_at", modified); 427 } 428 429 BoxAPIResponse response; 430 if (listener == null) { 431 response = request.send(); 432 } else { 433 response = request.send(listener); 434 } 435 response.disconnect(); 436 } 437 438 /** 439 * Gets an expiring URL for creating an embedded preview session. The URL will expire after 60 seconds and the 440 * preview session will expire after 60 minutes. 441 * @return the expiring preview link 442 */ 443 public URL getPreviewLink() { 444 BoxFile.Info info = this.getInfo("expiring_embed_link"); 445 446 return info.getPreviewLink(); 447 } 448 449 /** 450 * Gets a list of any comments on this file. 451 * @return a list of comments on this file. 452 */ 453 public List<BoxComment.Info> getComments() { 454 URL url = GET_COMMENTS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 455 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 456 BoxJSONResponse response = (BoxJSONResponse) request.send(); 457 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 458 459 int totalCount = responseJSON.get("total_count").asInt(); 460 List<BoxComment.Info> comments = new ArrayList<BoxComment.Info>(totalCount); 461 JsonArray entries = responseJSON.get("entries").asArray(); 462 for (JsonValue value : entries) { 463 JsonObject commentJSON = value.asObject(); 464 BoxComment comment = new BoxComment(this.getAPI(), commentJSON.get("id").asString()); 465 BoxComment.Info info = comment.new Info(commentJSON); 466 comments.add(info); 467 } 468 469 return comments; 470 } 471 472 /** 473 * Gets a list of any tasks on this file. 474 * @return a list of tasks on this file. 475 */ 476 public List<BoxTask.Info> getTasks() { 477 URL url = GET_TASKS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 478 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 479 BoxJSONResponse response = (BoxJSONResponse) request.send(); 480 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 481 482 int totalCount = responseJSON.get("total_count").asInt(); 483 List<BoxTask.Info> tasks = new ArrayList<BoxTask.Info>(totalCount); 484 JsonArray entries = responseJSON.get("entries").asArray(); 485 for (JsonValue value : entries) { 486 JsonObject taskJSON = value.asObject(); 487 BoxTask task = new BoxTask(this.getAPI(), taskJSON.get("id").asString()); 488 BoxTask.Info info = task.new Info(taskJSON); 489 tasks.add(info); 490 } 491 492 return tasks; 493 } 494 495 /** 496 * Creates metadata on this file. 497 * @param metadata The new metadata values. 498 * @return the metadata returned from the server. 499 */ 500 public Metadata createMetadata(Metadata metadata) { 501 return this.createMetadata(DEFAULT_METADATA_TYPE, metadata); 502 } 503 504 /** 505 * Creates the metadata of specified type. 506 * @param typeName the metadata type name. 507 * @param metadata the new metadata values. 508 * @return the metadata returned from the server. 509 */ 510 public Metadata createMetadata(String typeName, Metadata metadata) { 511 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), typeName); 512 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "POST"); 513 request.addHeader("Content-Type", "application/json"); 514 request.setBody(metadata.toString()); 515 BoxJSONResponse response = (BoxJSONResponse) request.send(); 516 return new Metadata(JsonObject.readFrom(response.getJSON())); 517 } 518 519 /** 520 * Gets the file properties metadata. 521 * @return the metadata returned from the server. 522 */ 523 public Metadata getMetadata() { 524 return this.getMetadata(DEFAULT_METADATA_TYPE); 525 } 526 527 /** 528 * Gets the file metadata of specified type. 529 * @param typeName the metadata type name. 530 * @return the metadata returned from the server. 531 */ 532 public Metadata getMetadata(String typeName) { 533 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), typeName); 534 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 535 BoxJSONResponse response = (BoxJSONResponse) request.send(); 536 return new Metadata(JsonObject.readFrom(response.getJSON())); 537 } 538 539 /** 540 * Updates the file metadata. 541 * @param metadata the new metadata values. 542 * @return the metadata returned from the server. 543 */ 544 public Metadata updateMetadata(Metadata metadata) { 545 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), metadata.getTypeName()); 546 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "PUT"); 547 request.addHeader("Content-Type", "application/json-patch+json"); 548 request.setBody(metadata.getPatch()); 549 BoxJSONResponse response = (BoxJSONResponse) request.send(); 550 return new Metadata(JsonObject.readFrom(response.getJSON())); 551 } 552 553 /** 554 * Deletes the file properties metadata. 555 */ 556 public void deleteMetadata() { 557 this.deleteMetadata(DEFAULT_METADATA_TYPE); 558 } 559 560 /** 561 * Deletes the file metadata of specified type. 562 * @param typeName the metadata type name. 563 */ 564 public void deleteMetadata(String typeName) { 565 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), typeName); 566 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 567 request.send(); 568 } 569 570 /** 571 * Contains information about a BoxFile. 572 */ 573 public class Info extends BoxItem.Info { 574 private String sha1; 575 private String versionNumber; 576 private long commentCount; 577 private EnumSet<Permission> permissions; 578 private String extension; 579 private boolean isPackage; 580 private BoxFileVersion version; 581 private URL previewLink; 582 583 /** 584 * Constructs an empty Info object. 585 */ 586 public Info() { 587 super(); 588 } 589 590 /** 591 * Constructs an Info object by parsing information from a JSON string. 592 * @param json the JSON string to parse. 593 */ 594 public Info(String json) { 595 super(json); 596 } 597 598 /** 599 * Constructs an Info object using an already parsed JSON object. 600 * @param jsonObject the parsed JSON object. 601 */ 602 Info(JsonObject jsonObject) { 603 super(jsonObject); 604 } 605 606 @Override 607 public BoxFile getResource() { 608 return BoxFile.this; 609 } 610 611 /** 612 * Gets the SHA1 hash of the file. 613 * @return the SHA1 hash of the file. 614 */ 615 public String getSha1() { 616 return this.sha1; 617 } 618 619 /** 620 * Gets the current version number of the file. 621 * @return the current version number of the file. 622 */ 623 public String getVersionNumber() { 624 return this.versionNumber; 625 } 626 627 /** 628 * Gets the number of comments on the file. 629 * @return the number of comments on the file. 630 */ 631 public long getCommentCount() { 632 return this.commentCount; 633 } 634 635 /** 636 * Gets the permissions that the current user has on the file. 637 * @return the permissions that the current user has on the file. 638 */ 639 public EnumSet<Permission> getPermissions() { 640 return this.permissions; 641 } 642 643 /** 644 * Gets the extension suffix of the file, excluding the dot. 645 * @return the extension of the file. 646 */ 647 public String getExtension() { 648 return this.extension; 649 } 650 651 /** 652 * Gets whether or not the file is an OSX package. 653 * @return true if the file is an OSX package; otherwise false. 654 */ 655 public boolean getIsPackage() { 656 return this.isPackage; 657 } 658 659 /** 660 * Gets the current version details of the file. 661 * @return the current version details of the file. 662 */ 663 public BoxFileVersion getVersion() { 664 return this.version; 665 } 666 667 /** 668 * Gets the current expiring preview link. 669 * @return the expiring preview link 670 */ 671 public URL getPreviewLink() { 672 return this.previewLink; 673 } 674 675 @Override 676 protected void parseJSONMember(JsonObject.Member member) { 677 super.parseJSONMember(member); 678 679 String memberName = member.getName(); 680 JsonValue value = member.getValue(); 681 if (memberName.equals("sha1")) { 682 this.sha1 = value.asString(); 683 } else if (memberName.equals("version_number")) { 684 this.versionNumber = value.asString(); 685 } else if (memberName.equals("comment_count")) { 686 this.commentCount = value.asLong(); 687 } else if (memberName.equals("permissions")) { 688 this.permissions = this.parsePermissions(value.asObject()); 689 } else if (memberName.equals("extension")) { 690 this.extension = value.asString(); 691 } else if (memberName.equals("is_package")) { 692 this.isPackage = value.asBoolean(); 693 } else if (memberName.equals("file_version")) { 694 this.version = this.parseFileVersion(value.asObject()); 695 } else if (memberName.equals("expiring_embed_link")) { 696 try { 697 String urlString = member.getValue().asObject().get("url").asString(); 698 this.previewLink = new URL(urlString); 699 } catch (MalformedURLException e) { 700 throw new BoxAPIException("Couldn't parse expiring_embed_link/url for file", e); 701 } 702 } 703 } 704 705 private EnumSet<Permission> parsePermissions(JsonObject jsonObject) { 706 EnumSet<Permission> permissions = EnumSet.noneOf(Permission.class); 707 for (JsonObject.Member member : jsonObject) { 708 JsonValue value = member.getValue(); 709 if (value.isNull() || !value.asBoolean()) { 710 continue; 711 } 712 713 String memberName = member.getName(); 714 if (memberName.equals("can_download")) { 715 permissions.add(Permission.CAN_DOWNLOAD); 716 } else if (memberName.equals("can_upload")) { 717 permissions.add(Permission.CAN_UPLOAD); 718 } else if (memberName.equals("can_rename")) { 719 permissions.add(Permission.CAN_RENAME); 720 } else if (memberName.equals("can_delete")) { 721 permissions.add(Permission.CAN_DELETE); 722 } else if (memberName.equals("can_share")) { 723 permissions.add(Permission.CAN_SHARE); 724 } else if (memberName.equals("can_set_share_access")) { 725 permissions.add(Permission.CAN_SET_SHARE_ACCESS); 726 } else if (memberName.equals("can_preview")) { 727 permissions.add(Permission.CAN_PREVIEW); 728 } else if (memberName.equals("can_comment")) { 729 permissions.add(Permission.CAN_COMMENT); 730 } 731 } 732 733 return permissions; 734 } 735 736 private BoxFileVersion parseFileVersion(JsonObject jsonObject) { 737 return new BoxFileVersion(BoxFile.this.getAPI(), jsonObject, BoxFile.this.getID()); 738 } 739 } 740 741 /** 742 * Enumerates the possible permissions that a user can have on a file. 743 */ 744 public enum Permission { 745 /** 746 * The user can download the file. 747 */ 748 CAN_DOWNLOAD ("can_download"), 749 750 /** 751 * The user can upload new versions of the file. 752 */ 753 CAN_UPLOAD ("can_upload"), 754 755 /** 756 * The user can rename the file. 757 */ 758 CAN_RENAME ("can_rename"), 759 760 /** 761 * The user can delete the file. 762 */ 763 CAN_DELETE ("can_delete"), 764 765 /** 766 * The user can share the file. 767 */ 768 CAN_SHARE ("can_share"), 769 770 /** 771 * The user can set the access level for shared links to the file. 772 */ 773 CAN_SET_SHARE_ACCESS ("can_set_share_access"), 774 775 /** 776 * The user can preview the file. 777 */ 778 CAN_PREVIEW ("can_preview"), 779 780 /** 781 * The user can comment on the file. 782 */ 783 CAN_COMMENT ("can_comment"); 784 785 private final String jsonValue; 786 787 private Permission(String jsonValue) { 788 this.jsonValue = jsonValue; 789 } 790 791 static Permission fromJSONValue(String jsonValue) { 792 return Permission.valueOf(jsonValue.toUpperCase()); 793 } 794 795 String toJSONValue() { 796 return this.jsonValue; 797 } 798 } 799}