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