001package com.box.sdk; 002 003import java.io.ByteArrayOutputStream; 004import java.io.IOException; 005import java.io.InputStream; 006import java.io.OutputStream; 007import java.net.MalformedURLException; 008import java.net.URL; 009import java.util.ArrayList; 010import java.util.Collection; 011import java.util.Date; 012import java.util.EnumSet; 013import java.util.List; 014import java.util.concurrent.TimeUnit; 015 016import com.eclipsesource.json.JsonArray; 017import com.eclipsesource.json.JsonObject; 018import com.eclipsesource.json.JsonValue; 019 020 021/** 022 * Represents an individual file on Box. This class can be used to download a file's contents, upload new versions, and 023 * perform other common file operations (move, copy, delete, etc.). 024 * 025 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked 026 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error 027 * handling for errors related to the Box REST API, you should capture this exception explicitly. 028 */ 029@BoxResourceType("file") 030public class BoxFile extends BoxItem { 031 032 /** 033 * An array of all possible file fields that can be requested when calling {@link #getInfo()}. 034 */ 035 public static final String[] ALL_FIELDS = {"type", "id", "sequence_id", "etag", "sha1", "name", 036 "description", "size", "path_collection", "created_at", "modified_at", 037 "trashed_at", "purged_at", "content_created_at", "content_modified_at", 038 "created_by", "modified_by", "owned_by", "shared_link", "parent", 039 "item_status", "version_number", "comment_count", "permissions", "tags", 040 "lock", "extension", "is_package", "file_version", "collections", 041 "watermark_info"}; 042 043 /** 044 * Used to specify what filetype to request for a file thumbnail. 045 */ 046 public enum ThumbnailFileType { 047 /** 048 * PNG image format. 049 */ 050 PNG, 051 052 /** 053 * JPG image format. 054 */ 055 JPG 056 } 057 058 private static final URLTemplate FILE_URL_TEMPLATE = new URLTemplate("files/%s"); 059 private static final URLTemplate CONTENT_URL_TEMPLATE = new URLTemplate("files/%s/content"); 060 private static final URLTemplate VERSIONS_URL_TEMPLATE = new URLTemplate("files/%s/versions"); 061 private static final URLTemplate COPY_URL_TEMPLATE = new URLTemplate("files/%s/copy"); 062 private static final URLTemplate ADD_COMMENT_URL_TEMPLATE = new URLTemplate("comments"); 063 private static final URLTemplate GET_COMMENTS_URL_TEMPLATE = new URLTemplate("files/%s/comments"); 064 private static final URLTemplate METADATA_URL_TEMPLATE = new URLTemplate("files/%s/metadata/%s/%s"); 065 private static final URLTemplate ADD_TASK_URL_TEMPLATE = new URLTemplate("tasks"); 066 private static final URLTemplate GET_TASKS_URL_TEMPLATE = new URLTemplate("files/%s/tasks"); 067 private static final URLTemplate GET_THUMBNAIL_PNG_TEMPLATE = new URLTemplate("files/%s/thumbnail.png"); 068 private static final URLTemplate GET_THUMBNAIL_JPG_TEMPLATE = new URLTemplate("files/%s/thumbnail.jpg"); 069 private static final URLTemplate UPLOAD_SESSION_URL_TEMPLATE = new URLTemplate("files/%s/upload_sessions"); 070 private static final URLTemplate UPLOAD_SESSION_STATUS_URL_TEMPLATE = new URLTemplate( 071 "files/upload_sessions/%s/status"); 072 private static final URLTemplate ABORT_UPLOAD_SESSION_URL_TEMPLATE = new URLTemplate("files/upload_sessions/%s"); 073 074 private static final URLTemplate ADD_COLLABORATION_URL = new URLTemplate("collaborations"); 075 private static final URLTemplate GET_ALL_FILE_COLLABORATIONS_URL = new URLTemplate("files/%s/collaborations"); 076 077 private static final int BUFFER_SIZE = 8192; 078 private static final int GET_COLLABORATORS_PAGE_SIZE = 1000; 079 080 /** 081 * Constructs a BoxFile for a file with a given ID. 082 * 083 * @param api the API connection to be used by the file. 084 * @param id the ID of the file. 085 */ 086 public BoxFile(BoxAPIConnection api, String id) { 087 super(api, id); 088 } 089 090 /** 091 * {@inheritDoc} 092 */ 093 @Override 094 protected URL getItemURL() { 095 return FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 096 } 097 098 @Override 099 public BoxSharedLink createSharedLink(BoxSharedLink.Access access, Date unshareDate, 100 BoxSharedLink.Permissions permissions) { 101 102 BoxSharedLink sharedLink = new BoxSharedLink(access, unshareDate, permissions); 103 Info info = new Info(); 104 info.setSharedLink(sharedLink); 105 106 this.updateInfo(info); 107 return info.getSharedLink(); 108 } 109 110 /** 111 * Adds new {@link BoxWebHook} to this {@link BoxFile}. 112 * 113 * @param address {@link BoxWebHook.Info#getAddress()} 114 * @param triggers {@link BoxWebHook.Info#getTriggers()} 115 * @return created {@link BoxWebHook.Info} 116 */ 117 public BoxWebHook.Info addWebHook(URL address, BoxWebHook.Trigger... triggers) { 118 return BoxWebHook.create(this, address, triggers); 119 } 120 121 /** 122 * Adds a comment to this file. The message can contain @mentions by using the string @[userid:username] anywhere 123 * within the message, where userid and username are the ID and username of the person being mentioned. 124 * 125 * @param message the comment's message. 126 * @return information about the newly added comment. 127 * @see <a href="https://developers.box.com/docs/#comments-add-a-comment-to-an-item">the tagged_message field 128 * for including @mentions.</a> 129 */ 130 public BoxComment.Info addComment(String message) { 131 JsonObject itemJSON = new JsonObject(); 132 itemJSON.add("type", "file"); 133 itemJSON.add("id", this.getID()); 134 135 JsonObject requestJSON = new JsonObject(); 136 requestJSON.add("item", itemJSON); 137 if (BoxComment.messageContainsMention(message)) { 138 requestJSON.add("tagged_message", message); 139 } else { 140 requestJSON.add("message", message); 141 } 142 143 URL url = ADD_COMMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL()); 144 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 145 request.setBody(requestJSON.toString()); 146 BoxJSONResponse response = (BoxJSONResponse) request.send(); 147 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 148 149 BoxComment addedComment = new BoxComment(this.getAPI(), responseJSON.get("id").asString()); 150 return addedComment.new Info(responseJSON); 151 } 152 153 /** 154 * Adds a new task to this file. The task can have an optional message to include, and a due date. 155 * 156 * @param action the action the task assignee will be prompted to do. 157 * @param message an optional message to include with the task. 158 * @param dueAt the day at which this task is due. 159 * @return information about the newly added task. 160 */ 161 public BoxTask.Info addTask(BoxTask.Action action, String message, Date dueAt) { 162 JsonObject itemJSON = new JsonObject(); 163 itemJSON.add("type", "file"); 164 itemJSON.add("id", this.getID()); 165 166 JsonObject requestJSON = new JsonObject(); 167 requestJSON.add("item", itemJSON); 168 requestJSON.add("action", action.toJSONString()); 169 170 if (message != null && !message.isEmpty()) { 171 requestJSON.add("message", message); 172 } 173 174 if (dueAt != null) { 175 requestJSON.add("due_at", BoxDateFormat.format(dueAt)); 176 } 177 178 URL url = ADD_TASK_URL_TEMPLATE.build(this.getAPI().getBaseURL()); 179 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 180 request.setBody(requestJSON.toString()); 181 BoxJSONResponse response = (BoxJSONResponse) request.send(); 182 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 183 184 BoxTask addedTask = new BoxTask(this.getAPI(), responseJSON.get("id").asString()); 185 return addedTask.new Info(responseJSON); 186 } 187 188 /** 189 * Gets an expiring URL for downloading a file directly from Box. This can be user, 190 * for example, for sending as a redirect to a browser to cause the browser 191 * to download the file directly from Box. 192 * 193 * @return the temporary download URL 194 */ 195 public URL getDownloadURL() { 196 URL url = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 197 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 198 request.setFollowRedirects(false); 199 200 BoxRedirectResponse response = (BoxRedirectResponse) request.send(); 201 202 return response.getRedirectURL(); 203 } 204 205 /** 206 * Downloads the contents of this file to a given OutputStream. 207 * 208 * @param output the stream to where the file will be written. 209 */ 210 public void download(OutputStream output) { 211 this.download(output, null); 212 } 213 214 /** 215 * Downloads the contents of this file to a given OutputStream while reporting the progress to a ProgressListener. 216 * 217 * @param output the stream to where the file will be written. 218 * @param listener a listener for monitoring the download's progress. 219 */ 220 public void download(OutputStream output, ProgressListener listener) { 221 URL url = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 222 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 223 BoxAPIResponse response = request.send(); 224 InputStream input = response.getBody(listener); 225 226 byte[] buffer = new byte[BUFFER_SIZE]; 227 try { 228 int n = input.read(buffer); 229 while (n != -1) { 230 output.write(buffer, 0, n); 231 n = input.read(buffer); 232 } 233 } catch (IOException e) { 234 throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e); 235 } finally { 236 response.disconnect(); 237 } 238 } 239 240 /** 241 * Downloads a part of this file's contents, starting at specified byte offset. 242 * 243 * @param output the stream to where the file will be written. 244 * @param offset the byte offset at which to start the download. 245 */ 246 public void downloadRange(OutputStream output, long offset) { 247 this.downloadRange(output, offset, -1); 248 } 249 250 /** 251 * Downloads a part of this file's contents, starting at rangeStart and stopping at rangeEnd. 252 * 253 * @param output the stream to where the file will be written. 254 * @param rangeStart the byte offset at which to start the download. 255 * @param rangeEnd the byte offset at which to stop the download. 256 */ 257 public void downloadRange(OutputStream output, long rangeStart, long rangeEnd) { 258 this.downloadRange(output, rangeStart, rangeEnd, null); 259 } 260 261 /** 262 * Downloads a part of this file's contents, starting at rangeStart and stopping at rangeEnd, while reporting the 263 * progress to a ProgressListener. 264 * 265 * @param output the stream to where the file will be written. 266 * @param rangeStart the byte offset at which to start the download. 267 * @param rangeEnd the byte offset at which to stop the download. 268 * @param listener a listener for monitoring the download's progress. 269 */ 270 public void downloadRange(OutputStream output, long rangeStart, long rangeEnd, ProgressListener listener) { 271 URL url = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 272 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 273 if (rangeEnd > 0) { 274 request.addHeader("Range", String.format("bytes=%s-%s", Long.toString(rangeStart), 275 Long.toString(rangeEnd))); 276 } else { 277 request.addHeader("Range", String.format("bytes=%s-", Long.toString(rangeStart))); 278 } 279 280 BoxAPIResponse response = request.send(); 281 InputStream input = response.getBody(listener); 282 283 byte[] buffer = new byte[BUFFER_SIZE]; 284 try { 285 int n = input.read(buffer); 286 while (n != -1) { 287 output.write(buffer, 0, n); 288 n = input.read(buffer); 289 } 290 } catch (IOException e) { 291 throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e); 292 } finally { 293 response.disconnect(); 294 } 295 } 296 297 @Override 298 public BoxFile.Info copy(BoxFolder destination) { 299 return this.copy(destination, null); 300 } 301 302 @Override 303 public BoxFile.Info copy(BoxFolder destination, String newName) { 304 URL url = COPY_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 305 306 JsonObject parent = new JsonObject(); 307 parent.add("id", destination.getID()); 308 309 JsonObject copyInfo = new JsonObject(); 310 copyInfo.add("parent", parent); 311 if (newName != null) { 312 copyInfo.add("name", newName); 313 } 314 315 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 316 request.setBody(copyInfo.toString()); 317 BoxJSONResponse response = (BoxJSONResponse) request.send(); 318 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 319 BoxFile copiedFile = new BoxFile(this.getAPI(), responseJSON.get("id").asString()); 320 return copiedFile.new Info(responseJSON); 321 } 322 323 /** 324 * Deletes this file by moving it to the trash. 325 */ 326 public void delete() { 327 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 328 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 329 BoxAPIResponse response = request.send(); 330 response.disconnect(); 331 } 332 333 @Override 334 public BoxItem.Info move(BoxFolder destination) { 335 return this.move(destination, null); 336 } 337 338 @Override 339 public BoxItem.Info move(BoxFolder destination, String newName) { 340 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 341 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 342 343 JsonObject parent = new JsonObject(); 344 parent.add("id", destination.getID()); 345 346 JsonObject updateInfo = new JsonObject(); 347 updateInfo.add("parent", parent); 348 if (newName != null) { 349 updateInfo.add("name", newName); 350 } 351 352 request.setBody(updateInfo.toString()); 353 BoxJSONResponse response = (BoxJSONResponse) request.send(); 354 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 355 BoxFile movedFile = new BoxFile(this.getAPI(), responseJSON.get("id").asString()); 356 return movedFile.new Info(responseJSON); 357 } 358 359 /** 360 * Renames this file. 361 * 362 * @param newName the new name of the file. 363 */ 364 public void rename(String newName) { 365 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 366 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 367 368 JsonObject updateInfo = new JsonObject(); 369 updateInfo.add("name", newName); 370 371 request.setBody(updateInfo.toString()); 372 BoxAPIResponse response = request.send(); 373 response.disconnect(); 374 } 375 376 @Override 377 public BoxFile.Info getInfo() { 378 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 379 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 380 BoxJSONResponse response = (BoxJSONResponse) request.send(); 381 return new Info(response.getJSON()); 382 } 383 384 @Override 385 public BoxFile.Info getInfo(String... fields) { 386 String queryString = new QueryStringBuilder().appendParam("fields", fields).toString(); 387 URL url = FILE_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 388 389 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 390 BoxJSONResponse response = (BoxJSONResponse) request.send(); 391 return new Info(response.getJSON()); 392 } 393 394 /** 395 * Updates the information about this file with any info fields that have been modified locally. 396 * 397 * <p>The only fields that will be updated are the ones that have been modified locally. For example, the following 398 * code won't update any information (or even send a network request) since none of the info's fields were 399 * changed:</p> 400 * 401 * <pre>BoxFile file = new File(api, id); 402 * BoxFile.Info info = file.getInfo(); 403 * file.updateInfo(info);</pre> 404 * 405 * @param info the updated info. 406 */ 407 public void updateInfo(BoxFile.Info info) { 408 URL url = FILE_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 409 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 410 request.setBody(info.getPendingChanges()); 411 BoxJSONResponse response = (BoxJSONResponse) request.send(); 412 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 413 info.update(jsonObject); 414 } 415 416 /** 417 * Gets any previous versions of this file. Note that only users with premium accounts will be able to retrieve 418 * previous versions of their files. 419 * 420 * @return a list of previous file versions. 421 */ 422 public Collection<BoxFileVersion> getVersions() { 423 URL url = VERSIONS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 424 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 425 BoxJSONResponse response = (BoxJSONResponse) request.send(); 426 427 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 428 JsonArray entries = jsonObject.get("entries").asArray(); 429 Collection<BoxFileVersion> versions = new ArrayList<BoxFileVersion>(); 430 for (JsonValue entry : entries) { 431 versions.add(new BoxFileVersion(this.getAPI(), entry.asObject(), this.getID())); 432 } 433 434 return versions; 435 } 436 437 /** 438 * Checks if the file can be successfully uploaded by using the preflight check. 439 * 440 * @param name the name to give the uploaded file or null to use existing name. 441 * @param fileSize the size of the file used for account capacity calculations. 442 * @param parentID the ID of the parent folder that the new version is being uploaded to. 443 */ 444 public void canUploadVersion(String name, long fileSize, String parentID) { 445 URL url = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 446 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "OPTIONS"); 447 448 JsonObject parent = new JsonObject(); 449 parent.add("id", parentID); 450 451 JsonObject preflightInfo = new JsonObject(); 452 preflightInfo.add("parent", parent); 453 if (name != null) { 454 preflightInfo.add("name", name); 455 } 456 457 preflightInfo.add("size", fileSize); 458 459 request.setBody(preflightInfo.toString()); 460 BoxAPIResponse response = request.send(); 461 response.disconnect(); 462 } 463 464 /** 465 * Uploads a new version of this file, replacing the current version. Note that only users with premium accounts 466 * will be able to view and recover previous versions of the file. 467 * 468 * @param fileContent a stream containing the new file contents. 469 */ 470 public void uploadVersion(InputStream fileContent) { 471 this.uploadVersion(fileContent, null); 472 } 473 474 /** 475 * Uploads a new version of this file, replacing the current version. Note that only users with premium accounts 476 * will be able to view and recover previous versions of the file. 477 * 478 * @param fileContent a stream containing the new file contents. 479 * @param fileContentSHA1 a string containing the SHA1 hash of the new file contents. 480 */ 481 public void uploadVersion(InputStream fileContent, String fileContentSHA1) { 482 this.uploadVersion(fileContent, fileContentSHA1, null); 483 } 484 485 /** 486 * Uploads a new version of this file, replacing the current version. Note that only users with premium accounts 487 * will be able to view and recover previous versions of the file. 488 * 489 * @param fileContent a stream containing the new file contents. 490 * @param fileContentSHA1 a string containing the SHA1 hash of the new file contents. 491 * @param modified the date that the new version was modified. 492 */ 493 public void uploadVersion(InputStream fileContent, String fileContentSHA1, Date modified) { 494 this.uploadVersion(fileContent, fileContentSHA1, modified, 0, null); 495 } 496 497 /** 498 * Uploads a new version of this file, replacing the current version, while reporting the progress to a 499 * ProgressListener. Note that only users with premium accounts will be able to view and recover previous versions 500 * of the file. 501 * 502 * @param fileContent a stream containing the new file contents. 503 * @param modified the date that the new version was modified. 504 * @param fileSize the size of the file used for determining the progress of the upload. 505 * @param listener a listener for monitoring the upload's progress. 506 */ 507 public void uploadVersion(InputStream fileContent, Date modified, long fileSize, ProgressListener listener) { 508 this.uploadVersion(fileContent, null, modified, fileSize, listener); 509 } 510 511 /** 512 * Uploads a new version of this file, replacing the current version, while reporting the progress to a 513 * ProgressListener. Note that only users with premium accounts will be able to view and recover previous versions 514 * of the file. 515 * 516 * @param fileContent a stream containing the new file contents. 517 * @param fileContentSHA1 the SHA1 hash of the file contents. will be sent along in the Content-MD5 header 518 * @param modified the date that the new version was modified. 519 * @param fileSize the size of the file used for determining the progress of the upload. 520 * @param listener a listener for monitoring the upload's progress. 521 */ 522 public void uploadVersion(InputStream fileContent, String fileContentSHA1, Date modified, long fileSize, 523 ProgressListener listener) { 524 URL uploadURL = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL(), this.getID()); 525 BoxMultipartRequest request = new BoxMultipartRequest(getAPI(), uploadURL); 526 527 if (fileSize > 0) { 528 request.setFile(fileContent, "", fileSize); 529 } else { 530 request.setFile(fileContent, ""); 531 } 532 533 if (fileContentSHA1 != null) { 534 request.setContentSHA1(fileContentSHA1); 535 } 536 537 if (modified != null) { 538 request.putField("content_modified_at", modified); 539 } 540 541 BoxJSONResponse response; 542 if (listener == null) { 543 response = (BoxJSONResponse) request.send(); 544 } else { 545 response = (BoxJSONResponse) request.send(listener); 546 } 547 response.getJSON(); 548 } 549 550 /** 551 * Gets an expiring URL for creating an embedded preview session. The URL will expire after 60 seconds and the 552 * preview session will expire after 60 minutes. 553 * 554 * @return the expiring preview link 555 */ 556 public URL getPreviewLink() { 557 BoxFile.Info info = this.getInfo("expiring_embed_link"); 558 559 return info.getPreviewLink(); 560 } 561 562 563 /** 564 * Retrieves a thumbnail, or smaller image representation, of this file. Sizes of 32x32, 64x64, 128x128, 565 * and 256x256 can be returned in the .png format and sizes of 32x32, 94x94, 160x160, and 320x320 can be returned 566 * in the .jpg format. 567 * 568 * @param fileType either PNG of JPG 569 * @param minWidth minimum width 570 * @param minHeight minimum height 571 * @param maxWidth maximum width 572 * @param maxHeight maximum height 573 * @return the byte array of the thumbnail image 574 */ 575 public byte[] getThumbnail(ThumbnailFileType fileType, int minWidth, int minHeight, int maxWidth, int maxHeight) { 576 QueryStringBuilder builder = new QueryStringBuilder(); 577 builder.appendParam("min_width", minWidth); 578 builder.appendParam("min_height", minHeight); 579 builder.appendParam("max_width", maxWidth); 580 builder.appendParam("max_height", maxHeight); 581 582 URLTemplate template; 583 if (fileType == ThumbnailFileType.PNG) { 584 template = GET_THUMBNAIL_PNG_TEMPLATE; 585 } else if (fileType == ThumbnailFileType.JPG) { 586 template = GET_THUMBNAIL_JPG_TEMPLATE; 587 } else { 588 throw new BoxAPIException("Unsupported thumbnail file type"); 589 } 590 URL url = template.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID()); 591 592 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 593 BoxAPIResponse response = request.send(); 594 595 ByteArrayOutputStream thumbOut = new ByteArrayOutputStream(); 596 InputStream body = response.getBody(); 597 byte[] buffer = new byte[BUFFER_SIZE]; 598 try { 599 int n = body.read(buffer); 600 while (n != -1) { 601 thumbOut.write(buffer, 0, n); 602 n = body.read(buffer); 603 } 604 } catch (IOException e) { 605 throw new BoxAPIException("Error reading thumbnail bytes from response body", e); 606 } finally { 607 response.disconnect(); 608 } 609 610 return thumbOut.toByteArray(); 611 } 612 613 /** 614 * Gets a list of any comments on this file. 615 * 616 * @return a list of comments on this file. 617 */ 618 public List<BoxComment.Info> getComments() { 619 URL url = GET_COMMENTS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 620 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 621 BoxJSONResponse response = (BoxJSONResponse) request.send(); 622 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 623 624 int totalCount = responseJSON.get("total_count").asInt(); 625 List<BoxComment.Info> comments = new ArrayList<BoxComment.Info>(totalCount); 626 JsonArray entries = responseJSON.get("entries").asArray(); 627 for (JsonValue value : entries) { 628 JsonObject commentJSON = value.asObject(); 629 BoxComment comment = new BoxComment(this.getAPI(), commentJSON.get("id").asString()); 630 BoxComment.Info info = comment.new Info(commentJSON); 631 comments.add(info); 632 } 633 634 return comments; 635 } 636 637 /** 638 * Gets a list of any tasks on this file. 639 * 640 * @return a list of tasks on this file. 641 */ 642 public List<BoxTask.Info> getTasks() { 643 URL url = GET_TASKS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 644 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 645 BoxJSONResponse response = (BoxJSONResponse) request.send(); 646 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 647 648 int totalCount = responseJSON.get("total_count").asInt(); 649 List<BoxTask.Info> tasks = new ArrayList<BoxTask.Info>(totalCount); 650 JsonArray entries = responseJSON.get("entries").asArray(); 651 for (JsonValue value : entries) { 652 JsonObject taskJSON = value.asObject(); 653 BoxTask task = new BoxTask(this.getAPI(), taskJSON.get("id").asString()); 654 BoxTask.Info info = task.new Info(taskJSON); 655 tasks.add(info); 656 } 657 658 return tasks; 659 } 660 661 /** 662 * Creates metadata on this file in the global properties template. 663 * 664 * @param metadata The new metadata values. 665 * @return the metadata returned from the server. 666 */ 667 public Metadata createMetadata(Metadata metadata) { 668 return this.createMetadata(Metadata.DEFAULT_METADATA_TYPE, metadata); 669 } 670 671 /** 672 * Creates metadata on this file in the specified template type. 673 * 674 * @param typeName the metadata template type name. 675 * @param metadata the new metadata values. 676 * @return the metadata returned from the server. 677 */ 678 public Metadata createMetadata(String typeName, Metadata metadata) { 679 String scope = Metadata.scopeBasedOnType(typeName); 680 return this.createMetadata(typeName, scope, metadata); 681 } 682 683 /** 684 * Creates metadata on this file in the specified template type. 685 * 686 * @param typeName the metadata template type name. 687 * @param scope the metadata scope (global or enterprise). 688 * @param metadata the new metadata values. 689 * @return the metadata returned from the server. 690 */ 691 public Metadata createMetadata(String typeName, String scope, Metadata metadata) { 692 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), scope, typeName); 693 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "POST"); 694 request.addHeader("Content-Type", "application/json"); 695 request.setBody(metadata.toString()); 696 BoxJSONResponse response = (BoxJSONResponse) request.send(); 697 return new Metadata(JsonObject.readFrom(response.getJSON())); 698 } 699 700 /** 701 * Locks a file. 702 * 703 * @param expiresAt expiration date of the lock. 704 * @return the lock returned from the server. 705 */ 706 public BoxLock lock(Date expiresAt) { 707 return this.lock(expiresAt, false); 708 } 709 710 /** 711 * Locks a file. 712 * 713 * @param expiresAt expiration date of the lock. 714 * @param isDownloadPrevented is downloading of file prevented when locked. 715 * @return the lock returned from the server. 716 */ 717 public BoxLock lock(Date expiresAt, boolean isDownloadPrevented) { 718 String queryString = new QueryStringBuilder().appendParam("fields", "lock").toString(); 719 URL url = FILE_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 720 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "PUT"); 721 722 JsonObject lockConfig = new JsonObject(); 723 lockConfig.add("type", "lock"); 724 lockConfig.add("expires_at", BoxDateFormat.format(expiresAt)); 725 lockConfig.add("is_download_prevented", isDownloadPrevented); 726 727 JsonObject requestJSON = new JsonObject(); 728 requestJSON.add("lock", lockConfig); 729 request.setBody(requestJSON.toString()); 730 731 BoxJSONResponse response = (BoxJSONResponse) request.send(); 732 733 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 734 JsonValue lockValue = responseJSON.get("lock"); 735 JsonObject lockJSON = JsonObject.readFrom(lockValue.toString()); 736 737 return new BoxLock(lockJSON, this.getAPI()); 738 } 739 740 /** 741 * Unlocks a file. 742 */ 743 public void unlock() { 744 String queryString = new QueryStringBuilder().appendParam("fields", "lock").toString(); 745 URL url = FILE_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 746 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "PUT"); 747 748 JsonObject lockObject = new JsonObject(); 749 lockObject.add("lock", JsonObject.NULL); 750 751 request.setBody(lockObject.toString()); 752 request.send(); 753 } 754 755 /** 756 * Used to retrieve all metadata associated with the file. 757 * 758 * @param fields the optional fields to retrieve. 759 * @return An iterable of metadata instances associated with the file. 760 */ 761 public Iterable<Metadata> getAllMetadata(String... fields) { 762 return Metadata.getAllMetadata(this, fields); 763 } 764 765 /** 766 * Gets the file properties metadata. 767 * 768 * @return the metadata returned from the server. 769 */ 770 public Metadata getMetadata() { 771 return this.getMetadata(Metadata.DEFAULT_METADATA_TYPE); 772 } 773 774 /** 775 * Gets the file metadata of specified template type. 776 * 777 * @param typeName the metadata template type name. 778 * @return the metadata returned from the server. 779 */ 780 public Metadata getMetadata(String typeName) { 781 String scope = Metadata.scopeBasedOnType(typeName); 782 return this.getMetadata(typeName, scope); 783 } 784 785 /** 786 * Gets the file metadata of specified template type. 787 * 788 * @param typeName the metadata template type name. 789 * @param scope the metadata scope (global or enterprise). 790 * @return the metadata returned from the server. 791 */ 792 public Metadata getMetadata(String typeName, String scope) { 793 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), scope, typeName); 794 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 795 BoxJSONResponse response = (BoxJSONResponse) request.send(); 796 return new Metadata(JsonObject.readFrom(response.getJSON())); 797 } 798 799 /** 800 * Updates the file metadata. 801 * 802 * @param metadata the new metadata values. 803 * @return the metadata returned from the server. 804 */ 805 public Metadata updateMetadata(Metadata metadata) { 806 String scope; 807 if (metadata.getScope().equals(Metadata.GLOBAL_METADATA_SCOPE)) { 808 scope = Metadata.GLOBAL_METADATA_SCOPE; 809 } else { 810 scope = Metadata.ENTERPRISE_METADATA_SCOPE; 811 } 812 813 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), 814 scope, metadata.getTemplateName()); 815 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "PUT"); 816 request.addHeader("Content-Type", "application/json-patch+json"); 817 request.setBody(metadata.getPatch()); 818 BoxJSONResponse response = (BoxJSONResponse) request.send(); 819 return new Metadata(JsonObject.readFrom(response.getJSON())); 820 } 821 822 /** 823 * Deletes the file properties metadata. 824 */ 825 public void deleteMetadata() { 826 this.deleteMetadata(Metadata.DEFAULT_METADATA_TYPE); 827 } 828 829 /** 830 * Deletes the file metadata of specified template type. 831 * 832 * @param typeName the metadata template type name. 833 */ 834 public void deleteMetadata(String typeName) { 835 String scope = Metadata.scopeBasedOnType(typeName); 836 this.deleteMetadata(typeName, scope); 837 } 838 839 /** 840 * Deletes the file metadata of specified template type. 841 * 842 * @param typeName the metadata template type name. 843 * @param scope the metadata scope (global or enterprise). 844 */ 845 public void deleteMetadata(String typeName, String scope) { 846 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), scope, typeName); 847 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 848 request.send(); 849 } 850 851 /** 852 * Used to retrieve the watermark for the file. 853 * If the file does not have a watermark applied to it, a 404 Not Found will be returned by API. 854 * 855 * @param fields the fields to retrieve. 856 * @return the watermark associated with the file. 857 */ 858 public BoxWatermark getWatermark(String... fields) { 859 return this.getWatermark(FILE_URL_TEMPLATE, fields); 860 } 861 862 /** 863 * Used to apply or update the watermark for the file. 864 * 865 * @return the watermark associated with the file. 866 */ 867 public BoxWatermark applyWatermark() { 868 return this.applyWatermark(FILE_URL_TEMPLATE, BoxWatermark.WATERMARK_DEFAULT_IMPRINT); 869 } 870 871 /** 872 * Removes a watermark from the file. 873 * If the file did not have a watermark applied to it, a 404 Not Found will be returned by API. 874 */ 875 public void removeWatermark() { 876 this.removeWatermark(FILE_URL_TEMPLATE); 877 } 878 879 /** 880 * {@inheritDoc} 881 */ 882 @Override 883 public BoxFile.Info setCollections(BoxCollection... collections) { 884 JsonArray jsonArray = new JsonArray(); 885 for (BoxCollection collection : collections) { 886 JsonObject collectionJSON = new JsonObject(); 887 collectionJSON.add("id", collection.getID()); 888 jsonArray.add(collectionJSON); 889 } 890 JsonObject infoJSON = new JsonObject(); 891 infoJSON.add("collections", jsonArray); 892 893 String queryString = new QueryStringBuilder().appendParam("fields", ALL_FIELDS).toString(); 894 URL url = FILE_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 895 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 896 request.setBody(infoJSON.toString()); 897 BoxJSONResponse response = (BoxJSONResponse) request.send(); 898 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 899 return new Info(jsonObject); 900 } 901 902 /** 903 * Creates an upload session to create a new version of a file in chunks. 904 * This will first verify that the version can be created and then open a session for uploading pieces of the file. 905 * @param fileSize the size of the file that will be uploaded. 906 * @return the created upload session instance. 907 */ 908 public BoxFileUploadSession.Info createUploadSession(long fileSize) { 909 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL(), this.getID()); 910 911 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 912 request.addHeader("Content-Type", "application/json"); 913 914 JsonObject body = new JsonObject(); 915 body.add("file_size", fileSize); 916 request.setBody(body.toString()); 917 918 BoxJSONResponse response = (BoxJSONResponse) request.send(); 919 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 920 921 String sessionId = jsonObject.get("id").asString(); 922 BoxFileUploadSession session = new BoxFileUploadSession(this.getAPI(), sessionId); 923 return session.new Info(jsonObject); 924 } 925 926 /** 927 * Creates a new version of a file. 928 * @param inputStream the stream instance that contains the data. 929 * @param fileSize the size of the file that will be uploaded. 930 * @return the created file instance. 931 * @throws InterruptedException when a thread execution is interrupted. 932 * @throws IOException when reading a stream throws exception. 933 */ 934 public BoxFile.Info uploadLargeFile(InputStream inputStream, long fileSize) 935 throws InterruptedException, IOException { 936 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL(), this.getID()); 937 return new LargeFileUpload().upload(this.getAPI(), inputStream, url, fileSize); 938 } 939 940 /** 941 * Creates a new version of a file using specified number of parallel http connections. 942 * @param inputStream the stream instance that contains the data. 943 * @param fileSize the size of the file that will be uploaded. 944 * @param nParallelConnections number of parallel http connections to use 945 * @param timeOut time to wait before killing the job 946 * @param unit time unit for the time wait value 947 * @return the created file instance. 948 * @throws InterruptedException when a thread execution is interrupted. 949 * @throws IOException when reading a stream throws exception. 950 */ 951 public BoxFile.Info uploadLargeFile(InputStream inputStream, long fileSize, 952 int nParallelConnections, long timeOut, TimeUnit unit) 953 throws InterruptedException, IOException { 954 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL(), this.getID()); 955 return new LargeFileUpload(nParallelConnections, timeOut, unit) 956 .upload(this.getAPI(), inputStream, url, fileSize); 957 } 958 959 /** 960 * Contains information about a BoxFile. 961 */ 962 public class Info extends BoxItem.Info { 963 private String sha1; 964 private String versionNumber; 965 private long commentCount; 966 private EnumSet<Permission> permissions; 967 private String extension; 968 private boolean isPackage; 969 private BoxFileVersion version; 970 private URL previewLink; 971 private BoxLock lock; 972 private boolean isWatermarked; 973 974 /** 975 * Constructs an empty Info object. 976 */ 977 public Info() { 978 super(); 979 } 980 981 /** 982 * Constructs an Info object by parsing information from a JSON string. 983 * 984 * @param json the JSON string to parse. 985 */ 986 public Info(String json) { 987 super(json); 988 } 989 990 /** 991 * Constructs an Info object using an already parsed JSON object. 992 * 993 * @param jsonObject the parsed JSON object. 994 */ 995 Info(JsonObject jsonObject) { 996 super(jsonObject); 997 } 998 999 @Override 1000 public BoxFile getResource() { 1001 return BoxFile.this; 1002 } 1003 1004 /** 1005 * Gets the SHA1 hash of the file. 1006 * 1007 * @return the SHA1 hash of the file. 1008 */ 1009 public String getSha1() { 1010 return this.sha1; 1011 } 1012 1013 /** 1014 * Gets the lock of the file. 1015 * 1016 * @return the lock of the file. 1017 */ 1018 public BoxLock getLock() { 1019 return this.lock; 1020 } 1021 1022 /** 1023 * Gets the current version number of the file. 1024 * 1025 * @return the current version number of the file. 1026 */ 1027 public String getVersionNumber() { 1028 return this.versionNumber; 1029 } 1030 1031 /** 1032 * Gets the number of comments on the file. 1033 * 1034 * @return the number of comments on the file. 1035 */ 1036 public long getCommentCount() { 1037 return this.commentCount; 1038 } 1039 1040 /** 1041 * Gets the permissions that the current user has on the file. 1042 * 1043 * @return the permissions that the current user has on the file. 1044 */ 1045 public EnumSet<Permission> getPermissions() { 1046 return this.permissions; 1047 } 1048 1049 /** 1050 * Gets the extension suffix of the file, excluding the dot. 1051 * 1052 * @return the extension of the file. 1053 */ 1054 public String getExtension() { 1055 return this.extension; 1056 } 1057 1058 /** 1059 * Gets whether or not the file is an OSX package. 1060 * 1061 * @return true if the file is an OSX package; otherwise false. 1062 */ 1063 public boolean getIsPackage() { 1064 return this.isPackage; 1065 } 1066 1067 /** 1068 * Gets the current version details of the file. 1069 * 1070 * @return the current version details of the file. 1071 */ 1072 public BoxFileVersion getVersion() { 1073 return this.version; 1074 } 1075 1076 /** 1077 * Gets the current expiring preview link. 1078 * 1079 * @return the expiring preview link 1080 */ 1081 public URL getPreviewLink() { 1082 return this.previewLink; 1083 } 1084 1085 /** 1086 * Gets flag indicating whether this file is Watermarked. 1087 * 1088 * @return whether the file is watermarked or not 1089 */ 1090 public boolean getIsWatermarked() { 1091 return this.isWatermarked; 1092 } 1093 1094 @Override 1095 protected void parseJSONMember(JsonObject.Member member) { 1096 super.parseJSONMember(member); 1097 1098 String memberName = member.getName(); 1099 JsonValue value = member.getValue(); 1100 if (memberName.equals("sha1")) { 1101 this.sha1 = value.asString(); 1102 } else if (memberName.equals("version_number")) { 1103 this.versionNumber = value.asString(); 1104 } else if (memberName.equals("comment_count")) { 1105 this.commentCount = value.asLong(); 1106 } else if (memberName.equals("permissions")) { 1107 this.permissions = this.parsePermissions(value.asObject()); 1108 } else if (memberName.equals("extension")) { 1109 this.extension = value.asString(); 1110 } else if (memberName.equals("is_package")) { 1111 this.isPackage = value.asBoolean(); 1112 } else if (memberName.equals("file_version")) { 1113 this.version = this.parseFileVersion(value.asObject()); 1114 } else if (memberName.equals("expiring_embed_link")) { 1115 try { 1116 String urlString = member.getValue().asObject().get("url").asString(); 1117 this.previewLink = new URL(urlString); 1118 } catch (MalformedURLException e) { 1119 throw new BoxAPIException("Couldn't parse expiring_embed_link/url for file", e); 1120 } 1121 } else if (memberName.equals("lock")) { 1122 if (value.isNull()) { 1123 this.lock = null; 1124 } else { 1125 this.lock = new BoxLock(value.asObject(), BoxFile.this.getAPI()); 1126 } 1127 } else if (memberName.equals("watermark_info")) { 1128 JsonObject jsonObject = value.asObject(); 1129 this.isWatermarked = jsonObject.get("is_watermarked").asBoolean(); 1130 } 1131 } 1132 1133 private EnumSet<Permission> parsePermissions(JsonObject jsonObject) { 1134 EnumSet<Permission> permissions = EnumSet.noneOf(Permission.class); 1135 for (JsonObject.Member member : jsonObject) { 1136 JsonValue value = member.getValue(); 1137 if (value.isNull() || !value.asBoolean()) { 1138 continue; 1139 } 1140 1141 String memberName = member.getName(); 1142 if (memberName.equals("can_download")) { 1143 permissions.add(Permission.CAN_DOWNLOAD); 1144 } else if (memberName.equals("can_upload")) { 1145 permissions.add(Permission.CAN_UPLOAD); 1146 } else if (memberName.equals("can_rename")) { 1147 permissions.add(Permission.CAN_RENAME); 1148 } else if (memberName.equals("can_delete")) { 1149 permissions.add(Permission.CAN_DELETE); 1150 } else if (memberName.equals("can_share")) { 1151 permissions.add(Permission.CAN_SHARE); 1152 } else if (memberName.equals("can_set_share_access")) { 1153 permissions.add(Permission.CAN_SET_SHARE_ACCESS); 1154 } else if (memberName.equals("can_preview")) { 1155 permissions.add(Permission.CAN_PREVIEW); 1156 } else if (memberName.equals("can_comment")) { 1157 permissions.add(Permission.CAN_COMMENT); 1158 } 1159 } 1160 1161 return permissions; 1162 } 1163 1164 private BoxFileVersion parseFileVersion(JsonObject jsonObject) { 1165 return new BoxFileVersion(BoxFile.this.getAPI(), jsonObject, BoxFile.this.getID()); 1166 } 1167 } 1168 1169 /** 1170 * Enumerates the possible permissions that a user can have on a file. 1171 */ 1172 public enum Permission { 1173 /** 1174 * The user can download the file. 1175 */ 1176 CAN_DOWNLOAD("can_download"), 1177 1178 /** 1179 * The user can upload new versions of the file. 1180 */ 1181 CAN_UPLOAD("can_upload"), 1182 1183 /** 1184 * The user can rename the file. 1185 */ 1186 CAN_RENAME("can_rename"), 1187 1188 /** 1189 * The user can delete the file. 1190 */ 1191 CAN_DELETE("can_delete"), 1192 1193 /** 1194 * The user can share the file. 1195 */ 1196 CAN_SHARE("can_share"), 1197 1198 /** 1199 * The user can set the access level for shared links to the file. 1200 */ 1201 CAN_SET_SHARE_ACCESS("can_set_share_access"), 1202 1203 /** 1204 * The user can preview the file. 1205 */ 1206 CAN_PREVIEW("can_preview"), 1207 1208 /** 1209 * The user can comment on the file. 1210 */ 1211 CAN_COMMENT("can_comment"); 1212 1213 private final String jsonValue; 1214 1215 private Permission(String jsonValue) { 1216 this.jsonValue = jsonValue; 1217 } 1218 1219 static Permission fromJSONValue(String jsonValue) { 1220 return Permission.valueOf(jsonValue.toUpperCase()); 1221 } 1222 1223 String toJSONValue() { 1224 return this.jsonValue; 1225 } 1226 } 1227 1228 private BoxCollaboration.Info collaborate(JsonObject accessibleByField, BoxCollaboration.Role role, 1229 Boolean notify, Boolean canViewPath) { 1230 BoxAPIConnection api = this.getAPI(); 1231 URL url = ADD_COLLABORATION_URL.build(api.getBaseURL()); 1232 1233 JsonObject itemField = new JsonObject(); 1234 itemField.add("id", this.getID()); 1235 itemField.add("type", "file"); 1236 1237 JsonObject requestJSON = new JsonObject(); 1238 requestJSON.add("item", itemField); 1239 requestJSON.add("accessible_by", accessibleByField); 1240 requestJSON.add("role", role.toJSONString()); 1241 if (canViewPath != null) { 1242 requestJSON.add("can_view_path", canViewPath.booleanValue()); 1243 } 1244 1245 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 1246 if (notify != null) { 1247 request.addHeader("notify", notify.toString()); 1248 } 1249 1250 request.setBody(requestJSON.toString()); 1251 BoxJSONResponse response = (BoxJSONResponse) request.send(); 1252 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 1253 1254 BoxCollaboration newCollaboration = new BoxCollaboration(api, responseJSON.get("id").asString()); 1255 BoxCollaboration.Info info = newCollaboration.new Info(responseJSON); 1256 return info; 1257 } 1258 1259 /** 1260 * Adds a collaborator to this file. 1261 * 1262 * @param collaborator the collaborator to add. 1263 * @param role the role of the collaborator. 1264 * @param notify determines if the user (or all the users in the group) will receive email notifications. 1265 * @param canViewPath whether view path collaboration feature is enabled or not. 1266 * @return info about the new collaboration. 1267 */ 1268 public BoxCollaboration.Info collaborate(BoxCollaborator collaborator, BoxCollaboration.Role role, 1269 Boolean notify, Boolean canViewPath) { 1270 JsonObject accessibleByField = new JsonObject(); 1271 accessibleByField.add("id", collaborator.getID()); 1272 1273 if (collaborator instanceof BoxUser) { 1274 accessibleByField.add("type", "user"); 1275 } else if (collaborator instanceof BoxGroup) { 1276 accessibleByField.add("type", "group"); 1277 } else { 1278 throw new IllegalArgumentException("The given collaborator is of an unknown type."); 1279 } 1280 return this.collaborate(accessibleByField, role, notify, canViewPath); 1281 } 1282 1283 1284 /** 1285 * Adds a collaborator to this folder. An email will be sent to the collaborator if they don't already have a Box 1286 * account. 1287 * 1288 * @param email the email address of the collaborator to add. 1289 * @param role the role of the collaborator. 1290 * @param notify determines if the user (or all the users in the group) will receive email notifications. 1291 * @param canViewPath whether view path collaboration feature is enabled or not. 1292 * @return info about the new collaboration. 1293 */ 1294 public BoxCollaboration.Info collaborate(String email, BoxCollaboration.Role role, 1295 Boolean notify, Boolean canViewPath) { 1296 JsonObject accessibleByField = new JsonObject(); 1297 accessibleByField.add("login", email); 1298 accessibleByField.add("type", "user"); 1299 1300 return this.collaborate(accessibleByField, role, notify, canViewPath); 1301 } 1302 1303 /** 1304 * Used to retrieve all collaborations associated with the item. 1305 * 1306 * @param fields the optional fields to retrieve. 1307 * @return An iterable of metadata instances associated with the item. 1308 */ 1309 public BoxResourceIterable<BoxCollaboration.Info> getAllFileCollaborations(String... fields) { 1310 return BoxCollaboration.getAllFileCollaborations(this.getAPI(), this.getID(), 1311 GET_COLLABORATORS_PAGE_SIZE, fields); 1312 1313 } 1314}