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