001package com.box.sdk; 002 003import java.io.InputStream; 004import java.net.URL; 005import java.util.ArrayList; 006import java.util.Collection; 007import java.util.Date; 008import java.util.EnumSet; 009import java.util.Iterator; 010 011import com.eclipsesource.json.JsonArray; 012import com.eclipsesource.json.JsonObject; 013import com.eclipsesource.json.JsonValue; 014 015/** 016 * Represents a folder on Box. This class can be used to iterate through a folder's contents, collaborate a folder with 017 * another user or group, and perform other common folder operations (move, copy, delete, etc.). 018 * 019 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked 020 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error 021 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p> 022 */ 023@BoxResourceType("folder") 024public class BoxFolder extends BoxItem implements Iterable<BoxItem.Info> { 025 /** 026 * An array of all possible folder fields that can be requested when calling {@link #getInfo()}. 027 */ 028 public static final String[] ALL_FIELDS = {"type", "id", "sequence_id", "etag", "name", "created_at", "modified_at", 029 "description", "size", "path_collection", "created_by", "modified_by", "trashed_at", "purged_at", 030 "content_created_at", "content_modified_at", "owned_by", "shared_link", "folder_upload_email", "parent", 031 "item_status", "item_collection", "sync_state", "has_collaborations", "permissions", "tags", 032 "can_non_owners_invite", "collections", "watermark_info"}; 033 034 private static final URLTemplate CREATE_FOLDER_URL = new URLTemplate("folders"); 035 private static final URLTemplate CREATE_WEB_LINK_URL = new URLTemplate("web_links"); 036 private static final URLTemplate COPY_FOLDER_URL = new URLTemplate("folders/%s/copy"); 037 private static final URLTemplate DELETE_FOLDER_URL = new URLTemplate("folders/%s?recursive=%b"); 038 private static final URLTemplate FOLDER_INFO_URL_TEMPLATE = new URLTemplate("folders/%s"); 039 private static final URLTemplate UPLOAD_FILE_URL = new URLTemplate("files/content"); 040 private static final URLTemplate ADD_COLLABORATION_URL = new URLTemplate("collaborations"); 041 private static final URLTemplate GET_COLLABORATIONS_URL = new URLTemplate("folders/%s/collaborations"); 042 private static final URLTemplate GET_ITEMS_URL = new URLTemplate("folders/%s/items/"); 043 private static final URLTemplate SEARCH_URL_TEMPLATE = new URLTemplate("search"); 044 private static final URLTemplate METADATA_URL_TEMPLATE = new URLTemplate("folders/%s/metadata/%s/%s"); 045 046 /** 047 * Constructs a BoxFolder for a folder with a given ID. 048 * @param api the API connection to be used by the folder. 049 * @param id the ID of the folder. 050 */ 051 public BoxFolder(BoxAPIConnection api, String id) { 052 super(api, id); 053 } 054 055 /** 056 * {@inheritDoc} 057 */ 058 @Override 059 protected URL getItemURL() { 060 return FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 061 } 062 063 /** 064 * Gets the current user's root folder. 065 * @param api the API connection to be used by the folder. 066 * @return the user's root folder. 067 */ 068 public static BoxFolder getRootFolder(BoxAPIConnection api) { 069 return new BoxFolder(api, "0"); 070 } 071 072 /** 073 * Adds a collaborator to this folder. 074 * @param collaborator the collaborator to add. 075 * @param role the role of the collaborator. 076 * @return info about the new collaboration. 077 */ 078 public BoxCollaboration.Info collaborate(BoxCollaborator collaborator, BoxCollaboration.Role role) { 079 JsonObject accessibleByField = new JsonObject(); 080 accessibleByField.add("id", collaborator.getID()); 081 082 if (collaborator instanceof BoxUser) { 083 accessibleByField.add("type", "user"); 084 } else if (collaborator instanceof BoxGroup) { 085 accessibleByField.add("type", "group"); 086 } else { 087 throw new IllegalArgumentException("The given collaborator is of an unknown type."); 088 } 089 090 return this.collaborate(accessibleByField, role); 091 } 092 093 /** 094 * Adds a collaborator to this folder. An email will be sent to the collaborator if they don't already have a Box 095 * account. 096 * @param email the email address of the collaborator to add. 097 * @param role the role of the collaborator. 098 * @return info about the new collaboration. 099 */ 100 public BoxCollaboration.Info collaborate(String email, BoxCollaboration.Role role) { 101 JsonObject accessibleByField = new JsonObject(); 102 accessibleByField.add("login", email); 103 accessibleByField.add("type", "user"); 104 105 return this.collaborate(accessibleByField, role); 106 } 107 108 private BoxCollaboration.Info collaborate(JsonObject accessibleByField, BoxCollaboration.Role role) { 109 BoxAPIConnection api = this.getAPI(); 110 URL url = ADD_COLLABORATION_URL.build(api.getBaseURL()); 111 112 JsonObject itemField = new JsonObject(); 113 itemField.add("id", this.getID()); 114 itemField.add("type", "folder"); 115 116 JsonObject requestJSON = new JsonObject(); 117 requestJSON.add("item", itemField); 118 requestJSON.add("accessible_by", accessibleByField); 119 requestJSON.add("role", role.toJSONString()); 120 121 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 122 request.setBody(requestJSON.toString()); 123 BoxJSONResponse response = (BoxJSONResponse) request.send(); 124 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 125 126 BoxCollaboration newCollaboration = new BoxCollaboration(api, responseJSON.get("id").asString()); 127 BoxCollaboration.Info info = newCollaboration.new Info(responseJSON); 128 return info; 129 } 130 131 @Override 132 public BoxSharedLink createSharedLink(BoxSharedLink.Access access, Date unshareDate, 133 BoxSharedLink.Permissions permissions) { 134 135 BoxSharedLink sharedLink = new BoxSharedLink(access, unshareDate, permissions); 136 Info info = new Info(); 137 info.setSharedLink(sharedLink); 138 139 this.updateInfo(info); 140 return info.getSharedLink(); 141 } 142 143 /** 144 * Gets information about all of the collaborations for this folder. 145 * @return a collection of information about the collaborations for this folder. 146 */ 147 public Collection<BoxCollaboration.Info> getCollaborations() { 148 BoxAPIConnection api = this.getAPI(); 149 URL url = GET_COLLABORATIONS_URL.build(api.getBaseURL(), this.getID()); 150 151 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 152 BoxJSONResponse response = (BoxJSONResponse) request.send(); 153 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 154 155 int entriesCount = responseJSON.get("total_count").asInt(); 156 Collection<BoxCollaboration.Info> collaborations = new ArrayList<BoxCollaboration.Info>(entriesCount); 157 JsonArray entries = responseJSON.get("entries").asArray(); 158 for (JsonValue entry : entries) { 159 JsonObject entryObject = entry.asObject(); 160 BoxCollaboration collaboration = new BoxCollaboration(api, entryObject.get("id").asString()); 161 BoxCollaboration.Info info = collaboration.new Info(entryObject); 162 collaborations.add(info); 163 } 164 165 return collaborations; 166 } 167 168 @Override 169 public BoxFolder.Info getInfo() { 170 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 171 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 172 BoxJSONResponse response = (BoxJSONResponse) request.send(); 173 return new Info(response.getJSON()); 174 } 175 176 @Override 177 public BoxFolder.Info getInfo(String... fields) { 178 String queryString = new QueryStringBuilder().appendParam("fields", fields).toString(); 179 URL url = FOLDER_INFO_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 180 181 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 182 BoxJSONResponse response = (BoxJSONResponse) request.send(); 183 return new Info(response.getJSON()); 184 } 185 186 /** 187 * Updates the information about this folder with any info fields that have been modified locally. 188 * @param info the updated info. 189 */ 190 public void updateInfo(BoxFolder.Info info) { 191 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 192 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 193 request.setBody(info.getPendingChanges()); 194 BoxJSONResponse response = (BoxJSONResponse) request.send(); 195 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 196 info.update(jsonObject); 197 } 198 199 @Override 200 public BoxFolder.Info copy(BoxFolder destination) { 201 return this.copy(destination, null); 202 } 203 204 @Override 205 public BoxFolder.Info copy(BoxFolder destination, String newName) { 206 URL url = COPY_FOLDER_URL.build(this.getAPI().getBaseURL(), this.getID()); 207 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 208 209 JsonObject parent = new JsonObject(); 210 parent.add("id", destination.getID()); 211 212 JsonObject copyInfo = new JsonObject(); 213 copyInfo.add("parent", parent); 214 if (newName != null) { 215 copyInfo.add("name", newName); 216 } 217 218 request.setBody(copyInfo.toString()); 219 BoxJSONResponse response = (BoxJSONResponse) request.send(); 220 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 221 BoxFolder copiedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString()); 222 return copiedFolder.new Info(responseJSON); 223 } 224 225 /** 226 * Creates a new child folder inside this folder. 227 * @param name the new folder's name. 228 * @return the created folder's info. 229 */ 230 public BoxFolder.Info createFolder(String name) { 231 JsonObject parent = new JsonObject(); 232 parent.add("id", this.getID()); 233 234 JsonObject newFolder = new JsonObject(); 235 newFolder.add("name", name); 236 newFolder.add("parent", parent); 237 238 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), CREATE_FOLDER_URL.build(this.getAPI().getBaseURL()), 239 "POST"); 240 request.setBody(newFolder.toString()); 241 BoxJSONResponse response = (BoxJSONResponse) request.send(); 242 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 243 244 BoxFolder createdFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString()); 245 return createdFolder.new Info(responseJSON); 246 } 247 248 /** 249 * Deletes this folder, optionally recursively deleting all of its contents. 250 * @param recursive true to recursively delete this folder's contents; otherwise false. 251 */ 252 public void delete(boolean recursive) { 253 URL url = DELETE_FOLDER_URL.build(this.getAPI().getBaseURL(), this.getID(), recursive); 254 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 255 BoxAPIResponse response = request.send(); 256 response.disconnect(); 257 } 258 259 @Override 260 public BoxItem.Info move(BoxFolder destination) { 261 return this.move(destination, null); 262 } 263 264 @Override 265 public BoxItem.Info move(BoxFolder destination, String newName) { 266 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 267 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 268 269 JsonObject parent = new JsonObject(); 270 parent.add("id", destination.getID()); 271 272 JsonObject updateInfo = new JsonObject(); 273 updateInfo.add("parent", parent); 274 if (newName != null) { 275 updateInfo.add("name", newName); 276 } 277 278 request.setBody(updateInfo.toString()); 279 BoxJSONResponse response = (BoxJSONResponse) request.send(); 280 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 281 BoxFolder movedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString()); 282 return movedFolder.new Info(responseJSON); 283 } 284 285 /** 286 * Renames this folder. 287 * @param newName the new name of the folder. 288 */ 289 public void rename(String newName) { 290 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 291 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 292 293 JsonObject updateInfo = new JsonObject(); 294 updateInfo.add("name", newName); 295 296 request.setBody(updateInfo.toString()); 297 BoxAPIResponse response = request.send(); 298 response.disconnect(); 299 } 300 301 /** 302 * Checks if the file can be successfully uploaded by using the preflight check. 303 * @param name the name to give the uploaded file. 304 * @param fileSize the size of the file used for account capacity calculations. 305 */ 306 public void canUpload(String name, long fileSize) { 307 URL url = UPLOAD_FILE_URL.build(this.getAPI().getBaseURL()); 308 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "OPTIONS"); 309 310 JsonObject parent = new JsonObject(); 311 parent.add("id", this.getID()); 312 313 JsonObject preflightInfo = new JsonObject(); 314 preflightInfo.add("parent", parent); 315 preflightInfo.add("name", name); 316 317 preflightInfo.add("size", fileSize); 318 319 request.setBody(preflightInfo.toString()); 320 BoxAPIResponse response = request.send(); 321 response.disconnect(); 322 } 323 324 /** 325 * Uploads a new file to this folder. 326 * @param fileContent a stream containing the contents of the file to upload. 327 * @param name the name to give the uploaded file. 328 * @return the uploaded file's info. 329 */ 330 public BoxFile.Info uploadFile(InputStream fileContent, String name) { 331 FileUploadParams uploadInfo = new FileUploadParams() 332 .setContent(fileContent) 333 .setName(name); 334 return this.uploadFile(uploadInfo); 335 } 336 337 /** 338 * Uploads a new file to this folder while reporting the progress to a ProgressListener. 339 * @param fileContent a stream containing the contents of the file to upload. 340 * @param name the name to give the uploaded file. 341 * @param fileSize the size of the file used for determining the progress of the upload. 342 * @param listener a listener for monitoring the upload's progress. 343 * @return the uploaded file's info. 344 */ 345 public BoxFile.Info uploadFile(InputStream fileContent, String name, long fileSize, ProgressListener listener) { 346 FileUploadParams uploadInfo = new FileUploadParams() 347 .setContent(fileContent) 348 .setName(name) 349 .setSize(fileSize) 350 .setProgressListener(listener); 351 return this.uploadFile(uploadInfo); 352 } 353 354 /** 355 * Uploads a new file to this folder with custom upload parameters. 356 * @param uploadParams the custom upload parameters. 357 * @return the uploaded file's info. 358 */ 359 public BoxFile.Info uploadFile(FileUploadParams uploadParams) { 360 URL uploadURL = UPLOAD_FILE_URL.build(this.getAPI().getBaseUploadURL()); 361 BoxMultipartRequest request = new BoxMultipartRequest(getAPI(), uploadURL); 362 363 JsonObject fieldJSON = new JsonObject(); 364 JsonObject parentIdJSON = new JsonObject(); 365 parentIdJSON.add("id", getID()); 366 fieldJSON.add("name", uploadParams.getName()); 367 fieldJSON.add("parent", parentIdJSON); 368 369 if (uploadParams.getCreated() != null) { 370 fieldJSON.add("content_created_at", BoxDateFormat.format(uploadParams.getCreated())); 371 } 372 373 if (uploadParams.getModified() != null) { 374 fieldJSON.add("content_modified_at", BoxDateFormat.format(uploadParams.getModified())); 375 } 376 377 request.putField("attributes", fieldJSON.toString()); 378 379 if (uploadParams.getSize() > 0) { 380 request.setFile(uploadParams.getContent(), uploadParams.getName(), uploadParams.getSize()); 381 } else { 382 request.setFile(uploadParams.getContent(), uploadParams.getName()); 383 } 384 385 BoxJSONResponse response; 386 if (uploadParams.getProgressListener() == null) { 387 response = (BoxJSONResponse) request.send(); 388 } else { 389 response = (BoxJSONResponse) request.send(uploadParams.getProgressListener()); 390 } 391 JsonObject collection = JsonObject.readFrom(response.getJSON()); 392 JsonArray entries = collection.get("entries").asArray(); 393 JsonObject fileInfoJSON = entries.get(0).asObject(); 394 String uploadedFileID = fileInfoJSON.get("id").asString(); 395 396 BoxFile uploadedFile = new BoxFile(getAPI(), uploadedFileID); 397 return uploadedFile.new Info(fileInfoJSON); 398 } 399 400 /** 401 * Uploads a new weblink to this folder. 402 * @param linkURL the URL the weblink points to. 403 * @return the uploaded weblink's info. 404 */ 405 public BoxWebLink.Info createWebLink(URL linkURL) { 406 return this.createWebLink(null, linkURL, null); 407 } 408 409 /** 410 * Uploads a new weblink to this folder. 411 * @param name the filename for the weblink. 412 * @param linkURL the URL the weblink points to. 413 * @return the uploaded weblink's info. 414 */ 415 public BoxWebLink.Info createWebLink(String name, URL linkURL) { 416 return this.createWebLink(name, linkURL, null); 417 } 418 419 /** 420 * Uploads a new weblink to this folder. 421 * @param linkURL the URL the weblink points to. 422 * @param description the weblink's description. 423 * @return the uploaded weblink's info. 424 */ 425 public BoxWebLink.Info createWebLink(URL linkURL, String description) { 426 return this.createWebLink(null, linkURL, description); 427 } 428 429 /** 430 * Uploads a new weblink to this folder. 431 * @param name the filename for the weblink. 432 * @param linkURL the URL the weblink points to. 433 * @param description the weblink's description. 434 * @return the uploaded weblink's info. 435 */ 436 public BoxWebLink.Info createWebLink(String name, URL linkURL, String description) { 437 JsonObject parent = new JsonObject(); 438 parent.add("id", this.getID()); 439 440 JsonObject newWebLink = new JsonObject(); 441 newWebLink.add("name", name); 442 newWebLink.add("parent", parent); 443 newWebLink.add("url", linkURL.toString()); 444 445 if (description != null) { 446 newWebLink.add("description", description); 447 } 448 449 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), 450 CREATE_WEB_LINK_URL.build(this.getAPI().getBaseURL()), "POST"); 451 request.setBody(newWebLink.toString()); 452 BoxJSONResponse response = (BoxJSONResponse) request.send(); 453 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 454 455 BoxWebLink createdWebLink = new BoxWebLink(this.getAPI(), responseJSON.get("id").asString()); 456 return createdWebLink.new Info(responseJSON); 457 } 458 459 /** 460 * Returns an iterable containing the items in this folder. Iterating over the iterable returned by this method is 461 * equivalent to iterating over this BoxFolder directly. 462 * @return an iterable containing the items in this folder. 463 */ 464 public Iterable<BoxItem.Info> getChildren() { 465 return this; 466 } 467 468 /** 469 * Returns an iterable containing the items in this folder and specifies which child fields to retrieve from the 470 * API. 471 * @param fields the fields to retrieve. 472 * @return an iterable containing the items in this folder. 473 */ 474 public Iterable<BoxItem.Info> getChildren(final String... fields) { 475 return new Iterable<BoxItem.Info>() { 476 @Override 477 public Iterator<BoxItem.Info> iterator() { 478 String queryString = new QueryStringBuilder().appendParam("fields", fields).toString(); 479 URL url = GET_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), queryString, getID()); 480 return new BoxItemIterator(getAPI(), url); 481 } 482 }; 483 } 484 485 /** 486 * Retrieves a specific range of child items in this folder. 487 * @param offset the index of the first child item to retrieve. 488 * @param limit the maximum number of children to retrieve after the offset. 489 * @param fields the fields to retrieve. 490 * @return a partial collection containing the specified range of child items. 491 */ 492 public PartialCollection<BoxItem.Info> getChildrenRange(long offset, long limit, String... fields) { 493 QueryStringBuilder builder = new QueryStringBuilder() 494 .appendParam("limit", limit) 495 .appendParam("offset", offset); 496 497 if (fields.length > 0) { 498 builder.appendParam("fields", fields).toString(); 499 } 500 501 URL url = GET_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), builder.toString(), getID()); 502 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 503 BoxJSONResponse response = (BoxJSONResponse) request.send(); 504 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 505 506 String totalCountString = responseJSON.get("total_count").toString(); 507 long fullSize = Double.valueOf(totalCountString).longValue(); 508 PartialCollection<BoxItem.Info> children = new PartialCollection<BoxItem.Info>(offset, limit, fullSize); 509 JsonArray jsonArray = responseJSON.get("entries").asArray(); 510 for (JsonValue value : jsonArray) { 511 JsonObject jsonObject = value.asObject(); 512 BoxItem.Info parsedItemInfo = (BoxItem.Info) BoxResource.parseInfo(this.getAPI(), jsonObject); 513 if (parsedItemInfo != null) { 514 children.add(parsedItemInfo); 515 } 516 } 517 return children; 518 } 519 520 /** 521 * Returns an iterator over the items in this folder. 522 * @return an iterator over the items in this folder. 523 */ 524 @Override 525 public Iterator<BoxItem.Info> iterator() { 526 URL url = GET_ITEMS_URL.build(this.getAPI().getBaseURL(), BoxFolder.this.getID()); 527 return new BoxItemIterator(BoxFolder.this.getAPI(), url); 528 } 529 530 /** 531 * Adds new {@link BoxWebHook} to this {@link BoxFolder}. 532 * 533 * @param address 534 * {@link BoxWebHook.Info#getAddress()} 535 * @param triggers 536 * {@link BoxWebHook.Info#getTriggers()} 537 * @return created {@link BoxWebHook.Info} 538 */ 539 public BoxWebHook.Info addWebHook(URL address, BoxWebHook.Trigger... triggers) { 540 return BoxWebHook.create(this, address, triggers); 541 } 542 543 /** 544 545 * Used to retrieve the watermark for the folder. 546 * If the folder does not have a watermark applied to it, a 404 Not Found will be returned by API. 547 * @param fields the fields to retrieve. 548 * @return the watermark associated with the folder. 549 */ 550 public BoxWatermark getWatermark(String... fields) { 551 return this.getWatermark(FOLDER_INFO_URL_TEMPLATE, fields); 552 } 553 554 /** 555 * Used to apply or update the watermark for the folder. 556 * @return the watermark associated with the folder. 557 */ 558 public BoxWatermark applyWatermark() { 559 return this.applyWatermark(FOLDER_INFO_URL_TEMPLATE, BoxWatermark.WATERMARK_DEFAULT_IMPRINT); 560 } 561 562 /** 563 * Removes a watermark from the folder. 564 * If the folder did not have a watermark applied to it, a 404 Not Found will be returned by API. 565 */ 566 public void removeWatermark() { 567 this.removeWatermark(FOLDER_INFO_URL_TEMPLATE); 568 } 569 570 /** 571 * Used to retrieve all metadata associated with the folder. 572 * 573 * @param fields the optional fields to retrieve. 574 * @return An iterable of metadata instances associated with the folder 575 */ 576 public Iterable<Metadata> getAllMetadata(String... fields) { 577 return Metadata.getAllMetadata(this, fields); 578 } 579 580 /** 581 * This method is deprecated, please use the {@link BoxSearch} class instead. 582 * Searches this folder and all descendant folders using a given queryPlease use BoxSearch Instead. 583 * @param query the search query. 584 * @return an Iterable containing the search results. 585 */ 586 @Deprecated 587 public Iterable<BoxItem.Info> search(final String query) { 588 return new Iterable<BoxItem.Info>() { 589 @Override 590 public Iterator<BoxItem.Info> iterator() { 591 QueryStringBuilder builder = new QueryStringBuilder(); 592 builder.appendParam("query", query); 593 builder.appendParam("ancestor_folder_ids", getID()); 594 595 URL url = SEARCH_URL_TEMPLATE.buildWithQuery(getAPI().getBaseURL(), builder.toString()); 596 return new BoxItemIterator(getAPI(), url); 597 } 598 }; 599 } 600 601 @Override 602 public BoxFolder.Info setCollections(BoxCollection... collections) { 603 JsonArray jsonArray = new JsonArray(); 604 for (BoxCollection collection : collections) { 605 JsonObject collectionJSON = new JsonObject(); 606 collectionJSON.add("id", collection.getID()); 607 jsonArray.add(collectionJSON); 608 } 609 JsonObject infoJSON = new JsonObject(); 610 infoJSON.add("collections", jsonArray); 611 612 String queryString = new QueryStringBuilder().appendParam("fields", ALL_FIELDS).toString(); 613 URL url = FOLDER_INFO_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 614 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 615 request.setBody(infoJSON.toString()); 616 BoxJSONResponse response = (BoxJSONResponse) request.send(); 617 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 618 return new Info(jsonObject); 619 } 620 621 /** 622 * Creates global property metadata on this folder. 623 * @param metadata the new metadata values. 624 * @return the metadata returned from the server. 625 */ 626 public Metadata createMetadata(Metadata metadata) { 627 return this.createMetadata(Metadata.DEFAULT_METADATA_TYPE, metadata); 628 } 629 630 /** 631 * Creates metadata on this folder using a specified template. 632 * @param templateName the name of the metadata template. 633 * @param metadata the new metadata values. 634 * @return the metadata returned from the server. 635 */ 636 public Metadata createMetadata(String templateName, Metadata metadata) { 637 String scope = Metadata.scopeBasedOnType(templateName); 638 return this.createMetadata(templateName, scope, metadata); 639 } 640 641 /** 642 * Creates metadata on this folder using a specified scope and template. 643 * @param templateName the name of the metadata template. 644 * @param scope the scope of the template (usually "global" or "enterprise"). 645 * @param metadata the new metadata values. 646 * @return the metadata returned from the server. 647 */ 648 public Metadata createMetadata(String templateName, String scope, Metadata metadata) { 649 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), scope, templateName); 650 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "POST"); 651 request.addHeader("Content-Type", "application/json"); 652 request.setBody(metadata.toString()); 653 BoxJSONResponse response = (BoxJSONResponse) request.send(); 654 return new Metadata(JsonObject.readFrom(response.getJSON())); 655 } 656 657 /** 658 * Gets the global properties metadata on this folder. 659 * @return the metadata returned from the server. 660 */ 661 public Metadata getMetadata() { 662 return this.getMetadata(Metadata.DEFAULT_METADATA_TYPE); 663 } 664 665 /** 666 * Gets the metadata on this folder associated with a specified template. 667 * @param templateName the metadata template type name. 668 * @return the metadata returned from the server. 669 */ 670 public Metadata getMetadata(String templateName) { 671 String scope = Metadata.scopeBasedOnType(templateName); 672 return this.getMetadata(templateName, scope); 673 } 674 675 /** 676 * Gets the metadata on this folder associated with a specified scope and template. 677 * @param templateName the metadata template type name. 678 * @param scope the scope of the template (usually "global" or "enterprise"). 679 * @return the metadata returned from the server. 680 */ 681 public Metadata getMetadata(String templateName, String scope) { 682 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), scope, templateName); 683 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 684 BoxJSONResponse response = (BoxJSONResponse) request.send(); 685 return new Metadata(JsonObject.readFrom(response.getJSON())); 686 } 687 688 /** 689 * Updates the global properties metadata on this folder. 690 * @param metadata the new metadata values. 691 * @return the metadata returned from the server. 692 */ 693 public Metadata updateMetadata(Metadata metadata) { 694 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), metadata.getScope(), 695 metadata.getTemplateName()); 696 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "PUT"); 697 request.addHeader("Content-Type", "application/json-patch+json"); 698 request.setBody(metadata.getPatch()); 699 BoxJSONResponse response = (BoxJSONResponse) request.send(); 700 return new Metadata(JsonObject.readFrom(response.getJSON())); 701 } 702 703 /** 704 * Deletes the global properties metadata on this folder. 705 */ 706 public void deleteMetadata() { 707 this.deleteMetadata(Metadata.DEFAULT_METADATA_TYPE); 708 } 709 710 /** 711 * Deletes the metadata on this folder associated with a specified template. 712 * @param templateName the metadata template type name. 713 */ 714 public void deleteMetadata(String templateName) { 715 String scope = Metadata.scopeBasedOnType(templateName); 716 this.deleteMetadata(templateName, scope); 717 } 718 719 /** 720 * Deletes the metadata on this folder associated with a specified scope and template. 721 * @param templateName the metadata template type name. 722 * @param scope the scope of the template (usually "global" or "enterprise"). 723 */ 724 public void deleteMetadata(String templateName, String scope) { 725 URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), scope, templateName); 726 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 727 BoxAPIResponse response = request.send(); 728 response.disconnect(); 729 } 730 731 /** 732 * Contains information about a BoxFolder. 733 */ 734 public class Info extends BoxItem.Info { 735 private BoxUploadEmail uploadEmail; 736 private boolean hasCollaborations; 737 private SyncState syncState; 738 private EnumSet<Permission> permissions; 739 private boolean canNonOwnersInvite; 740 private boolean isWatermarked; 741 742 /** 743 * Constructs an empty Info object. 744 */ 745 public Info() { 746 super(); 747 } 748 749 /** 750 * Constructs an Info object by parsing information from a JSON string. 751 * @param json the JSON string to parse. 752 */ 753 public Info(String json) { 754 super(json); 755 } 756 757 /** 758 * Constructs an Info object using an already parsed JSON object. 759 * @param jsonObject the parsed JSON object. 760 */ 761 Info(JsonObject jsonObject) { 762 super(jsonObject); 763 } 764 765 /** 766 * Gets the upload email for the folder. 767 * @return the upload email for the folder. 768 */ 769 public BoxUploadEmail getUploadEmail() { 770 return this.uploadEmail; 771 } 772 773 /** 774 * Sets the upload email for the folder. 775 * @param uploadEmail the upload email for the folder. 776 */ 777 public void setUploadEmail(BoxUploadEmail uploadEmail) { 778 if (this.uploadEmail == uploadEmail) { 779 return; 780 } 781 782 this.removeChildObject("folder_upload_email"); 783 this.uploadEmail = uploadEmail; 784 785 if (uploadEmail == null) { 786 this.addPendingChange("folder_upload_email", (String) null); 787 } else { 788 this.addChildObject("folder_upload_email", uploadEmail); 789 } 790 } 791 792 /** 793 * Gets whether or not the folder has any collaborations. 794 * @return true if the folder has collaborations; otherwise false. 795 */ 796 public boolean getHasCollaborations() { 797 return this.hasCollaborations; 798 } 799 800 /** 801 * Gets the sync state of the folder. 802 * @return the sync state of the folder. 803 */ 804 public SyncState getSyncState() { 805 return this.syncState; 806 } 807 808 /** 809 * Sets the sync state of the folder. 810 * @param syncState the sync state of the folder. 811 */ 812 public void setSyncState(SyncState syncState) { 813 this.syncState = syncState; 814 this.addPendingChange("sync_state", syncState.toJSONValue()); 815 } 816 817 /** 818 * Gets the permissions that the current user has on the folder. 819 * @return the permissions that the current user has on the folder. 820 */ 821 public EnumSet<Permission> getPermissions() { 822 return this.permissions; 823 } 824 825 /** 826 * Gets whether or not the non-owners can invite collaborators to the folder. 827 * @return [description] 828 */ 829 public boolean getCanNonOwnersInvite() { 830 return this.canNonOwnersInvite; 831 } 832 833 /** 834 * Gets flag indicating whether this file is Watermarked. 835 * @return whether the file is watermarked or not 836 */ 837 public boolean getIsWatermarked() { 838 return this.isWatermarked; 839 } 840 841 @Override 842 public BoxFolder getResource() { 843 return BoxFolder.this; 844 } 845 846 @Override 847 protected void parseJSONMember(JsonObject.Member member) { 848 super.parseJSONMember(member); 849 850 String memberName = member.getName(); 851 JsonValue value = member.getValue(); 852 if (memberName.equals("folder_upload_email")) { 853 if (this.uploadEmail == null) { 854 this.uploadEmail = new BoxUploadEmail(value.asObject()); 855 } else { 856 this.uploadEmail.update(value.asObject()); 857 } 858 859 } else if (memberName.equals("has_collaborations")) { 860 this.hasCollaborations = value.asBoolean(); 861 862 } else if (memberName.equals("sync_state")) { 863 this.syncState = SyncState.fromJSONValue(value.asString()); 864 865 } else if (memberName.equals("permissions")) { 866 this.permissions = this.parsePermissions(value.asObject()); 867 868 } else if (memberName.equals("can_non_owners_invite")) { 869 this.canNonOwnersInvite = value.asBoolean(); 870 } else if (memberName.equals("watermark_info")) { 871 JsonObject jsonObject = value.asObject(); 872 this.isWatermarked = jsonObject.get("is_watermarked").asBoolean(); 873 } 874 } 875 876 private EnumSet<Permission> parsePermissions(JsonObject jsonObject) { 877 EnumSet<Permission> permissions = EnumSet.noneOf(Permission.class); 878 for (JsonObject.Member member : jsonObject) { 879 JsonValue value = member.getValue(); 880 if (value.isNull() || !value.asBoolean()) { 881 continue; 882 } 883 884 String memberName = member.getName(); 885 if (memberName.equals("can_download")) { 886 permissions.add(Permission.CAN_DOWNLOAD); 887 } else if (memberName.equals("can_upload")) { 888 permissions.add(Permission.CAN_UPLOAD); 889 } else if (memberName.equals("can_rename")) { 890 permissions.add(Permission.CAN_RENAME); 891 } else if (memberName.equals("can_delete")) { 892 permissions.add(Permission.CAN_DELETE); 893 } else if (memberName.equals("can_share")) { 894 permissions.add(Permission.CAN_SHARE); 895 } else if (memberName.equals("can_invite_collaborator")) { 896 permissions.add(Permission.CAN_INVITE_COLLABORATOR); 897 } else if (memberName.equals("can_set_share_access")) { 898 permissions.add(Permission.CAN_SET_SHARE_ACCESS); 899 } 900 } 901 902 return permissions; 903 } 904 } 905 906 /** 907 * Enumerates the possible sync states that a folder can have. 908 */ 909 public enum SyncState { 910 /** 911 * The folder is synced. 912 */ 913 SYNCED("synced"), 914 915 /** 916 * The folder is not synced. 917 */ 918 NOT_SYNCED("not_synced"), 919 920 /** 921 * The folder is partially synced. 922 */ 923 PARTIALLY_SYNCED("partially_synced"); 924 925 private final String jsonValue; 926 927 private SyncState(String jsonValue) { 928 this.jsonValue = jsonValue; 929 } 930 931 static SyncState fromJSONValue(String jsonValue) { 932 return SyncState.valueOf(jsonValue.toUpperCase()); 933 } 934 935 String toJSONValue() { 936 return this.jsonValue; 937 } 938 } 939 940 /** 941 * Enumerates the possible permissions that a user can have on a folder. 942 */ 943 public enum Permission { 944 /** 945 * The user can download the folder. 946 */ 947 CAN_DOWNLOAD("can_download"), 948 949 /** 950 * The user can upload to the folder. 951 */ 952 CAN_UPLOAD("can_upload"), 953 954 /** 955 * The user can rename the folder. 956 */ 957 CAN_RENAME("can_rename"), 958 959 /** 960 * The user can delete the folder. 961 */ 962 CAN_DELETE("can_delete"), 963 964 /** 965 * The user can share the folder. 966 */ 967 CAN_SHARE("can_share"), 968 969 /** 970 * The user can invite collaborators to the folder. 971 */ 972 CAN_INVITE_COLLABORATOR("can_invite_collaborator"), 973 974 /** 975 * The user can set the access level for shared links to the folder. 976 */ 977 CAN_SET_SHARE_ACCESS("can_set_share_access"); 978 979 private final String jsonValue; 980 981 private Permission(String jsonValue) { 982 this.jsonValue = jsonValue; 983 } 984 985 static Permission fromJSONValue(String jsonValue) { 986 return Permission.valueOf(jsonValue.toUpperCase()); 987 } 988 989 String toJSONValue() { 990 return this.jsonValue; 991 } 992 } 993}