001package com.box.sdk; 002 003import java.io.IOException; 004import java.io.InputStream; 005import java.net.URL; 006import java.util.ArrayList; 007import java.util.Collection; 008import java.util.Date; 009import java.util.EnumSet; 010import java.util.Iterator; 011import java.util.List; 012import java.util.Map; 013import java.util.concurrent.TimeUnit; 014 015import com.box.sdk.internal.utils.Parsers; 016import com.eclipsesource.json.JsonArray; 017import com.eclipsesource.json.JsonObject; 018import com.eclipsesource.json.JsonValue; 019/** 020 * Represents a folder on Box. This class can be used to iterate through a folder's contents, collaborate a folder with 021 * another user or group, and perform other common folder operations (move, copy, delete, etc.). 022 * <p> 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 */ 027@BoxResourceType("folder") 028public class BoxFolder extends BoxItem implements Iterable<BoxItem.Info> { 029 /** 030 * An array of all possible folder fields that can be requested when calling {@link #getInfo()}. 031 */ 032 public static final String[] ALL_FIELDS = {"type", "id", "sequence_id", "etag", "name", "created_at", "modified_at", 033 "description", "size", "path_collection", "created_by", "modified_by", "trashed_at", "purged_at", 034 "content_created_at", "content_modified_at", "owned_by", "shared_link", "folder_upload_email", "parent", 035 "item_status", "item_collection", "sync_state", "has_collaborations", "permissions", "tags", 036 "can_non_owners_invite", "collections", "watermark_info", "metadata", "is_externally_owned", 037 "is_collaboration_restricted_to_enterprise", "allowed_shared_link_access_levels", "allowed_invitee_roles"}; 038 039 /** 040 * Used to specify what direction to sort and display results. 041 */ 042 public enum SortDirection { 043 /** 044 * ASC for ascending order. 045 */ 046 ASC, 047 048 /** 049 * DESC for descending order. 050 */ 051 DESC 052 } 053 054 /** 055 * Create Folder URL Template. 056 */ 057 public static final URLTemplate CREATE_FOLDER_URL = new URLTemplate("folders"); 058 /** 059 * Create Web Link URL Template. 060 */ 061 public static final URLTemplate CREATE_WEB_LINK_URL = new URLTemplate("web_links"); 062 /** 063 * Copy Folder URL Template. 064 */ 065 public static final URLTemplate COPY_FOLDER_URL = new URLTemplate("folders/%s/copy"); 066 /** 067 * Delete Folder URL Template. 068 */ 069 public static final URLTemplate DELETE_FOLDER_URL = new URLTemplate("folders/%s?recursive=%b"); 070 /** 071 * Folder Info URL Template. 072 */ 073 public static final URLTemplate FOLDER_INFO_URL_TEMPLATE = new URLTemplate("folders/%s"); 074 /** 075 * Upload File URL Template. 076 */ 077 public static final URLTemplate UPLOAD_FILE_URL = new URLTemplate("files/content"); 078 /** 079 * Add Collaboration URL Template. 080 */ 081 public static final URLTemplate ADD_COLLABORATION_URL = new URLTemplate("collaborations"); 082 /** 083 * Get Collaborations URL Template. 084 */ 085 public static final URLTemplate GET_COLLABORATIONS_URL = new URLTemplate("folders/%s/collaborations"); 086 /** 087 * Get Items URL Template. 088 */ 089 public static final URLTemplate GET_ITEMS_URL = new URLTemplate("folders/%s/items/"); 090 /** 091 * Search URL Template. 092 */ 093 public static final URLTemplate SEARCH_URL_TEMPLATE = new URLTemplate("search"); 094 /** 095 * Metadata URL Template. 096 */ 097 public static final URLTemplate METADATA_URL_TEMPLATE = new URLTemplate("folders/%s/metadata/%s/%s"); 098 /** 099 * Upload Session URL Template. 100 */ 101 public static final URLTemplate UPLOAD_SESSION_URL_TEMPLATE = new URLTemplate("files/upload_sessions"); 102 103 /** 104 * Constructs a BoxFolder for a folder with a given ID. 105 * 106 * @param api the API connection to be used by the folder. 107 * @param id the ID of the folder. 108 */ 109 public BoxFolder(BoxAPIConnection api, String id) { 110 super(api, id); 111 } 112 113 /** 114 * {@inheritDoc} 115 */ 116 @Override 117 protected URL getItemURL() { 118 return FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 119 } 120 121 /** 122 * Gets the current user's root folder. 123 * 124 * @param api the API connection to be used by the folder. 125 * @return the user's root folder. 126 */ 127 public static BoxFolder getRootFolder(BoxAPIConnection api) { 128 return new BoxFolder(api, "0"); 129 } 130 131 /** 132 * Adds a collaborator to this folder. 133 * 134 * @param collaborator the collaborator to add. 135 * @param role the role of the collaborator. 136 * @return info about the new collaboration. 137 */ 138 public BoxCollaboration.Info collaborate(BoxCollaborator collaborator, BoxCollaboration.Role role) { 139 JsonObject accessibleByField = new JsonObject(); 140 accessibleByField.add("id", collaborator.getID()); 141 142 if (collaborator instanceof BoxUser) { 143 accessibleByField.add("type", "user"); 144 } else if (collaborator instanceof BoxGroup) { 145 accessibleByField.add("type", "group"); 146 } else { 147 throw new IllegalArgumentException("The given collaborator is of an unknown type."); 148 } 149 150 return this.collaborate(accessibleByField, role, null, null); 151 } 152 153 /** 154 * Adds a collaborator to this folder. An email will be sent to the collaborator if they don't already have a Box 155 * account. 156 * 157 * @param email the email address of the collaborator to add. 158 * @param role the role of the collaborator. 159 * @return info about the new collaboration. 160 */ 161 public BoxCollaboration.Info collaborate(String email, BoxCollaboration.Role role) { 162 JsonObject accessibleByField = new JsonObject(); 163 accessibleByField.add("login", email); 164 accessibleByField.add("type", "user"); 165 166 return this.collaborate(accessibleByField, role, null, null); 167 } 168 169 /** 170 * Adds a collaborator to this folder. 171 * 172 * @param collaborator the collaborator to add. 173 * @param role the role of the collaborator. 174 * @param notify the user/group should receive email notification of the collaboration or not. 175 * @param canViewPath the view path collaboration feature is enabled or not. 176 * View path collaborations allow the invitee to see the entire ancestral path to the associated 177 * folder. The user will not gain privileges in any ancestral folder. 178 * @return info about the new collaboration. 179 */ 180 public BoxCollaboration.Info collaborate(BoxCollaborator collaborator, BoxCollaboration.Role role, 181 Boolean notify, Boolean canViewPath) { 182 JsonObject accessibleByField = new JsonObject(); 183 accessibleByField.add("id", collaborator.getID()); 184 185 if (collaborator instanceof BoxUser) { 186 accessibleByField.add("type", "user"); 187 } else if (collaborator instanceof BoxGroup) { 188 accessibleByField.add("type", "group"); 189 } else { 190 throw new IllegalArgumentException("The given collaborator is of an unknown type."); 191 } 192 193 return this.collaborate(accessibleByField, role, notify, canViewPath); 194 } 195 196 /** 197 * Adds a collaborator to this folder. An email will be sent to the collaborator if they don't already have a Box 198 * account. 199 * 200 * @param email the email address of the collaborator to add. 201 * @param role the role of the collaborator. 202 * @param notify the user/group should receive email notification of the collaboration or not. 203 * @param canViewPath the view path collaboration feature is enabled or not. 204 * View path collaborations allow the invitee to see the entire ancestral path to the associated 205 * folder. The user will not gain privileges in any ancestral folder. 206 * @return info about the new collaboration. 207 */ 208 public BoxCollaboration.Info collaborate(String email, BoxCollaboration.Role role, 209 Boolean notify, Boolean canViewPath) { 210 JsonObject accessibleByField = new JsonObject(); 211 accessibleByField.add("login", email); 212 accessibleByField.add("type", "user"); 213 214 return this.collaborate(accessibleByField, role, notify, canViewPath); 215 } 216 217 private BoxCollaboration.Info collaborate(JsonObject accessibleByField, BoxCollaboration.Role role, 218 Boolean notify, Boolean canViewPath) { 219 220 JsonObject itemField = new JsonObject(); 221 itemField.add("id", this.getID()); 222 itemField.add("type", "folder"); 223 224 return BoxCollaboration.create(this.getAPI(), accessibleByField, itemField, role, notify, canViewPath); 225 } 226 227 @Override 228 public BoxSharedLink createSharedLink(BoxSharedLink.Access access, Date unshareDate, 229 BoxSharedLink.Permissions permissions) { 230 231 BoxSharedLink sharedLink = new BoxSharedLink(access, unshareDate, permissions); 232 Info info = new Info(); 233 info.setSharedLink(sharedLink); 234 235 this.updateInfo(info); 236 return info.getSharedLink(); 237 } 238 239 /** 240 * Creates new SharedLink for a BoxFolder with a password. 241 * 242 * @param access The access level of the shared link. 243 * @param unshareDate A specified date to unshare the Box folder. 244 * @param permissions The permissions to set on the shared link for the Box folder. 245 * @param password Password set on the shared link to give access to the Box folder. 246 * @return information about the newly created shared link. 247 */ 248 public BoxSharedLink createSharedLink(BoxSharedLink.Access access, Date unshareDate, 249 BoxSharedLink.Permissions permissions, String password) { 250 251 BoxSharedLink sharedLink = new BoxSharedLink(access, unshareDate, permissions, password); 252 Info info = new Info(); 253 info.setSharedLink(sharedLink); 254 255 this.updateInfo(info); 256 return info.getSharedLink(); 257 } 258 259 /** 260 * Gets information about all of the collaborations for this folder. 261 * 262 * @return a collection of information about the collaborations for this folder. 263 */ 264 public Collection<BoxCollaboration.Info> getCollaborations() { 265 BoxAPIConnection api = this.getAPI(); 266 URL url = GET_COLLABORATIONS_URL.build(api.getBaseURL(), this.getID()); 267 268 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 269 BoxJSONResponse response = (BoxJSONResponse) request.send(); 270 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 271 272 int entriesCount = responseJSON.get("total_count").asInt(); 273 Collection<BoxCollaboration.Info> collaborations = new ArrayList<BoxCollaboration.Info>(entriesCount); 274 JsonArray entries = responseJSON.get("entries").asArray(); 275 for (JsonValue entry : entries) { 276 JsonObject entryObject = entry.asObject(); 277 BoxCollaboration collaboration = new BoxCollaboration(api, entryObject.get("id").asString()); 278 BoxCollaboration.Info info = collaboration.new Info(entryObject); 279 collaborations.add(info); 280 } 281 282 return collaborations; 283 } 284 285 @Override 286 public BoxFolder.Info getInfo() { 287 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 288 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 289 BoxJSONResponse response = (BoxJSONResponse) request.send(); 290 return new Info(response.getJSON()); 291 } 292 293 @Override 294 public BoxFolder.Info getInfo(String... fields) { 295 String queryString = new QueryStringBuilder().appendParam("fields", fields).toString(); 296 URL url = FOLDER_INFO_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 297 298 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 299 BoxJSONResponse response = (BoxJSONResponse) request.send(); 300 return new Info(response.getJSON()); 301 } 302 303 /** 304 * Updates the information about this folder with any info fields that have been modified locally. 305 * 306 * @param info the updated info. 307 */ 308 public void updateInfo(BoxFolder.Info info) { 309 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 310 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 311 request.setBody(info.getPendingChanges()); 312 BoxJSONResponse response = (BoxJSONResponse) request.send(); 313 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 314 info.update(jsonObject); 315 } 316 317 @Override 318 public BoxFolder.Info copy(BoxFolder destination) { 319 return this.copy(destination, null); 320 } 321 322 @Override 323 public BoxFolder.Info copy(BoxFolder destination, String newName) { 324 URL url = COPY_FOLDER_URL.build(this.getAPI().getBaseURL(), this.getID()); 325 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 326 327 JsonObject parent = new JsonObject(); 328 parent.add("id", destination.getID()); 329 330 JsonObject copyInfo = new JsonObject(); 331 copyInfo.add("parent", parent); 332 if (newName != null) { 333 copyInfo.add("name", newName); 334 } 335 336 request.setBody(copyInfo.toString()); 337 BoxJSONResponse response = (BoxJSONResponse) request.send(); 338 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 339 BoxFolder copiedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString()); 340 return copiedFolder.new Info(responseJSON); 341 } 342 343 /** 344 * Creates a new child folder inside this folder. 345 * 346 * @param name the new folder's name. 347 * @return the created folder's info. 348 */ 349 public BoxFolder.Info createFolder(String name) { 350 JsonObject parent = new JsonObject(); 351 parent.add("id", this.getID()); 352 353 JsonObject newFolder = new JsonObject(); 354 newFolder.add("name", name); 355 newFolder.add("parent", parent); 356 357 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), CREATE_FOLDER_URL.build(this.getAPI().getBaseURL()), 358 "POST"); 359 request.setBody(newFolder.toString()); 360 BoxJSONResponse response = (BoxJSONResponse) request.send(); 361 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 362 363 BoxFolder createdFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString()); 364 return createdFolder.new Info(responseJSON); 365 } 366 367 /** 368 * Deletes this folder, optionally recursively deleting all of its contents. 369 * 370 * @param recursive true to recursively delete this folder's contents; otherwise false. 371 */ 372 public void delete(boolean recursive) { 373 URL url = DELETE_FOLDER_URL.buildAlpha(this.getAPI().getBaseURL(), this.getID(), recursive); 374 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 375 BoxAPIResponse response = request.send(); 376 response.disconnect(); 377 } 378 379 @Override 380 public BoxItem.Info move(BoxFolder destination) { 381 return this.move(destination, null); 382 } 383 384 @Override 385 public BoxItem.Info move(BoxFolder destination, String newName) { 386 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 387 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 388 389 JsonObject parent = new JsonObject(); 390 parent.add("id", destination.getID()); 391 392 JsonObject updateInfo = new JsonObject(); 393 updateInfo.add("parent", parent); 394 if (newName != null) { 395 updateInfo.add("name", newName); 396 } 397 398 request.setBody(updateInfo.toString()); 399 BoxJSONResponse response = (BoxJSONResponse) request.send(); 400 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 401 BoxFolder movedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString()); 402 return movedFolder.new Info(responseJSON); 403 } 404 405 /** 406 * Renames this folder. 407 * 408 * @param newName the new name of the folder. 409 */ 410 public void rename(String newName) { 411 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 412 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 413 414 JsonObject updateInfo = new JsonObject(); 415 updateInfo.add("name", newName); 416 417 request.setBody(updateInfo.toString()); 418 BoxJSONResponse response = (BoxJSONResponse) request.send(); 419 response.getJSON(); 420 } 421 422 /** 423 * Checks if the file can be successfully uploaded by using the preflight check. 424 * 425 * @param name the name to give the uploaded file. 426 * @param fileSize the size of the file used for account capacity calculations. 427 */ 428 public void canUpload(String name, long fileSize) { 429 URL url = UPLOAD_FILE_URL.build(this.getAPI().getBaseURL()); 430 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "OPTIONS"); 431 432 JsonObject parent = new JsonObject(); 433 parent.add("id", this.getID()); 434 435 JsonObject preflightInfo = new JsonObject(); 436 preflightInfo.add("parent", parent); 437 preflightInfo.add("name", name); 438 439 preflightInfo.add("size", fileSize); 440 441 request.setBody(preflightInfo.toString()); 442 BoxAPIResponse response = request.send(); 443 response.disconnect(); 444 } 445 446 /** 447 * Uploads a new file to this folder. 448 * 449 * @param fileContent a stream containing the contents of the file to upload. 450 * @param name the name to give the uploaded file. 451 * @return the uploaded file's info. 452 */ 453 public BoxFile.Info uploadFile(InputStream fileContent, String name) { 454 FileUploadParams uploadInfo = new FileUploadParams() 455 .setContent(fileContent) 456 .setName(name); 457 return this.uploadFile(uploadInfo); 458 } 459 460 /** 461 * Uploads a new file to this folder. 462 * 463 * @param callback the callback which allows file content to be written on output stream. 464 * @param name the name to give the uploaded file. 465 * @return the uploaded file's info. 466 */ 467 public BoxFile.Info uploadFile(UploadFileCallback callback, String name) { 468 FileUploadParams uploadInfo = new FileUploadParams() 469 .setUploadFileCallback(callback) 470 .setName(name); 471 return this.uploadFile(uploadInfo); 472 } 473 474 /** 475 * Uploads a new file to this folder while reporting the progress to a ProgressListener. 476 * 477 * @param fileContent a stream containing the contents of the file to upload. 478 * @param name the name to give the uploaded file. 479 * @param fileSize the size of the file used for determining the progress of the upload. 480 * @param listener a listener for monitoring the upload's progress. 481 * @return the uploaded file's info. 482 */ 483 public BoxFile.Info uploadFile(InputStream fileContent, String name, long fileSize, ProgressListener listener) { 484 FileUploadParams uploadInfo = new FileUploadParams() 485 .setContent(fileContent) 486 .setName(name) 487 .setSize(fileSize) 488 .setProgressListener(listener); 489 return this.uploadFile(uploadInfo); 490 } 491 492 /** 493 * Uploads a new file to this folder with a specified file description. 494 * 495 * @param fileContent a stream containing the contents of the file to upload. 496 * @param name the name to give the uploaded file. 497 * @param description the description to give the uploaded file. 498 * @return the uploaded file's info. 499 */ 500 public BoxFile.Info uploadFile(InputStream fileContent, String name, String description) { 501 FileUploadParams uploadInfo = new FileUploadParams() 502 .setContent(fileContent) 503 .setName(name) 504 .setDescription(description); 505 return this.uploadFile(uploadInfo); 506 } 507 508 /** 509 * Uploads a new file to this folder with custom upload parameters. 510 * 511 * @param uploadParams the custom upload parameters. 512 * @return the uploaded file's info. 513 */ 514 public BoxFile.Info uploadFile(FileUploadParams uploadParams) { 515 URL uploadURL = UPLOAD_FILE_URL.build(this.getAPI().getBaseUploadURL()); 516 BoxMultipartRequest request = new BoxMultipartRequest(getAPI(), uploadURL); 517 518 JsonObject fieldJSON = new JsonObject(); 519 JsonObject parentIdJSON = new JsonObject(); 520 parentIdJSON.add("id", getID()); 521 fieldJSON.add("name", uploadParams.getName()); 522 fieldJSON.add("parent", parentIdJSON); 523 524 if (uploadParams.getCreated() != null) { 525 fieldJSON.add("content_created_at", BoxDateFormat.format(uploadParams.getCreated())); 526 } 527 528 if (uploadParams.getModified() != null) { 529 fieldJSON.add("content_modified_at", BoxDateFormat.format(uploadParams.getModified())); 530 } 531 532 if (uploadParams.getSHA1() != null && !uploadParams.getSHA1().isEmpty()) { 533 request.setContentSHA1(uploadParams.getSHA1()); 534 } 535 536 if (uploadParams.getDescription() != null) { 537 fieldJSON.add("description", uploadParams.getDescription()); 538 } 539 540 request.putField("attributes", fieldJSON.toString()); 541 542 if (uploadParams.getSize() > 0) { 543 request.setFile(uploadParams.getContent(), uploadParams.getName(), uploadParams.getSize()); 544 } else if (uploadParams.getContent() != null) { 545 request.setFile(uploadParams.getContent(), uploadParams.getName()); 546 } else { 547 request.setUploadFileCallback(uploadParams.getUploadFileCallback(), uploadParams.getName()); 548 } 549 550 BoxJSONResponse response; 551 if (uploadParams.getProgressListener() == null) { 552 response = (BoxJSONResponse) request.send(); 553 } else { 554 response = (BoxJSONResponse) request.send(uploadParams.getProgressListener()); 555 } 556 JsonObject collection = JsonObject.readFrom(response.getJSON()); 557 JsonArray entries = collection.get("entries").asArray(); 558 JsonObject fileInfoJSON = entries.get(0).asObject(); 559 String uploadedFileID = fileInfoJSON.get("id").asString(); 560 561 BoxFile uploadedFile = new BoxFile(getAPI(), uploadedFileID); 562 return uploadedFile.new Info(fileInfoJSON); 563 } 564 565 /** 566 * Uploads a new weblink to this folder. 567 * 568 * @param linkURL the URL the weblink points to. 569 * @return the uploaded weblink's info. 570 */ 571 public BoxWebLink.Info createWebLink(URL linkURL) { 572 return this.createWebLink(null, linkURL, 573 null); 574 } 575 576 /** 577 * Uploads a new weblink to this folder. 578 * 579 * @param name the filename for the weblink. 580 * @param linkURL the URL the weblink points to. 581 * @return the uploaded weblink's info. 582 */ 583 public BoxWebLink.Info createWebLink(String name, URL linkURL) { 584 return this.createWebLink(name, linkURL, 585 null); 586 } 587 588 /** 589 * Uploads a new weblink to this folder. 590 * 591 * @param linkURL the URL the weblink points to. 592 * @param description the weblink's description. 593 * @return the uploaded weblink's info. 594 */ 595 public BoxWebLink.Info createWebLink(URL linkURL, String description) { 596 return this.createWebLink(null, linkURL, description); 597 } 598 599 /** 600 * Uploads a new weblink to this folder. 601 * 602 * @param name the filename for the weblink. 603 * @param linkURL the URL the weblink points to. 604 * @param description the weblink's description. 605 * @return the uploaded weblink's info. 606 */ 607 public BoxWebLink.Info createWebLink(String name, URL linkURL, String description) { 608 JsonObject parent = new JsonObject(); 609 parent.add("id", this.getID()); 610 611 JsonObject newWebLink = new JsonObject(); 612 newWebLink.add("name", name); 613 newWebLink.add("parent", parent); 614 newWebLink.add("url", linkURL.toString()); 615 616 if (description != null) { 617 newWebLink.add("description", description); 618 } 619 620 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), 621 CREATE_WEB_LINK_URL.build(this.getAPI().getBaseURL()), "POST"); 622 request.setBody(newWebLink.toString()); 623 BoxJSONResponse response = (BoxJSONResponse) request.send(); 624 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 625 626 BoxWebLink createdWebLink = new BoxWebLink(this.getAPI(), responseJSON.get("id").asString()); 627 return createdWebLink.new Info(responseJSON); 628 } 629 630 /** 631 * Returns an iterable containing the items in this folder. Iterating over the iterable returned by this method is 632 * equivalent to iterating over this BoxFolder directly. 633 * 634 * @return an iterable containing the items in this folder. 635 */ 636 public Iterable<BoxItem.Info> getChildren() { 637 return this; 638 } 639 640 /** 641 * Returns an iterable containing the items in this folder and specifies which child fields to retrieve from the 642 * API. 643 * 644 * @param fields the fields to retrieve. 645 * @return an iterable containing the items in this folder. 646 */ 647 public Iterable<BoxItem.Info> getChildren(final String... fields) { 648 return new Iterable<BoxItem.Info>() { 649 @Override 650 public Iterator<BoxItem.Info> iterator() { 651 String queryString = new QueryStringBuilder().appendParam("fields", fields).toString(); 652 URL url = GET_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), queryString, getID()); 653 return new BoxItemIterator(getAPI(), url); 654 } 655 }; 656 } 657 658 /** 659 * Returns an iterable containing the items in this folder sorted by name and direction. 660 * @param sort the field to sort by, can be set as `name`, `id`, and `date`. 661 * @param direction the direction to display the item results. 662 * @param fields the fields to retrieve. 663 * @return an iterable containing the items in this folder. 664 */ 665 public Iterable<BoxItem.Info> getChildren(String sort, SortDirection direction, final String... fields) { 666 QueryStringBuilder builder = new QueryStringBuilder() 667 .appendParam("sort", sort) 668 .appendParam("direction", direction.toString()); 669 670 if (fields.length > 0) { 671 builder.appendParam("fields", fields).toString(); 672 } 673 final String query = builder.toString(); 674 return new Iterable<BoxItem.Info>() { 675 @Override 676 public Iterator<BoxItem.Info> iterator() { 677 URL url = GET_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), query, getID()); 678 return new BoxItemIterator(getAPI(), url); 679 } 680 }; 681 } 682 683 /** 684 * Retrieves a specific range of child items in this folder. 685 * 686 * @param offset the index of the first child item to retrieve. 687 * @param limit the maximum number of children to retrieve after the offset. 688 * @param fields the fields to retrieve. 689 * @return a partial collection containing the specified range of child items. 690 */ 691 public PartialCollection<BoxItem.Info> getChildrenRange(long offset, long limit, String... fields) { 692 QueryStringBuilder builder = new QueryStringBuilder() 693 .appendParam("limit", limit) 694 .appendParam("offset", offset); 695 696 if (fields.length > 0) { 697 builder.appendParam("fields", fields).toString(); 698 } 699 700 URL url = GET_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), builder.toString(), getID()); 701 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 702 BoxJSONResponse response = (BoxJSONResponse) request.send(); 703 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 704 705 String totalCountString = responseJSON.get("total_count").toString(); 706 long fullSize = Double.valueOf(totalCountString).longValue(); 707 PartialCollection<BoxItem.Info> children = new PartialCollection<BoxItem.Info>(offset, limit, fullSize); 708 JsonArray jsonArray = responseJSON.get("entries").asArray(); 709 for (JsonValue value : jsonArray) { 710 JsonObject jsonObject = value.asObject(); 711 BoxItem.Info parsedItemInfo = (BoxItem.Info) BoxResource.parseInfo(this.getAPI(), jsonObject); 712 if (parsedItemInfo != null) { 713 children.add(parsedItemInfo); 714 } 715 } 716 return children; 717 } 718 719 /** 720 * Returns an iterator over the items in this folder. 721 * 722 * @return an iterator over the items in this folder. 723 */ 724 @Override 725 public Iterator<BoxItem.Info> iterator() { 726 URL url = GET_ITEMS_URL.build(this.getAPI().getBaseURL(), BoxFolder.this.getID()); 727 return new BoxItemIterator(BoxFolder.this.getAPI(), url); 728 } 729 730 /** 731 * Adds new {@link BoxWebHook} to this {@link BoxFolder}. 732 * 733 * @param address {@link BoxWebHook.Info#getAddress()} 734 * @param triggers {@link BoxWebHook.Info#getTriggers()} 735 * @return created {@link BoxWebHook.Info} 736 */ 737 public BoxWebHook.Info addWebHook(URL address, BoxWebHook.Trigger... triggers) { 738 return BoxWebHook.create(this, address, triggers); 739 } 740 741 /** 742 * Used to retrieve the watermark for the folder. 743 * If the folder does not have a watermark applied to it, a 404 Not Found will be returned by API. 744 * 745 * @param fields the fields to retrieve. 746 * @return the watermark associated with the folder. 747 */ 748 public BoxWatermark getWatermark(String... fields) { 749 return this.getWatermark(FOLDER_INFO_URL_TEMPLATE, fields); 750 } 751 752 /** 753 * Used to apply or update the watermark for the folder. 754 * 755 * @return the watermark associated with the folder. 756 */ 757 public BoxWatermark applyWatermark() { 758 return this.applyWatermark(FOLDER_INFO_URL_TEMPLATE, BoxWatermark.WATERMARK_DEFAULT_IMPRINT); 759 } 760 761 /** 762 * Removes a watermark from the folder. 763 * If the folder did not have a watermark applied to it, a 404 Not Found will be returned by API. 764 */ 765 public void removeWatermark() { 766 this.removeWatermark(FOLDER_INFO_URL_TEMPLATE); 767 } 768 769 /** 770 * Used to retrieve all metadata associated with the folder. 771 * 772 * @param fields the optional fields to retrieve. 773 * @return An iterable of metadata instances associated with the folder 774 */ 775 public Iterable<Metadata> getAllMetadata(String... fields) { 776 return Metadata.getAllMetadata(this, fields); 777 } 778 779 /** 780 * This method is deprecated, please use the {@link BoxSearch} class instead. 781 * Searches this folder and all descendant folders using a given queryPlease use BoxSearch Instead. 782 * 783 * @param query the search query. 784 * @return an Iterable containing the search results. 785 */ 786 @Deprecated 787 public Iterable<BoxItem.Info> search(final String query) { 788 return new Iterable<BoxItem.Info>() { 789 @Override 790 public Iterator<BoxItem.Info> iterator() { 791 QueryStringBuilder builder = new QueryStringBuilder(); 792 builder.appendParam("query", query); 793 builder.appendParam("ancestor_folder_ids", getID()); 794 795 URL url = SEARCH_URL_TEMPLATE.buildWithQuery(getAPI().getBaseURL(), builder.toString()); 796 return new BoxItemIterator(getAPI(), url); 797 } 798 }; 799 } 800 801 @Override 802 public BoxFolder.Info setCollections(BoxCollection... collections) { 803 JsonArray jsonArray = new JsonArray(); 804 for (BoxCollection collection : collections) { 805 JsonObject collectionJSON = new JsonObject(); 806 collectionJSON.add("id", collection.getID()); 807 jsonArray.add(collectionJSON); 808 } 809 JsonObject infoJSON = new JsonObject(); 810 infoJSON.add("collections", jsonArray); 811 812 String queryString = new QueryStringBuilder().appendParam("fields", ALL_FIELDS).toString(); 813 URL url = FOLDER_INFO_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 814 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 815 request.setBody(infoJSON.toString()); 816 BoxJSONResponse response = (BoxJSONResponse) request.send(); 817 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 818 return new Info(jsonObject); 819 } 820 821 /** 822 * Creates global property metadata on this folder. 823 * 824 * @param metadata the new metadata values. 825 * @return the metadata returned from the server. 826 */ 827 public Metadata createMetadata(Metadata metadata) { 828 return this.createMetadata(Metadata.DEFAULT_METADATA_TYPE, metadata); 829 } 830 831 /** 832 * Creates metadata on this folder using a specified template. 833 * 834 * @param templateName the name of the metadata template. 835 * @param metadata the new metadata values. 836 * @return the metadata returned from the server. 837 */ 838 public Metadata createMetadata(String templateName, Metadata metadata) { 839 String scope = Metadata.scopeBasedOnType(templateName); 840 return this.createMetadata(templateName, scope, metadata); 841 } 842 843 /** 844 * Creates metadata on this folder using a specified scope and template. 845 * 846 * @param templateName the name of the metadata template. 847 * @param scope the scope of the template (usually "global" or "enterprise"). 848 * @param metadata the new metadata values. 849 * @return the metadata returned from the server. 850 */ 851 public Metadata createMetadata(String templateName, String scope, Metadata metadata) { 852 URL url = METADATA_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID(), scope, templateName); 853 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "POST"); 854 request.addHeader("Content-Type", "application/json"); 855 request.setBody(metadata.toString()); 856 BoxJSONResponse response = (BoxJSONResponse) request.send(); 857 return new Metadata(JsonObject.readFrom(response.getJSON())); 858 } 859 860 /** 861 * Sets the provided metadata on the folder, overwriting any existing metadata keys already present. 862 * 863 * @param templateName the name of the metadata template. 864 * @param scope the scope of the template (usually "global" or "enterprise"). 865 * @param metadata the new metadata values. 866 * @return the metadata returned from the server. 867 */ 868 public Metadata setMetadata(String templateName, String scope, Metadata metadata) { 869 Metadata metadataValue = null; 870 871 try { 872 metadataValue = this.createMetadata(templateName, scope, metadata); 873 } catch (BoxAPIException e) { 874 if (e.getResponseCode() == 409) { 875 Metadata metadataToUpdate = new Metadata(scope, templateName); 876 for (JsonValue value : metadata.getOperations()) { 877 if (value.asObject().get("value").isNumber()) { 878 metadataToUpdate.add(value.asObject().get("path").asString(), 879 value.asObject().get("value").asDouble()); 880 } else if (value.asObject().get("value").isString()) { 881 metadataToUpdate.add(value.asObject().get("path").asString(), 882 value.asObject().get("value").asString()); 883 } else if (value.asObject().get("value").isArray()) { 884 ArrayList<String> list = new ArrayList<String>(); 885 for (JsonValue jsonValue : value.asObject().get("value").asArray()) { 886 list.add(jsonValue.asString()); 887 } 888 metadataToUpdate.add(value.asObject().get("path").asString(), list); 889 } 890 } 891 metadataValue = this.updateMetadata(metadataToUpdate); 892 } else { 893 throw e; 894 } 895 } 896 897 return metadataValue; 898 } 899 900 /** 901 * Gets the global properties metadata on this folder. 902 * 903 * @return the metadata returned from the server. 904 */ 905 public Metadata getMetadata() { 906 return this.getMetadata(Metadata.DEFAULT_METADATA_TYPE); 907 } 908 909 /** 910 * Gets the metadata on this folder associated with a specified template. 911 * 912 * @param templateName the metadata template type name. 913 * @return the metadata returned from the server. 914 */ 915 public Metadata getMetadata(String templateName) { 916 String scope = Metadata.scopeBasedOnType(templateName); 917 return this.getMetadata(templateName, scope); 918 } 919 920 /** 921 * Gets the metadata on this folder associated with a specified scope and template. 922 * 923 * @param templateName the metadata template type name. 924 * @param scope the scope of the template (usually "global" or "enterprise"). 925 * @return the metadata returned from the server. 926 */ 927 public Metadata getMetadata(String templateName, String scope) { 928 URL url = METADATA_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID(), scope, templateName); 929 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 930 BoxJSONResponse response = (BoxJSONResponse) request.send(); 931 return new Metadata(JsonObject.readFrom(response.getJSON())); 932 } 933 934 /** 935 * Updates the global properties metadata on this folder. 936 * 937 * @param metadata the new metadata values. 938 * @return the metadata returned from the server. 939 */ 940 public Metadata updateMetadata(Metadata metadata) { 941 URL url = METADATA_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID(), metadata.getScope(), 942 metadata.getTemplateName()); 943 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "PUT"); 944 request.addHeader("Content-Type", "application/json-patch+json"); 945 request.setBody(metadata.getPatch()); 946 BoxJSONResponse response = (BoxJSONResponse) request.send(); 947 return new Metadata(JsonObject.readFrom(response.getJSON())); 948 } 949 950 /** 951 * Deletes the global properties metadata on this folder. 952 */ 953 public void deleteMetadata() { 954 this.deleteMetadata(Metadata.DEFAULT_METADATA_TYPE); 955 } 956 957 /** 958 * Deletes the metadata on this folder associated with a specified template. 959 * 960 * @param templateName the metadata template type name. 961 */ 962 public void deleteMetadata(String templateName) { 963 String scope = Metadata.scopeBasedOnType(templateName); 964 this.deleteMetadata(templateName, scope); 965 } 966 967 /** 968 * Deletes the metadata on this folder associated with a specified scope and template. 969 * 970 * @param templateName the metadata template type name. 971 * @param scope the scope of the template (usually "global" or "enterprise"). 972 */ 973 public void deleteMetadata(String templateName, String scope) { 974 URL url = METADATA_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID(), scope, templateName); 975 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 976 BoxAPIResponse response = request.send(); 977 response.disconnect(); 978 } 979 980 /** 981 * Adds a metadata classification to the specified file. 982 * 983 * @param classificationType the metadata classification type. 984 * @return the metadata classification type added to the file. 985 */ 986 public String addClassification(String classificationType) { 987 Metadata metadata = new Metadata().add(Metadata.CLASSIFICATION_KEY, classificationType); 988 Metadata classification = this.createMetadata(Metadata.CLASSIFICATION_TEMPLATE_KEY, 989 "enterprise", metadata); 990 991 return classification.getString(Metadata.CLASSIFICATION_KEY); 992 } 993 994 /** 995 * Updates a metadata classification on the specified file. 996 * 997 * @param classificationType the metadata classification type. 998 * @return the new metadata classification type updated on the file. 999 */ 1000 public String updateClassification(String classificationType) { 1001 Metadata metadata = new Metadata("enterprise", Metadata.CLASSIFICATION_TEMPLATE_KEY); 1002 metadata.replace(Metadata.CLASSIFICATION_KEY, classificationType); 1003 Metadata classification = this.updateMetadata(metadata); 1004 1005 return classification.getString(Metadata.CLASSIFICATION_KEY); 1006 } 1007 1008 /** 1009 * Attempts to add classification to a file. If classification already exists then do update. 1010 * 1011 * @param classificationType the metadata classification type. 1012 * @return the metadata classification type on the file. 1013 */ 1014 public String setClassification(String classificationType) { 1015 Metadata metadata = new Metadata().add(Metadata.CLASSIFICATION_KEY, classificationType); 1016 Metadata classification = null; 1017 1018 try { 1019 classification = this.createMetadata(Metadata.CLASSIFICATION_TEMPLATE_KEY, "enterprise", metadata); 1020 } catch (BoxAPIException e) { 1021 if (e.getResponseCode() == 409) { 1022 metadata = new Metadata("enterprise", Metadata.CLASSIFICATION_TEMPLATE_KEY); 1023 metadata.replace(Metadata.CLASSIFICATION_KEY, classificationType); 1024 classification = this.updateMetadata(metadata); 1025 } else { 1026 throw e; 1027 } 1028 } 1029 1030 return classification.getString("/Box__Security__Classification__Key"); 1031 } 1032 1033 /** 1034 * Gets the classification type for the specified file. 1035 * 1036 * @return the metadata classification type on the file. 1037 */ 1038 public String getClassification() { 1039 Metadata metadata = this.getMetadata(Metadata.CLASSIFICATION_TEMPLATE_KEY); 1040 return metadata.getString(Metadata.CLASSIFICATION_KEY); 1041 } 1042 1043 /** 1044 * Deletes the classification on the file. 1045 */ 1046 public void deleteClassification() { 1047 this.deleteMetadata(Metadata.CLASSIFICATION_TEMPLATE_KEY, "enterprise"); 1048 } 1049 1050 /** 1051 * Creates an upload session to create a new file in chunks. 1052 * This will first verify that the file can be created and then open a session for uploading pieces of the file. 1053 * 1054 * @param fileName the name of the file to be created 1055 * @param fileSize the size of the file that will be uploaded 1056 * @return the created upload session instance 1057 */ 1058 public BoxFileUploadSession.Info createUploadSession(String fileName, long fileSize) { 1059 1060 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1061 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 1062 1063 JsonObject body = new JsonObject(); 1064 body.add("folder_id", this.getID()); 1065 body.add("file_name", fileName); 1066 body.add("file_size", fileSize); 1067 request.setBody(body.toString()); 1068 1069 BoxJSONResponse response = (BoxJSONResponse) request.send(); 1070 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 1071 1072 String sessionId = jsonObject.get("id").asString(); 1073 BoxFileUploadSession session = new BoxFileUploadSession(this.getAPI(), sessionId); 1074 1075 return session.new Info(jsonObject); 1076 } 1077 1078 /** 1079 * Creates a new file. 1080 * 1081 * @param inputStream the stream instance that contains the data. 1082 * @param fileName the name of the file to be created. 1083 * @param fileSize the size of the file that will be uploaded. 1084 * @return the created file instance. 1085 * @throws InterruptedException when a thread execution is interrupted. 1086 * @throws IOException when reading a stream throws exception. 1087 */ 1088 public BoxFile.Info uploadLargeFile(InputStream inputStream, String fileName, long fileSize) 1089 throws InterruptedException, IOException { 1090 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1091 this.canUpload(fileName, fileSize); 1092 return new LargeFileUpload(). 1093 upload(this.getAPI(), this.getID(), inputStream, url, fileName, fileSize); 1094 } 1095 1096 /** 1097 * Creates a new file. Also sets file attributes. 1098 * 1099 * @param inputStream the stream instance that contains the data. 1100 * @param fileName the name of the file to be created. 1101 * @param fileSize the size of the file that will be uploaded. 1102 * @param fileAttributes file attributes to set 1103 * @return the created file instance. 1104 * @throws InterruptedException when a thread execution is interrupted. 1105 * @throws IOException when reading a stream throws exception. 1106 */ 1107 public BoxFile.Info uploadLargeFile(InputStream inputStream, String fileName, long fileSize, 1108 Map<String, String> fileAttributes) 1109 throws InterruptedException, IOException { 1110 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1111 this.canUpload(fileName, fileSize); 1112 return new LargeFileUpload(). 1113 upload(this.getAPI(), this.getID(), inputStream, url, fileName, fileSize, fileAttributes); 1114 } 1115 1116 /** 1117 * Creates a new file using specified number of parallel http connections. 1118 * 1119 * @param inputStream the stream instance that contains the data. 1120 * @param fileName the name of the file to be created. 1121 * @param fileSize the size of the file that will be uploaded. 1122 * @param nParallelConnections number of parallel http connections to use 1123 * @param timeOut time to wait before killing the job 1124 * @param unit time unit for the time wait value 1125 * @return the created file instance. 1126 * @throws InterruptedException when a thread execution is interrupted. 1127 * @throws IOException when reading a stream throws exception. 1128 */ 1129 public BoxFile.Info uploadLargeFile(InputStream inputStream, String fileName, long fileSize, 1130 int nParallelConnections, long timeOut, TimeUnit unit) 1131 throws InterruptedException, IOException { 1132 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1133 this.canUpload(fileName, fileSize); 1134 return new LargeFileUpload(nParallelConnections, timeOut, unit). 1135 upload(this.getAPI(), this.getID(), inputStream, url, fileName, fileSize); 1136 } 1137 1138 /** 1139 * Creates a new file using specified number of parallel http connections. Also sets file attributes. 1140 * 1141 * @param inputStream the stream instance that contains the data. 1142 * @param fileName the name of the file to be created. 1143 * @param fileSize the size of the file that will be uploaded. 1144 * @param nParallelConnections number of parallel http connections to use 1145 * @param timeOut time to wait before killing the job 1146 * @param unit time unit for the time wait value 1147 * @param fileAttributes file attributes to set 1148 * @return the created file instance. 1149 * @throws InterruptedException when a thread execution is interrupted. 1150 * @throws IOException when reading a stream throws exception. 1151 */ 1152 public BoxFile.Info uploadLargeFile(InputStream inputStream, String fileName, long fileSize, 1153 int nParallelConnections, long timeOut, TimeUnit unit, 1154 Map<String, String> fileAttributes) 1155 throws InterruptedException, IOException { 1156 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1157 this.canUpload(fileName, fileSize); 1158 return new LargeFileUpload(nParallelConnections, timeOut, unit). 1159 upload(this.getAPI(), this.getID(), inputStream, url, fileName, fileSize, fileAttributes); 1160 } 1161 1162 /** 1163 * Creates a new Metadata Cascade Policy on a folder. 1164 * 1165 * @param scope the scope of the metadata cascade policy. 1166 * @param templateKey the key of the template. 1167 * @return information about the Metadata Cascade Policy. 1168 */ 1169 public BoxMetadataCascadePolicy.Info addMetadataCascadePolicy(String scope, String templateKey) { 1170 1171 return BoxMetadataCascadePolicy.create(this.getAPI(), this.getID(), scope, templateKey); 1172 } 1173 1174 /** 1175 * Retrieves all Metadata Cascade Policies on a folder. 1176 * 1177 * @param fields optional fields to retrieve for cascade policies. 1178 * @return the Iterable of Box Metadata Cascade Policies in your enterprise. 1179 */ 1180 public Iterable<BoxMetadataCascadePolicy.Info> getMetadataCascadePolicies(String... fields) { 1181 Iterable<BoxMetadataCascadePolicy.Info> cascadePoliciesInfo = 1182 BoxMetadataCascadePolicy.getAll(this.getAPI(), this.getID(), fields); 1183 1184 return cascadePoliciesInfo; 1185 } 1186 1187 /** 1188 * Retrieves all Metadata Cascade Policies on a folder. 1189 * 1190 * @param enterpriseID the ID of the enterprise to retrieve cascade policies for. 1191 * @param limit the number of entries of cascade policies to retrieve. 1192 * @param fields optional fields to retrieve for cascade policies. 1193 * @return the Iterable of Box Metadata Cascade Policies in your enterprise. 1194 */ 1195 public Iterable<BoxMetadataCascadePolicy.Info> getMetadataCascadePolicies(String enterpriseID, 1196 int limit, String... fields) { 1197 Iterable<BoxMetadataCascadePolicy.Info> cascadePoliciesInfo = 1198 BoxMetadataCascadePolicy.getAll(this.getAPI(), this.getID(), enterpriseID, limit, fields); 1199 1200 return cascadePoliciesInfo; 1201 } 1202 1203 /** 1204 * Contains information about a BoxFolder. 1205 */ 1206 public class Info extends BoxItem.Info { 1207 private BoxUploadEmail uploadEmail; 1208 private boolean hasCollaborations; 1209 private SyncState syncState; 1210 private EnumSet<Permission> permissions; 1211 private boolean canNonOwnersInvite; 1212 private boolean isWatermarked; 1213 private boolean isCollaborationRestrictedToEnterprise; 1214 private boolean isExternallyOwned; 1215 private Map<String, Map<String, Metadata>> metadataMap; 1216 private List<String> allowedSharedLinkAccessLevels; 1217 private List<String> allowedInviteeRoles; 1218 private BoxClassification classification; 1219 1220 /** 1221 * Constructs an empty Info object. 1222 */ 1223 public Info() { 1224 super(); 1225 } 1226 1227 /** 1228 * Constructs an Info object by parsing information from a JSON string. 1229 * 1230 * @param json the JSON string to parse. 1231 */ 1232 public Info(String json) { 1233 super(json); 1234 } 1235 1236 /** 1237 * Constructs an Info object using an already parsed JSON object. 1238 * 1239 * @param jsonObject the parsed JSON object. 1240 */ 1241 public Info(JsonObject jsonObject) { 1242 super(jsonObject); 1243 } 1244 1245 /** 1246 * Gets the upload email for the folder. 1247 * 1248 * @return the upload email for the folder. 1249 */ 1250 public BoxUploadEmail getUploadEmail() { 1251 return this.uploadEmail; 1252 } 1253 1254 /** 1255 * Sets the upload email for the folder. 1256 * 1257 * @param uploadEmail the upload email for the folder. 1258 */ 1259 public void setUploadEmail(BoxUploadEmail uploadEmail) { 1260 if (this.uploadEmail == uploadEmail) { 1261 return; 1262 } 1263 1264 this.removeChildObject("folder_upload_email"); 1265 this.uploadEmail = uploadEmail; 1266 1267 if (uploadEmail == null) { 1268 this.addPendingChange("folder_upload_email", (String) null); 1269 } else { 1270 this.addChildObject("folder_upload_email", uploadEmail); 1271 } 1272 } 1273 1274 /** 1275 * Gets whether or not the folder has any collaborations. 1276 * 1277 * @return true if the folder has collaborations; otherwise false. 1278 */ 1279 public boolean getHasCollaborations() { 1280 return this.hasCollaborations; 1281 } 1282 1283 /** 1284 * Gets the sync state of the folder. 1285 * 1286 * @return the sync state of the folder. 1287 */ 1288 public SyncState getSyncState() { 1289 return this.syncState; 1290 } 1291 1292 /** 1293 * Sets the sync state of the folder. 1294 * 1295 * @param syncState the sync state of the folder. 1296 */ 1297 public void setSyncState(SyncState syncState) { 1298 this.syncState = syncState; 1299 this.addPendingChange("sync_state", syncState.toJSONValue()); 1300 } 1301 1302 /** 1303 * Gets the permissions that the current user has on the folder. 1304 * 1305 * @return the permissions that the current user has on the folder. 1306 */ 1307 public EnumSet<Permission> getPermissions() { 1308 return this.permissions; 1309 } 1310 1311 /** 1312 * Gets whether or not the non-owners can invite collaborators to the folder. 1313 * 1314 * @return [description] 1315 */ 1316 public boolean getCanNonOwnersInvite() { 1317 return this.canNonOwnersInvite; 1318 } 1319 1320 /** 1321 * Sets whether or not non-owners can invite collaborators to the folder. 1322 * 1323 * @param canNonOwnersInvite indicates non-owners can invite collaborators to the folder. 1324 */ 1325 public void setCanNonOwnersInvite(boolean canNonOwnersInvite) { 1326 this.canNonOwnersInvite = canNonOwnersInvite; 1327 this.addPendingChange("can_non_owners_invite", canNonOwnersInvite); 1328 } 1329 1330 /** 1331 * Gets whether future collaborations should be restricted to within the enterprise only. 1332 * 1333 * @return indicates whether collaboration is restricted to enterprise only. 1334 */ 1335 public boolean getIsCollaborationRestrictedToEnterprise() { 1336 return this.isCollaborationRestrictedToEnterprise; 1337 } 1338 1339 /** 1340 * Sets whether future collaborations should be restricted to within the enterprise only. 1341 * 1342 * @param isRestricted indicates whether there is collaboration restriction within enterprise. 1343 */ 1344 public void setIsCollaborationRestrictedToEnterprise(boolean isRestricted) { 1345 this.isCollaborationRestrictedToEnterprise = isRestricted; 1346 this.addPendingChange("is_collaboration_restricted_to_enterprise", isRestricted); 1347 } 1348 1349 /** 1350 * Retrieves the allowed roles for collaborations. 1351 * 1352 * @return the roles allowed for collaboration. 1353 */ 1354 public List<String> getAllowedInviteeRoles() { 1355 return this.allowedInviteeRoles; 1356 } 1357 1358 /** 1359 * Retrieves the allowed access levels for a shared link. 1360 * 1361 * @return the allowed access levels for a shared link. 1362 */ 1363 public List<String> getAllowedSharedLinkAccessLevels() { 1364 return this.allowedSharedLinkAccessLevels; 1365 } 1366 1367 /** 1368 * Gets flag indicating whether this file is Watermarked. 1369 * 1370 * @return whether the file is watermarked or not 1371 */ 1372 public boolean getIsWatermarked() { 1373 return this.isWatermarked; 1374 } 1375 1376 /** 1377 * Gets the metadata on this folder associated with a specified scope and template. 1378 * Makes an attempt to get metadata that was retrieved using getInfo(String ...) method. If no result is found 1379 * then makes an API call to get metadata 1380 * 1381 * @param templateName the metadata template type name. 1382 * @param scope the scope of the template (usually "global" or "enterprise"). 1383 * @return the metadata returned from the server. 1384 */ 1385 public Metadata getMetadata(String templateName, String scope) { 1386 try { 1387 return this.metadataMap.get(scope).get(templateName); 1388 } catch (NullPointerException e) { 1389 return null; 1390 } 1391 } 1392 1393 /** 1394 * Get the field is_externally_owned determining whether this folder is owned by a user outside of the 1395 * enterprise. 1396 * @return a boolean indicating whether this folder is owned by a user outside the enterprise. 1397 */ 1398 public boolean getIsExternallyOwned() { 1399 return this.isExternallyOwned; 1400 } 1401 1402 /** 1403 * Gets the metadata classification type of this folder. 1404 * @return the metadata classification type of this folder. 1405 */ 1406 public BoxClassification getClassification() { 1407 return this.classification; 1408 } 1409 1410 @Override 1411 public BoxFolder getResource() { 1412 return BoxFolder.this; 1413 } 1414 1415 @Override 1416 protected void parseJSONMember(JsonObject.Member member) { 1417 super.parseJSONMember(member); 1418 1419 String memberName = member.getName(); 1420 JsonValue value = member.getValue(); 1421 try { 1422 if (memberName.equals("folder_upload_email")) { 1423 if (this.uploadEmail == null) { 1424 this.uploadEmail = new BoxUploadEmail(value.asObject()); 1425 } else { 1426 this.uploadEmail.update(value.asObject()); 1427 } 1428 1429 } else if (memberName.equals("has_collaborations")) { 1430 this.hasCollaborations = value.asBoolean(); 1431 1432 } else if (memberName.equals("sync_state")) { 1433 this.syncState = SyncState.fromJSONValue(value.asString()); 1434 1435 } else if (memberName.equals("permissions")) { 1436 this.permissions = this.parsePermissions(value.asObject()); 1437 1438 } else if (memberName.equals("can_non_owners_invite")) { 1439 this.canNonOwnersInvite = value.asBoolean(); 1440 } else if (memberName.equals("allowed_shared_link_access_levels")) { 1441 this.allowedSharedLinkAccessLevels = this.parseSharedLinkAccessLevels(value.asArray()); 1442 } else if (memberName.equals("allowed_invitee_roles")) { 1443 this.allowedInviteeRoles = this.parseAllowedInviteeRoles(value.asArray()); 1444 } else if (memberName.equals("is_collaboration_restricted_to_enterprise")) { 1445 this.isCollaborationRestrictedToEnterprise = value.asBoolean(); 1446 } else if (memberName.equals("is_externally_owned")) { 1447 this.isExternallyOwned = value.asBoolean(); 1448 } else if (memberName.equals("watermark_info")) { 1449 JsonObject jsonObject = value.asObject(); 1450 this.isWatermarked = jsonObject.get("is_watermarked").asBoolean(); 1451 } else if (memberName.equals("metadata")) { 1452 JsonObject jsonObject = value.asObject(); 1453 this.metadataMap = Parsers.parseAndPopulateMetadataMap(jsonObject); 1454 } else if (memberName.equals("classification")) { 1455 if (value.isNull()) { 1456 this.classification = null; 1457 } else { 1458 this.classification = new BoxClassification(value.asObject()); 1459 } 1460 } 1461 } catch (Exception e) { 1462 throw new BoxDeserializationException(memberName, value.toString(), e); 1463 } 1464 } 1465 1466 private EnumSet<Permission> parsePermissions(JsonObject jsonObject) { 1467 EnumSet<Permission> permissions = EnumSet.noneOf(Permission.class); 1468 for (JsonObject.Member member : jsonObject) { 1469 JsonValue value = member.getValue(); 1470 if (value.isNull() || !value.asBoolean()) { 1471 continue; 1472 } 1473 1474 String memberName = member.getName(); 1475 if (memberName.equals("can_download")) { 1476 permissions.add(Permission.CAN_DOWNLOAD); 1477 } else if (memberName.equals("can_upload")) { 1478 permissions.add(Permission.CAN_UPLOAD); 1479 } else if (memberName.equals("can_rename")) { 1480 permissions.add(Permission.CAN_RENAME); 1481 } else if (memberName.equals("can_delete")) { 1482 permissions.add(Permission.CAN_DELETE); 1483 } else if (memberName.equals("can_share")) { 1484 permissions.add(Permission.CAN_SHARE); 1485 } else if (memberName.equals("can_invite_collaborator")) { 1486 permissions.add(Permission.CAN_INVITE_COLLABORATOR); 1487 } else if (memberName.equals("can_set_share_access")) { 1488 permissions.add(Permission.CAN_SET_SHARE_ACCESS); 1489 } 1490 } 1491 1492 return permissions; 1493 } 1494 1495 private List<String> parseSharedLinkAccessLevels(JsonArray jsonArray) { 1496 List<String> accessLevels = new ArrayList<String>(jsonArray.size()); 1497 for (JsonValue value : jsonArray) { 1498 accessLevels.add(value.asString()); 1499 } 1500 1501 return accessLevels; 1502 } 1503 1504 private List<String> parseAllowedInviteeRoles(JsonArray jsonArray) { 1505 List<String> roles = new ArrayList<String>(jsonArray.size()); 1506 for (JsonValue value : jsonArray) { 1507 roles.add(value.asString()); 1508 } 1509 1510 return roles; 1511 } 1512 } 1513 1514 /** 1515 * Enumerates the possible sync states that a folder can have. 1516 */ 1517 public enum SyncState { 1518 /** 1519 * The folder is synced. 1520 */ 1521 SYNCED("synced"), 1522 1523 /** 1524 * The folder is not synced. 1525 */ 1526 NOT_SYNCED("not_synced"), 1527 1528 /** 1529 * The folder is partially synced. 1530 */ 1531 PARTIALLY_SYNCED("partially_synced"); 1532 1533 private final String jsonValue; 1534 1535 private SyncState(String jsonValue) { 1536 this.jsonValue = jsonValue; 1537 } 1538 1539 static SyncState fromJSONValue(String jsonValue) { 1540 return SyncState.valueOf(jsonValue.toUpperCase()); 1541 } 1542 1543 String toJSONValue() { 1544 return this.jsonValue; 1545 } 1546 } 1547 1548 /** 1549 * Enumerates the possible permissions that a user can have on a folder. 1550 */ 1551 public enum Permission { 1552 /** 1553 * The user can download the folder. 1554 */ 1555 CAN_DOWNLOAD("can_download"), 1556 1557 /** 1558 * The user can upload to the folder. 1559 */ 1560 CAN_UPLOAD("can_upload"), 1561 1562 /** 1563 * The user can rename the folder. 1564 */ 1565 CAN_RENAME("can_rename"), 1566 1567 /** 1568 * The user can delete the folder. 1569 */ 1570 CAN_DELETE("can_delete"), 1571 1572 /** 1573 * The user can share the folder. 1574 */ 1575 CAN_SHARE("can_share"), 1576 1577 /** 1578 * The user can invite collaborators to the folder. 1579 */ 1580 CAN_INVITE_COLLABORATOR("can_invite_collaborator"), 1581 1582 /** 1583 * The user can set the access level for shared links to the folder. 1584 */ 1585 CAN_SET_SHARE_ACCESS("can_set_share_access"); 1586 1587 private final String jsonValue; 1588 1589 private Permission(String jsonValue) { 1590 this.jsonValue = jsonValue; 1591 } 1592 1593 static Permission fromJSONValue(String jsonValue) { 1594 return Permission.valueOf(jsonValue.toUpperCase()); 1595 } 1596 1597 String toJSONValue() { 1598 return this.jsonValue; 1599 } 1600 } 1601}