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 * Retrieves a specific range of child items in this folder. 689 * 690 * @param offset the index of the first child item to retrieve. 691 * @param limit the maximum number of children to retrieve after the offset. 692 * @param fields the fields to retrieve. 693 * @return a partial collection containing the specified range of child items. 694 */ 695 public PartialCollection<BoxItem.Info> getChildrenRange(long offset, long limit, String... fields) { 696 QueryStringBuilder builder = new QueryStringBuilder() 697 .appendParam("limit", limit) 698 .appendParam("offset", offset); 699 700 if (fields.length > 0) { 701 builder.appendParam("fields", fields).toString(); 702 } 703 704 URL url = GET_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), builder.toString(), getID()); 705 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 706 BoxJSONResponse response = (BoxJSONResponse) request.send(); 707 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 708 709 String totalCountString = responseJSON.get("total_count").toString(); 710 long fullSize = Double.valueOf(totalCountString).longValue(); 711 PartialCollection<BoxItem.Info> children = new PartialCollection<BoxItem.Info>(offset, limit, fullSize); 712 JsonArray jsonArray = responseJSON.get("entries").asArray(); 713 for (JsonValue value : jsonArray) { 714 JsonObject jsonObject = value.asObject(); 715 BoxItem.Info parsedItemInfo = (BoxItem.Info) BoxResource.parseInfo(this.getAPI(), jsonObject); 716 if (parsedItemInfo != null) { 717 children.add(parsedItemInfo); 718 } 719 } 720 return children; 721 } 722 723 /** 724 * Returns an iterator over the items in this folder. 725 * 726 * @return an iterator over the items in this folder. 727 */ 728 @Override 729 public Iterator<BoxItem.Info> iterator() { 730 URL url = GET_ITEMS_URL.build(this.getAPI().getBaseURL(), BoxFolder.this.getID()); 731 return new BoxItemIterator(BoxFolder.this.getAPI(), url); 732 } 733 734 /** 735 * Adds new {@link BoxWebHook} to this {@link BoxFolder}. 736 * 737 * @param address {@link BoxWebHook.Info#getAddress()} 738 * @param triggers {@link BoxWebHook.Info#getTriggers()} 739 * @return created {@link BoxWebHook.Info} 740 */ 741 public BoxWebHook.Info addWebHook(URL address, BoxWebHook.Trigger... triggers) { 742 return BoxWebHook.create(this, address, triggers); 743 } 744 745 /** 746 * Used to retrieve the watermark for the folder. 747 * If the folder does not have a watermark applied to it, a 404 Not Found will be returned by API. 748 * 749 * @param fields the fields to retrieve. 750 * @return the watermark associated with the folder. 751 */ 752 public BoxWatermark getWatermark(String... fields) { 753 return this.getWatermark(FOLDER_INFO_URL_TEMPLATE, fields); 754 } 755 756 /** 757 * Used to apply or update the watermark for the folder. 758 * 759 * @return the watermark associated with the folder. 760 */ 761 public BoxWatermark applyWatermark() { 762 return this.applyWatermark(FOLDER_INFO_URL_TEMPLATE, BoxWatermark.WATERMARK_DEFAULT_IMPRINT); 763 } 764 765 /** 766 * Removes a watermark from the folder. 767 * If the folder did not have a watermark applied to it, a 404 Not Found will be returned by API. 768 */ 769 public void removeWatermark() { 770 this.removeWatermark(FOLDER_INFO_URL_TEMPLATE); 771 } 772 773 /** 774 * Used to retrieve all metadata associated with the folder. 775 * 776 * @param fields the optional fields to retrieve. 777 * @return An iterable of metadata instances associated with the folder 778 */ 779 public Iterable<Metadata> getAllMetadata(String... fields) { 780 return Metadata.getAllMetadata(this, fields); 781 } 782 783 /** 784 * This method is deprecated, please use the {@link BoxSearch} class instead. 785 * Searches this folder and all descendant folders using a given queryPlease use BoxSearch Instead. 786 * 787 * @param query the search query. 788 * @return an Iterable containing the search results. 789 */ 790 @Deprecated 791 public Iterable<BoxItem.Info> search(final String query) { 792 return new Iterable<BoxItem.Info>() { 793 @Override 794 public Iterator<BoxItem.Info> iterator() { 795 QueryStringBuilder builder = new QueryStringBuilder(); 796 builder.appendParam("query", query); 797 builder.appendParam("ancestor_folder_ids", getID()); 798 799 URL url = SEARCH_URL_TEMPLATE.buildWithQuery(getAPI().getBaseURL(), builder.toString()); 800 return new BoxItemIterator(getAPI(), url); 801 } 802 }; 803 } 804 805 @Override 806 public BoxFolder.Info setCollections(BoxCollection... collections) { 807 JsonArray jsonArray = new JsonArray(); 808 for (BoxCollection collection : collections) { 809 JsonObject collectionJSON = new JsonObject(); 810 collectionJSON.add("id", collection.getID()); 811 jsonArray.add(collectionJSON); 812 } 813 JsonObject infoJSON = new JsonObject(); 814 infoJSON.add("collections", jsonArray); 815 816 String queryString = new QueryStringBuilder().appendParam("fields", ALL_FIELDS).toString(); 817 URL url = FOLDER_INFO_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 818 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 819 request.setBody(infoJSON.toString()); 820 BoxJSONResponse response = (BoxJSONResponse) request.send(); 821 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 822 return new Info(jsonObject); 823 } 824 825 /** 826 * Creates global property metadata on this folder. 827 * 828 * @param metadata the new metadata values. 829 * @return the metadata returned from the server. 830 */ 831 public Metadata createMetadata(Metadata metadata) { 832 return this.createMetadata(Metadata.DEFAULT_METADATA_TYPE, metadata); 833 } 834 835 /** 836 * Creates metadata on this folder using a specified template. 837 * 838 * @param templateName the name of the metadata template. 839 * @param metadata the new metadata values. 840 * @return the metadata returned from the server. 841 */ 842 public Metadata createMetadata(String templateName, Metadata metadata) { 843 String scope = Metadata.scopeBasedOnType(templateName); 844 return this.createMetadata(templateName, scope, metadata); 845 } 846 847 /** 848 * Creates metadata on this folder using a specified scope and template. 849 * 850 * @param templateName the name of the metadata template. 851 * @param scope the scope of the template (usually "global" or "enterprise"). 852 * @param metadata the new metadata values. 853 * @return the metadata returned from the server. 854 */ 855 public Metadata createMetadata(String templateName, String scope, Metadata metadata) { 856 URL url = METADATA_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID(), scope, templateName); 857 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "POST"); 858 request.addHeader("Content-Type", "application/json"); 859 request.setBody(metadata.toString()); 860 BoxJSONResponse response = (BoxJSONResponse) request.send(); 861 return new Metadata(JsonObject.readFrom(response.getJSON())); 862 } 863 864 /** 865 * Sets the provided metadata on the folder, overwriting any existing metadata keys already present. 866 * 867 * @param templateName the name of the metadata template. 868 * @param scope the scope of the template (usually "global" or "enterprise"). 869 * @param metadata the new metadata values. 870 * @return the metadata returned from the server. 871 */ 872 public Metadata setMetadata(String templateName, String scope, Metadata metadata) { 873 Metadata metadataValue = null; 874 875 try { 876 metadataValue = this.createMetadata(templateName, scope, metadata); 877 } catch (BoxAPIException e) { 878 if (e.getResponseCode() == 409) { 879 Metadata metadataToUpdate = new Metadata(scope, templateName); 880 for (JsonValue value : metadata.getOperations()) { 881 if (value.asObject().get("value").isNumber()) { 882 metadataToUpdate.add(value.asObject().get("path").asString(), 883 value.asObject().get("value").asDouble()); 884 } else if (value.asObject().get("value").isString()) { 885 metadataToUpdate.add(value.asObject().get("path").asString(), 886 value.asObject().get("value").asString()); 887 } else if (value.asObject().get("value").isArray()) { 888 ArrayList<String> list = new ArrayList<String>(); 889 for (JsonValue jsonValue : value.asObject().get("value").asArray()) { 890 list.add(jsonValue.asString()); 891 } 892 metadataToUpdate.add(value.asObject().get("path").asString(), list); 893 } 894 } 895 metadataValue = this.updateMetadata(metadataToUpdate); 896 } else { 897 throw e; 898 } 899 } 900 901 return metadataValue; 902 } 903 904 /** 905 * Gets the global properties metadata on this folder. 906 * 907 * @return the metadata returned from the server. 908 */ 909 public Metadata getMetadata() { 910 return this.getMetadata(Metadata.DEFAULT_METADATA_TYPE); 911 } 912 913 /** 914 * Gets the metadata on this folder associated with a specified template. 915 * 916 * @param templateName the metadata template type name. 917 * @return the metadata returned from the server. 918 */ 919 public Metadata getMetadata(String templateName) { 920 String scope = Metadata.scopeBasedOnType(templateName); 921 return this.getMetadata(templateName, scope); 922 } 923 924 /** 925 * Gets the metadata on this folder associated with a specified scope and template. 926 * 927 * @param templateName the metadata template type name. 928 * @param scope the scope of the template (usually "global" or "enterprise"). 929 * @return the metadata returned from the server. 930 */ 931 public Metadata getMetadata(String templateName, String scope) { 932 URL url = METADATA_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID(), scope, templateName); 933 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 934 BoxJSONResponse response = (BoxJSONResponse) request.send(); 935 return new Metadata(JsonObject.readFrom(response.getJSON())); 936 } 937 938 /** 939 * Updates the global properties metadata on this folder. 940 * 941 * @param metadata the new metadata values. 942 * @return the metadata returned from the server. 943 */ 944 public Metadata updateMetadata(Metadata metadata) { 945 URL url = METADATA_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID(), metadata.getScope(), 946 metadata.getTemplateName()); 947 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "PUT"); 948 request.addHeader("Content-Type", "application/json-patch+json"); 949 request.setBody(metadata.getPatch()); 950 BoxJSONResponse response = (BoxJSONResponse) request.send(); 951 return new Metadata(JsonObject.readFrom(response.getJSON())); 952 } 953 954 /** 955 * Deletes the global properties metadata on this folder. 956 */ 957 public void deleteMetadata() { 958 this.deleteMetadata(Metadata.DEFAULT_METADATA_TYPE); 959 } 960 961 /** 962 * Deletes the metadata on this folder associated with a specified template. 963 * 964 * @param templateName the metadata template type name. 965 */ 966 public void deleteMetadata(String templateName) { 967 String scope = Metadata.scopeBasedOnType(templateName); 968 this.deleteMetadata(templateName, scope); 969 } 970 971 /** 972 * Deletes the metadata on this folder associated with a specified scope and template. 973 * 974 * @param templateName the metadata template type name. 975 * @param scope the scope of the template (usually "global" or "enterprise"). 976 */ 977 public void deleteMetadata(String templateName, String scope) { 978 URL url = METADATA_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID(), scope, templateName); 979 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 980 BoxAPIResponse response = request.send(); 981 response.disconnect(); 982 } 983 984 /** 985 * Adds a metadata classification to the specified file. 986 * 987 * @param classificationType the metadata classification type. 988 * @return the metadata classification type added to the file. 989 */ 990 public String addClassification(String classificationType) { 991 Metadata metadata = new Metadata().add(Metadata.CLASSIFICATION_KEY, classificationType); 992 Metadata classification = this.createMetadata(Metadata.CLASSIFICATION_TEMPLATE_KEY, 993 "enterprise", metadata); 994 995 return classification.getString(Metadata.CLASSIFICATION_KEY); 996 } 997 998 /** 999 * Updates a metadata classification on the specified file. 1000 * 1001 * @param classificationType the metadata classification type. 1002 * @return the new metadata classification type updated on the file. 1003 */ 1004 public String updateClassification(String classificationType) { 1005 Metadata metadata = new Metadata("enterprise", Metadata.CLASSIFICATION_TEMPLATE_KEY); 1006 metadata.replace(Metadata.CLASSIFICATION_KEY, classificationType); 1007 Metadata classification = this.updateMetadata(metadata); 1008 1009 return classification.getString(Metadata.CLASSIFICATION_KEY); 1010 } 1011 1012 /** 1013 * Attempts to add classification to a file. If classification already exists then do update. 1014 * 1015 * @param classificationType the metadata classification type. 1016 * @return the metadata classification type on the file. 1017 */ 1018 public String setClassification(String classificationType) { 1019 Metadata metadata = new Metadata().add(Metadata.CLASSIFICATION_KEY, classificationType); 1020 Metadata classification = null; 1021 1022 try { 1023 classification = this.createMetadata(Metadata.CLASSIFICATION_TEMPLATE_KEY, "enterprise", metadata); 1024 } catch (BoxAPIException e) { 1025 if (e.getResponseCode() == 409) { 1026 metadata = new Metadata("enterprise", Metadata.CLASSIFICATION_TEMPLATE_KEY); 1027 metadata.replace(Metadata.CLASSIFICATION_KEY, classificationType); 1028 classification = this.updateMetadata(metadata); 1029 } else { 1030 throw e; 1031 } 1032 } 1033 1034 return classification.getString("/Box__Security__Classification__Key"); 1035 } 1036 1037 /** 1038 * Gets the classification type for the specified file. 1039 * 1040 * @return the metadata classification type on the file. 1041 */ 1042 public String getClassification() { 1043 Metadata metadata = this.getMetadata(Metadata.CLASSIFICATION_TEMPLATE_KEY); 1044 return metadata.getString(Metadata.CLASSIFICATION_KEY); 1045 } 1046 1047 /** 1048 * Deletes the classification on the file. 1049 */ 1050 public void deleteClassification() { 1051 this.deleteMetadata(Metadata.CLASSIFICATION_TEMPLATE_KEY, "enterprise"); 1052 } 1053 1054 /** 1055 * Creates an upload session to create a new file in chunks. 1056 * This will first verify that the file can be created and then open a session for uploading pieces of the file. 1057 * 1058 * @param fileName the name of the file to be created 1059 * @param fileSize the size of the file that will be uploaded 1060 * @return the created upload session instance 1061 */ 1062 public BoxFileUploadSession.Info createUploadSession(String fileName, long fileSize) { 1063 1064 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1065 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 1066 1067 JsonObject body = new JsonObject(); 1068 body.add("folder_id", this.getID()); 1069 body.add("file_name", fileName); 1070 body.add("file_size", fileSize); 1071 request.setBody(body.toString()); 1072 1073 BoxJSONResponse response = (BoxJSONResponse) request.send(); 1074 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 1075 1076 String sessionId = jsonObject.get("id").asString(); 1077 BoxFileUploadSession session = new BoxFileUploadSession(this.getAPI(), sessionId); 1078 1079 return session.new Info(jsonObject); 1080 } 1081 1082 /** 1083 * Creates a new file. 1084 * 1085 * @param inputStream the stream instance that contains the data. 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 file instance. 1089 * @throws InterruptedException when a thread execution is interrupted. 1090 * @throws IOException when reading a stream throws exception. 1091 */ 1092 public BoxFile.Info uploadLargeFile(InputStream inputStream, String fileName, long fileSize) 1093 throws InterruptedException, IOException { 1094 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1095 this.canUpload(fileName, fileSize); 1096 return new LargeFileUpload(). 1097 upload(this.getAPI(), this.getID(), inputStream, url, fileName, fileSize); 1098 } 1099 1100 /** 1101 * Creates a new file. Also sets file attributes. 1102 * 1103 * @param inputStream the stream instance that contains the data. 1104 * @param fileName the name of the file to be created. 1105 * @param fileSize the size of the file that will be uploaded. 1106 * @param fileAttributes file attributes to set 1107 * @return the created file instance. 1108 * @throws InterruptedException when a thread execution is interrupted. 1109 * @throws IOException when reading a stream throws exception. 1110 */ 1111 public BoxFile.Info uploadLargeFile(InputStream inputStream, String fileName, long fileSize, 1112 Map<String, String> fileAttributes) 1113 throws InterruptedException, IOException { 1114 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1115 this.canUpload(fileName, fileSize); 1116 return new LargeFileUpload(). 1117 upload(this.getAPI(), this.getID(), inputStream, url, fileName, fileSize, fileAttributes); 1118 } 1119 1120 /** 1121 * Creates a new file using specified number of parallel http connections. 1122 * 1123 * @param inputStream the stream instance that contains the data. 1124 * @param fileName the name of the file to be created. 1125 * @param fileSize the size of the file that will be uploaded. 1126 * @param nParallelConnections number of parallel http connections to use 1127 * @param timeOut time to wait before killing the job 1128 * @param unit time unit for the time wait value 1129 * @return the created file instance. 1130 * @throws InterruptedException when a thread execution is interrupted. 1131 * @throws IOException when reading a stream throws exception. 1132 */ 1133 public BoxFile.Info uploadLargeFile(InputStream inputStream, String fileName, long fileSize, 1134 int nParallelConnections, long timeOut, TimeUnit unit) 1135 throws InterruptedException, IOException { 1136 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1137 this.canUpload(fileName, fileSize); 1138 return new LargeFileUpload(nParallelConnections, timeOut, unit). 1139 upload(this.getAPI(), this.getID(), inputStream, url, fileName, fileSize); 1140 } 1141 1142 /** 1143 * Creates a new file using specified number of parallel http connections. Also sets file attributes. 1144 * 1145 * @param inputStream the stream instance that contains the data. 1146 * @param fileName the name of the file to be created. 1147 * @param fileSize the size of the file that will be uploaded. 1148 * @param nParallelConnections number of parallel http connections to use 1149 * @param timeOut time to wait before killing the job 1150 * @param unit time unit for the time wait value 1151 * @param fileAttributes file attributes to set 1152 * @return the created file instance. 1153 * @throws InterruptedException when a thread execution is interrupted. 1154 * @throws IOException when reading a stream throws exception. 1155 */ 1156 public BoxFile.Info uploadLargeFile(InputStream inputStream, String fileName, long fileSize, 1157 int nParallelConnections, long timeOut, TimeUnit unit, 1158 Map<String, String> fileAttributes) 1159 throws InterruptedException, IOException { 1160 URL url = UPLOAD_SESSION_URL_TEMPLATE.build(this.getAPI().getBaseUploadURL()); 1161 this.canUpload(fileName, fileSize); 1162 return new LargeFileUpload(nParallelConnections, timeOut, unit). 1163 upload(this.getAPI(), this.getID(), inputStream, url, fileName, fileSize, fileAttributes); 1164 } 1165 1166 /** 1167 * Creates a new Metadata Cascade Policy on a folder. 1168 * 1169 * @param scope the scope of the metadata cascade policy. 1170 * @param templateKey the key of the template. 1171 * @return information about the Metadata Cascade Policy. 1172 */ 1173 public BoxMetadataCascadePolicy.Info addMetadataCascadePolicy(String scope, String templateKey) { 1174 1175 return BoxMetadataCascadePolicy.create(this.getAPI(), this.getID(), scope, templateKey); 1176 } 1177 1178 /** 1179 * Retrieves all Metadata Cascade Policies on a folder. 1180 * 1181 * @param fields optional fields to retrieve for cascade policies. 1182 * @return the Iterable of Box Metadata Cascade Policies in your enterprise. 1183 */ 1184 public Iterable<BoxMetadataCascadePolicy.Info> getMetadataCascadePolicies(String... fields) { 1185 Iterable<BoxMetadataCascadePolicy.Info> cascadePoliciesInfo = 1186 BoxMetadataCascadePolicy.getAll(this.getAPI(), this.getID(), fields); 1187 1188 return cascadePoliciesInfo; 1189 } 1190 1191 /** 1192 * Retrieves all Metadata Cascade Policies on a folder. 1193 * 1194 * @param enterpriseID the ID of the enterprise to retrieve cascade policies for. 1195 * @param limit the number of entries of cascade policies to retrieve. 1196 * @param fields optional fields to retrieve for cascade policies. 1197 * @return the Iterable of Box Metadata Cascade Policies in your enterprise. 1198 */ 1199 public Iterable<BoxMetadataCascadePolicy.Info> getMetadataCascadePolicies(String enterpriseID, 1200 int limit, String... fields) { 1201 Iterable<BoxMetadataCascadePolicy.Info> cascadePoliciesInfo = 1202 BoxMetadataCascadePolicy.getAll(this.getAPI(), this.getID(), enterpriseID, limit, fields); 1203 1204 return cascadePoliciesInfo; 1205 } 1206 1207 /** 1208 * Lock this folder. 1209 * 1210 * @return a created folder lock object. 1211 */ 1212 public BoxFolderLock.Info lock() { 1213 JsonObject folderObject = new JsonObject(); 1214 folderObject.add("type", "folder"); 1215 folderObject.add("id", this.getID()); 1216 1217 JsonObject lockedOperations = new JsonObject(); 1218 lockedOperations.add("move", true); 1219 lockedOperations.add("delete", true); 1220 1221 1222 JsonObject body = new JsonObject(); 1223 body.add("folder", folderObject); 1224 body.add("locked_operations", lockedOperations); 1225 1226 BoxJSONRequest request = 1227 new BoxJSONRequest(this.getAPI(), FOLDER_LOCK_URL_TEMPLATE.build(this.getAPI().getBaseURL()), 1228 "POST"); 1229 request.setBody(body.toString()); 1230 BoxJSONResponse response = (BoxJSONResponse) request.send(); 1231 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 1232 1233 BoxFolderLock createdFolderLock = new BoxFolderLock(this.getAPI(), responseJSON.get("id").asString()); 1234 return createdFolderLock.new Info(responseJSON); 1235 } 1236 1237 /** 1238 * Get the lock on this folder. 1239 * 1240 * @return a folder lock object. 1241 */ 1242 public Iterable<BoxFolderLock.Info> getLocks() { 1243 String queryString = new QueryStringBuilder().appendParam("folder_id", this.getID()).toString(); 1244 final BoxAPIConnection api = this.getAPI(); 1245 return new BoxResourceIterable<BoxFolderLock.Info>(api, 1246 FOLDER_LOCK_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), queryString), 100) { 1247 @Override 1248 protected BoxFolderLock.Info factory(JsonObject jsonObject) { 1249 BoxFolderLock folderLock = 1250 new BoxFolderLock(api, jsonObject.get("id").asString()); 1251 return folderLock.new Info(jsonObject); 1252 } 1253 }; 1254 } 1255 1256 /** 1257 * Contains information about a BoxFolder. 1258 */ 1259 public class Info extends BoxItem.Info { 1260 private BoxUploadEmail uploadEmail; 1261 private boolean hasCollaborations; 1262 private SyncState syncState; 1263 private EnumSet<Permission> permissions; 1264 private boolean canNonOwnersInvite; 1265 private boolean isWatermarked; 1266 private boolean isCollaborationRestrictedToEnterprise; 1267 private boolean isExternallyOwned; 1268 private Map<String, Map<String, Metadata>> metadataMap; 1269 private List<String> allowedSharedLinkAccessLevels; 1270 private List<String> allowedInviteeRoles; 1271 private BoxClassification classification; 1272 1273 /** 1274 * Constructs an empty Info object. 1275 */ 1276 public Info() { 1277 super(); 1278 } 1279 1280 /** 1281 * Constructs an Info object by parsing information from a JSON string. 1282 * 1283 * @param json the JSON string to parse. 1284 */ 1285 public Info(String json) { 1286 super(json); 1287 } 1288 1289 /** 1290 * Constructs an Info object using an already parsed JSON object. 1291 * 1292 * @param jsonObject the parsed JSON object. 1293 */ 1294 public Info(JsonObject jsonObject) { 1295 super(jsonObject); 1296 } 1297 1298 /** 1299 * Gets the upload email for the folder. 1300 * 1301 * @return the upload email for the folder. 1302 */ 1303 public BoxUploadEmail getUploadEmail() { 1304 return this.uploadEmail; 1305 } 1306 1307 /** 1308 * Sets the upload email for the folder. 1309 * 1310 * @param uploadEmail the upload email for the folder. 1311 */ 1312 public void setUploadEmail(BoxUploadEmail uploadEmail) { 1313 if (this.uploadEmail == uploadEmail) { 1314 return; 1315 } 1316 1317 this.removeChildObject("folder_upload_email"); 1318 this.uploadEmail = uploadEmail; 1319 1320 if (uploadEmail == null) { 1321 this.addPendingChange("folder_upload_email", (String) null); 1322 } else { 1323 this.addChildObject("folder_upload_email", uploadEmail); 1324 } 1325 } 1326 1327 /** 1328 * Gets whether or not the folder has any collaborations. 1329 * 1330 * @return true if the folder has collaborations; otherwise false. 1331 */ 1332 public boolean getHasCollaborations() { 1333 return this.hasCollaborations; 1334 } 1335 1336 /** 1337 * Gets the sync state of the folder. 1338 * 1339 * @return the sync state of the folder. 1340 */ 1341 public SyncState getSyncState() { 1342 return this.syncState; 1343 } 1344 1345 /** 1346 * Sets the sync state of the folder. 1347 * 1348 * @param syncState the sync state of the folder. 1349 */ 1350 public void setSyncState(SyncState syncState) { 1351 this.syncState = syncState; 1352 this.addPendingChange("sync_state", syncState.toJSONValue()); 1353 } 1354 1355 /** 1356 * Gets the permissions that the current user has on the folder. 1357 * 1358 * @return the permissions that the current user has on the folder. 1359 */ 1360 public EnumSet<Permission> getPermissions() { 1361 return this.permissions; 1362 } 1363 1364 /** 1365 * Gets whether or not the non-owners can invite collaborators to the folder. 1366 * 1367 * @return [description] 1368 */ 1369 public boolean getCanNonOwnersInvite() { 1370 return this.canNonOwnersInvite; 1371 } 1372 1373 /** 1374 * Sets whether or not non-owners can invite collaborators to the folder. 1375 * 1376 * @param canNonOwnersInvite indicates non-owners can invite collaborators to the folder. 1377 */ 1378 public void setCanNonOwnersInvite(boolean canNonOwnersInvite) { 1379 this.canNonOwnersInvite = canNonOwnersInvite; 1380 this.addPendingChange("can_non_owners_invite", canNonOwnersInvite); 1381 } 1382 1383 /** 1384 * Gets whether future collaborations should be restricted to within the enterprise only. 1385 * 1386 * @return indicates whether collaboration is restricted to enterprise only. 1387 */ 1388 public boolean getIsCollaborationRestrictedToEnterprise() { 1389 return this.isCollaborationRestrictedToEnterprise; 1390 } 1391 1392 /** 1393 * Sets whether future collaborations should be restricted to within the enterprise only. 1394 * 1395 * @param isRestricted indicates whether there is collaboration restriction within enterprise. 1396 */ 1397 public void setIsCollaborationRestrictedToEnterprise(boolean isRestricted) { 1398 this.isCollaborationRestrictedToEnterprise = isRestricted; 1399 this.addPendingChange("is_collaboration_restricted_to_enterprise", isRestricted); 1400 } 1401 1402 /** 1403 * Retrieves the allowed roles for collaborations. 1404 * 1405 * @return the roles allowed for collaboration. 1406 */ 1407 public List<String> getAllowedInviteeRoles() { 1408 return this.allowedInviteeRoles; 1409 } 1410 1411 /** 1412 * Retrieves the allowed access levels for a shared link. 1413 * 1414 * @return the allowed access levels for a shared link. 1415 */ 1416 public List<String> getAllowedSharedLinkAccessLevels() { 1417 return this.allowedSharedLinkAccessLevels; 1418 } 1419 1420 /** 1421 * Gets flag indicating whether this file is Watermarked. 1422 * 1423 * @return whether the file is watermarked or not 1424 */ 1425 public boolean getIsWatermarked() { 1426 return this.isWatermarked; 1427 } 1428 1429 /** 1430 * Gets the metadata on this folder associated with a specified scope and template. 1431 * Makes an attempt to get metadata that was retrieved using getInfo(String ...) method. If no result is found 1432 * then makes an API call to get metadata 1433 * 1434 * @param templateName the metadata template type name. 1435 * @param scope the scope of the template (usually "global" or "enterprise"). 1436 * @return the metadata returned from the server. 1437 */ 1438 public Metadata getMetadata(String templateName, String scope) { 1439 try { 1440 return this.metadataMap.get(scope).get(templateName); 1441 } catch (NullPointerException e) { 1442 return null; 1443 } 1444 } 1445 1446 /** 1447 * Get the field is_externally_owned determining whether this folder is owned by a user outside of the 1448 * enterprise. 1449 * @return a boolean indicating whether this folder is owned by a user outside the enterprise. 1450 */ 1451 public boolean getIsExternallyOwned() { 1452 return this.isExternallyOwned; 1453 } 1454 1455 /** 1456 * Gets the metadata classification type of this folder. 1457 * @return the metadata classification type of this folder. 1458 */ 1459 public BoxClassification getClassification() { 1460 return this.classification; 1461 } 1462 1463 @Override 1464 public BoxFolder getResource() { 1465 return BoxFolder.this; 1466 } 1467 1468 @Override 1469 protected void parseJSONMember(JsonObject.Member member) { 1470 super.parseJSONMember(member); 1471 1472 String memberName = member.getName(); 1473 JsonValue value = member.getValue(); 1474 try { 1475 if (memberName.equals("folder_upload_email")) { 1476 if (this.uploadEmail == null) { 1477 this.uploadEmail = new BoxUploadEmail(value.asObject()); 1478 } else { 1479 this.uploadEmail.update(value.asObject()); 1480 } 1481 1482 } else if (memberName.equals("has_collaborations")) { 1483 this.hasCollaborations = value.asBoolean(); 1484 1485 } else if (memberName.equals("sync_state")) { 1486 this.syncState = SyncState.fromJSONValue(value.asString()); 1487 1488 } else if (memberName.equals("permissions")) { 1489 this.permissions = this.parsePermissions(value.asObject()); 1490 1491 } else if (memberName.equals("can_non_owners_invite")) { 1492 this.canNonOwnersInvite = value.asBoolean(); 1493 } else if (memberName.equals("allowed_shared_link_access_levels")) { 1494 this.allowedSharedLinkAccessLevels = this.parseSharedLinkAccessLevels(value.asArray()); 1495 } else if (memberName.equals("allowed_invitee_roles")) { 1496 this.allowedInviteeRoles = this.parseAllowedInviteeRoles(value.asArray()); 1497 } else if (memberName.equals("is_collaboration_restricted_to_enterprise")) { 1498 this.isCollaborationRestrictedToEnterprise = value.asBoolean(); 1499 } else if (memberName.equals("is_externally_owned")) { 1500 this.isExternallyOwned = value.asBoolean(); 1501 } else if (memberName.equals("watermark_info")) { 1502 JsonObject jsonObject = value.asObject(); 1503 this.isWatermarked = jsonObject.get("is_watermarked").asBoolean(); 1504 } else if (memberName.equals("metadata")) { 1505 JsonObject jsonObject = value.asObject(); 1506 this.metadataMap = Parsers.parseAndPopulateMetadataMap(jsonObject); 1507 } else if (memberName.equals("classification")) { 1508 if (value.isNull()) { 1509 this.classification = null; 1510 } else { 1511 this.classification = new BoxClassification(value.asObject()); 1512 } 1513 } 1514 } catch (Exception e) { 1515 throw new BoxDeserializationException(memberName, value.toString(), e); 1516 } 1517 } 1518 1519 private EnumSet<Permission> parsePermissions(JsonObject jsonObject) { 1520 EnumSet<Permission> permissions = EnumSet.noneOf(Permission.class); 1521 for (JsonObject.Member member : jsonObject) { 1522 JsonValue value = member.getValue(); 1523 if (value.isNull() || !value.asBoolean()) { 1524 continue; 1525 } 1526 1527 String memberName = member.getName(); 1528 if (memberName.equals("can_download")) { 1529 permissions.add(Permission.CAN_DOWNLOAD); 1530 } else if (memberName.equals("can_upload")) { 1531 permissions.add(Permission.CAN_UPLOAD); 1532 } else if (memberName.equals("can_rename")) { 1533 permissions.add(Permission.CAN_RENAME); 1534 } else if (memberName.equals("can_delete")) { 1535 permissions.add(Permission.CAN_DELETE); 1536 } else if (memberName.equals("can_share")) { 1537 permissions.add(Permission.CAN_SHARE); 1538 } else if (memberName.equals("can_invite_collaborator")) { 1539 permissions.add(Permission.CAN_INVITE_COLLABORATOR); 1540 } else if (memberName.equals("can_set_share_access")) { 1541 permissions.add(Permission.CAN_SET_SHARE_ACCESS); 1542 } 1543 } 1544 1545 return permissions; 1546 } 1547 1548 private List<String> parseSharedLinkAccessLevels(JsonArray jsonArray) { 1549 List<String> accessLevels = new ArrayList<String>(jsonArray.size()); 1550 for (JsonValue value : jsonArray) { 1551 accessLevels.add(value.asString()); 1552 } 1553 1554 return accessLevels; 1555 } 1556 1557 private List<String> parseAllowedInviteeRoles(JsonArray jsonArray) { 1558 List<String> roles = new ArrayList<String>(jsonArray.size()); 1559 for (JsonValue value : jsonArray) { 1560 roles.add(value.asString()); 1561 } 1562 1563 return roles; 1564 } 1565 } 1566 1567 /** 1568 * Enumerates the possible sync states that a folder can have. 1569 */ 1570 public enum SyncState { 1571 /** 1572 * The folder is synced. 1573 */ 1574 SYNCED("synced"), 1575 1576 /** 1577 * The folder is not synced. 1578 */ 1579 NOT_SYNCED("not_synced"), 1580 1581 /** 1582 * The folder is partially synced. 1583 */ 1584 PARTIALLY_SYNCED("partially_synced"); 1585 1586 private final String jsonValue; 1587 1588 private SyncState(String jsonValue) { 1589 this.jsonValue = jsonValue; 1590 } 1591 1592 static SyncState fromJSONValue(String jsonValue) { 1593 return SyncState.valueOf(jsonValue.toUpperCase()); 1594 } 1595 1596 String toJSONValue() { 1597 return this.jsonValue; 1598 } 1599 } 1600 1601 /** 1602 * Enumerates the possible permissions that a user can have on a folder. 1603 */ 1604 public enum Permission { 1605 /** 1606 * The user can download the folder. 1607 */ 1608 CAN_DOWNLOAD("can_download"), 1609 1610 /** 1611 * The user can upload to the folder. 1612 */ 1613 CAN_UPLOAD("can_upload"), 1614 1615 /** 1616 * The user can rename the folder. 1617 */ 1618 CAN_RENAME("can_rename"), 1619 1620 /** 1621 * The user can delete the folder. 1622 */ 1623 CAN_DELETE("can_delete"), 1624 1625 /** 1626 * The user can share the folder. 1627 */ 1628 CAN_SHARE("can_share"), 1629 1630 /** 1631 * The user can invite collaborators to the folder. 1632 */ 1633 CAN_INVITE_COLLABORATOR("can_invite_collaborator"), 1634 1635 /** 1636 * The user can set the access level for shared links to the folder. 1637 */ 1638 CAN_SET_SHARE_ACCESS("can_set_share_access"); 1639 1640 private final String jsonValue; 1641 1642 private Permission(String jsonValue) { 1643 this.jsonValue = jsonValue; 1644 } 1645 1646 static Permission fromJSONValue(String jsonValue) { 1647 return Permission.valueOf(jsonValue.toUpperCase()); 1648 } 1649 1650 String toJSONValue() { 1651 return this.jsonValue; 1652 } 1653 } 1654}