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 */
023public class BoxFolder extends BoxItem implements Iterable<BoxItem.Info> {
024    /**
025     * An array of all possible folder fields that can be requested when calling {@link #getInfo()}.
026     */
027    public static final String[] ALL_FIELDS = {"type", "id", "sequence_id", "etag", "name", "created_at", "modified_at",
028        "description", "size", "path_collection", "created_by", "modified_by", "trashed_at", "purged_at",
029        "content_created_at", "content_modified_at", "owned_by", "shared_link", "folder_upload_email", "parent",
030        "item_status", "item_collection", "sync_state", "has_collaborations", "permissions", "tags",
031        "can_non_owners_invite"};
032
033    private static final URLTemplate CREATE_FOLDER_URL = new URLTemplate("folders");
034    private static final URLTemplate COPY_FOLDER_URL = new URLTemplate("folders/%s/copy");
035    private static final URLTemplate DELETE_FOLDER_URL = new URLTemplate("folders/%s?recursive=%b");
036    private static final URLTemplate FOLDER_INFO_URL_TEMPLATE = new URLTemplate("folders/%s");
037    private static final URLTemplate UPLOAD_FILE_URL = new URLTemplate("files/content");
038    private static final URLTemplate ADD_COLLABORATION_URL = new URLTemplate("collaborations");
039    private static final URLTemplate GET_COLLABORATIONS_URL = new URLTemplate("folders/%s/collaborations");
040    private static final URLTemplate GET_ITEMS_URL = new URLTemplate("folders/%s/items/");
041    private static final URLTemplate SEARCH_URL_TEMPLATE = new URLTemplate("search");
042
043    /**
044     * Constructs a BoxFolder for a folder with a given ID.
045     * @param  api the API connection to be used by the folder.
046     * @param  id  the ID of the folder.
047     */
048    public BoxFolder(BoxAPIConnection api, String id) {
049        super(api, id);
050    }
051
052    /**
053     * Gets the current user's root folder.
054     * @param  api the API connection to be used by the folder.
055     * @return     the user's root folder.
056     */
057    public static BoxFolder getRootFolder(BoxAPIConnection api) {
058        return new BoxFolder(api, "0");
059    }
060
061    /**
062     * Adds a collaborator to this folder.
063     * @param  collaborator the collaborator to add.
064     * @param  role         the role of the collaborator.
065     * @return              info about the new collaboration.
066     */
067    public BoxCollaboration.Info collaborate(BoxCollaborator collaborator, BoxCollaboration.Role role) {
068        JsonObject accessibleByField = new JsonObject();
069        accessibleByField.add("id", collaborator.getID());
070
071        if (collaborator instanceof BoxUser) {
072            accessibleByField.add("type", "user");
073        } else {
074            throw new IllegalArgumentException("The given collaborator is of an unknown type.");
075        }
076
077        return this.collaborate(accessibleByField, role);
078    }
079
080    /**
081     * Adds a collaborator to this folder. An email will be sent to the collaborator if they don't already have a Box
082     * account.
083     * @param  email the email address of the collaborator to add.
084     * @param  role  the role of the collaborator.
085     * @return       info about the new collaboration.
086     */
087    public BoxCollaboration.Info collaborate(String email, BoxCollaboration.Role role) {
088        JsonObject accessibleByField = new JsonObject();
089        accessibleByField.add("login", email);
090        accessibleByField.add("type", "user");
091
092        return this.collaborate(accessibleByField, role);
093    }
094
095    private BoxCollaboration.Info collaborate(JsonObject accessibleByField, BoxCollaboration.Role role) {
096        BoxAPIConnection api = this.getAPI();
097        URL url = ADD_COLLABORATION_URL.build(api.getBaseURL());
098
099        JsonObject itemField = new JsonObject();
100        itemField.add("id", this.getID());
101        itemField.add("type", "folder");
102
103        JsonObject requestJSON = new JsonObject();
104        requestJSON.add("item", itemField);
105        requestJSON.add("accessible_by", accessibleByField);
106        requestJSON.add("role", role.toJSONString());
107
108        BoxJSONRequest request = new BoxJSONRequest(api, url, "POST");
109        request.setBody(requestJSON.toString());
110        BoxJSONResponse response = (BoxJSONResponse) request.send();
111        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
112
113        BoxCollaboration newCollaboration = new BoxCollaboration(api, responseJSON.get("id").asString());
114        BoxCollaboration.Info info = newCollaboration.new Info(responseJSON);
115        return info;
116    }
117
118    @Override
119    public BoxSharedLink createSharedLink(BoxSharedLink.Access access, Date unshareDate,
120        BoxSharedLink.Permissions permissions) {
121
122        BoxSharedLink sharedLink = new BoxSharedLink(access, unshareDate, permissions);
123        Info info = new Info();
124        info.setSharedLink(sharedLink);
125
126        this.updateInfo(info);
127        return info.getSharedLink();
128    }
129
130    /**
131     * Gets information about all of the collaborations for this folder.
132     * @return a collection of information about the collaborations for this folder.
133     */
134    public Collection<BoxCollaboration.Info> getCollaborations() {
135        BoxAPIConnection api = this.getAPI();
136        URL url = GET_COLLABORATIONS_URL.build(api.getBaseURL(), this.getID());
137
138        BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
139        BoxJSONResponse response = (BoxJSONResponse) request.send();
140        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
141
142        int entriesCount = responseJSON.get("total_count").asInt();
143        Collection<BoxCollaboration.Info> collaborations = new ArrayList<BoxCollaboration.Info>(entriesCount);
144        JsonArray entries = responseJSON.get("entries").asArray();
145        for (JsonValue entry : entries) {
146            JsonObject entryObject = entry.asObject();
147            BoxCollaboration collaboration = new BoxCollaboration(api, entryObject.get("id").asString());
148            BoxCollaboration.Info info = collaboration.new Info(entryObject);
149            collaborations.add(info);
150        }
151
152        return collaborations;
153    }
154
155    @Override
156    public BoxFolder.Info getInfo() {
157        URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
158        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
159        BoxJSONResponse response = (BoxJSONResponse) request.send();
160        return new Info(response.getJSON());
161    }
162
163    @Override
164    public BoxFolder.Info getInfo(String... fields) {
165        String queryString = new QueryStringBuilder().appendParam("fields", fields).toString();
166        URL url = FOLDER_INFO_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID());
167
168        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
169        BoxJSONResponse response = (BoxJSONResponse) request.send();
170        return new Info(response.getJSON());
171    }
172
173    /**
174     * Updates the information about this folder with any info fields that have been modified locally.
175     * @param info the updated info.
176     */
177    public void updateInfo(BoxFolder.Info info) {
178        URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
179        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
180        request.setBody(info.getPendingChanges());
181        BoxJSONResponse response = (BoxJSONResponse) request.send();
182        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
183        info.update(jsonObject);
184    }
185
186    @Override
187    public BoxFolder.Info copy(BoxFolder destination) {
188        return this.copy(destination, null);
189    }
190
191    @Override
192    public BoxFolder.Info copy(BoxFolder destination, String newName) {
193        URL url = COPY_FOLDER_URL.build(this.getAPI().getBaseURL(), this.getID());
194        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");
195
196        JsonObject parent = new JsonObject();
197        parent.add("id", destination.getID());
198
199        JsonObject copyInfo = new JsonObject();
200        copyInfo.add("parent", parent);
201        if (newName != null) {
202            copyInfo.add("name", newName);
203        }
204
205        request.setBody(copyInfo.toString());
206        BoxJSONResponse response = (BoxJSONResponse) request.send();
207        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
208        BoxFolder copiedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString());
209        return copiedFolder.new Info(responseJSON);
210    }
211
212    /**
213     * Creates a new child folder inside this folder.
214     * @param  name the new folder's name.
215     * @return      the created folder's info.
216     */
217    public BoxFolder.Info createFolder(String name) {
218        JsonObject parent = new JsonObject();
219        parent.add("id", this.getID());
220
221        JsonObject newFolder = new JsonObject();
222        newFolder.add("name", name);
223        newFolder.add("parent", parent);
224
225        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), CREATE_FOLDER_URL.build(this.getAPI().getBaseURL()),
226            "POST");
227        request.setBody(newFolder.toString());
228        BoxJSONResponse response = (BoxJSONResponse) request.send();
229        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
230
231        BoxFolder createdFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString());
232        return createdFolder.new Info(responseJSON);
233    }
234
235    /**
236     * Deletes this folder, optionally recursively deleting all of its contents.
237     * @param recursive true to recursively delete this folder's contents; otherwise false.
238     */
239    public void delete(boolean recursive) {
240        URL url = DELETE_FOLDER_URL.build(this.getAPI().getBaseURL(), this.getID(), recursive);
241        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
242        BoxAPIResponse response = request.send();
243        response.disconnect();
244    }
245
246    @Override
247    public BoxItem.Info move(BoxFolder destination) {
248        return this.move(destination, null);
249    }
250
251    @Override
252    public BoxItem.Info move(BoxFolder destination, String newName) {
253        URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
254        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
255
256        JsonObject parent = new JsonObject();
257        parent.add("id", destination.getID());
258
259        JsonObject updateInfo = new JsonObject();
260        updateInfo.add("parent", parent);
261        if (newName != null) {
262            updateInfo.add("name", newName);
263        }
264
265        request.setBody(updateInfo.toString());
266        BoxJSONResponse response = (BoxJSONResponse) request.send();
267        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
268        BoxFolder movedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString());
269        return movedFolder.new Info(responseJSON);
270    }
271
272    /**
273     * Renames this folder.
274     * @param newName the new name of the folder.
275     */
276    public void rename(String newName) {
277        URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
278        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
279
280        JsonObject updateInfo = new JsonObject();
281        updateInfo.add("name", newName);
282
283        request.setBody(updateInfo.toString());
284        BoxAPIResponse response = request.send();
285        response.disconnect();
286    }
287
288    /**
289     * Uploads a new file to this folder.
290     * @param  fileContent a stream containing the contents of the file to upload.
291     * @param  name        the name to give the uploaded file.
292     * @return             the uploaded file's info.
293     */
294    public BoxFile.Info uploadFile(InputStream fileContent, String name) {
295        FileUploadParams uploadInfo = new FileUploadParams()
296            .setContent(fileContent)
297            .setName(name);
298        return this.uploadFile(uploadInfo);
299    }
300
301    /**
302     * Uploads a new file to this folder while reporting the progress to a ProgressListener.
303     * @param  fileContent a stream containing the contents of the file to upload.
304     * @param  name        the name to give the uploaded file.
305     * @param  fileSize    the size of the file used for determining the progress of the upload.
306     * @param  listener    a listener for monitoring the upload's progress.
307     * @return             the uploaded file's info.
308     */
309    public BoxFile.Info uploadFile(InputStream fileContent, String name, long fileSize, ProgressListener listener) {
310        FileUploadParams uploadInfo = new FileUploadParams()
311            .setContent(fileContent)
312            .setName(name)
313            .setSize(fileSize)
314            .setProgressListener(listener);
315        return this.uploadFile(uploadInfo);
316    }
317
318    /**
319     * Uploads a new file to this folder with custom upload parameters.
320     * @param  uploadParams the custom upload parameters.
321     * @return              the uploaded file's info.
322     */
323    public BoxFile.Info uploadFile(FileUploadParams uploadParams) {
324        URL uploadURL = UPLOAD_FILE_URL.build(this.getAPI().getBaseUploadURL());
325        BoxMultipartRequest request = new BoxMultipartRequest(getAPI(), uploadURL);
326        request.putField("parent_id", getID());
327
328        if (uploadParams.getSize() > 0) {
329            request.setFile(uploadParams.getContent(), uploadParams.getName(), uploadParams.getSize());
330        } else {
331            request.setFile(uploadParams.getContent(), uploadParams.getName());
332        }
333
334        if (uploadParams.getCreated() != null) {
335            request.putField("content_created_at", uploadParams.getCreated());
336        }
337
338        if (uploadParams.getModified() != null) {
339            request.putField("content_modified_at", uploadParams.getModified());
340        }
341
342        BoxJSONResponse response;
343        if (uploadParams.getProgressListener() == null) {
344            response = (BoxJSONResponse) request.send();
345        } else {
346            response = (BoxJSONResponse) request.send(uploadParams.getProgressListener());
347        }
348        JsonObject collection = JsonObject.readFrom(response.getJSON());
349        JsonArray entries = collection.get("entries").asArray();
350        JsonObject fileInfoJSON = entries.get(0).asObject();
351        String uploadedFileID = fileInfoJSON.get("id").asString();
352
353        BoxFile uploadedFile = new BoxFile(getAPI(), uploadedFileID);
354        return uploadedFile.new Info(fileInfoJSON);
355    }
356
357    /**
358     * Returns an iterable containing the items in this folder. Iterating over the iterable returned by this method is
359     * equivalent to iterating over this BoxFolder directly.
360     * @return an iterable containing the items in this folder.
361     */
362    public Iterable<BoxItem.Info> getChildren() {
363        return this;
364    }
365
366    /**
367     * Returns an iterable containing the items in this folder and specifies which child fields to retrieve from the
368     * API.
369     * @param  fields the fields to retrieve.
370     * @return        an iterable containing the items in this folder.
371     */
372    public Iterable<BoxItem.Info> getChildren(final String... fields) {
373        return new Iterable<BoxItem.Info>() {
374            public Iterator<BoxItem.Info> iterator() {
375                String queryString = new QueryStringBuilder().appendParam("fields", fields).toString();
376                URL url = GET_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), queryString, getID());
377                return new BoxItemIterator(getAPI(), url);
378            }
379        };
380    }
381
382    /**
383     * Retrieves a specific range of child items in this folder.
384     * @param  offset the index of the first child item to retrieve.
385     * @param  limit  the maximum number of children to retrieve after the offset.
386     * @param  fields the fields to retrieve.
387     * @return        a partial collection containing the specified range of child items.
388     */
389    public PartialCollection<BoxItem.Info> getChildrenRange(long offset, long limit, String... fields) {
390        QueryStringBuilder builder = new QueryStringBuilder()
391            .appendParam("limit", limit)
392            .appendParam("offset", offset);
393
394        if (fields.length > 0) {
395            builder.appendParam("fields", fields).toString();
396        }
397
398        URL url = GET_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), builder.toString(), getID());
399        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
400        BoxJSONResponse response = (BoxJSONResponse) request.send();
401        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
402
403        String totalCountString = responseJSON.get("total_count").toString();
404        long fullSize = Double.valueOf(totalCountString).longValue();
405        PartialCollection<BoxItem.Info> children = new PartialCollection<BoxItem.Info>(offset, limit, fullSize);
406        JsonArray jsonArray = responseJSON.get("entries").asArray();
407        for (JsonValue value : jsonArray) {
408            JsonObject jsonObject = value.asObject();
409            BoxItem.Info parsedItemInfo = (BoxItem.Info) BoxResource.parseInfo(this.getAPI(), jsonObject);
410            if (parsedItemInfo != null) {
411                children.add(parsedItemInfo);
412            }
413        }
414        return children;
415    }
416
417    /**
418     * Returns an iterator over the items in this folder.
419     * @return an iterator over the items in this folder.
420     */
421    public Iterator<BoxItem.Info> iterator() {
422        URL url = GET_ITEMS_URL.build(this.getAPI().getBaseURL(), BoxFolder.this.getID());
423        return new BoxItemIterator(BoxFolder.this.getAPI(), url);
424    }
425
426    /**
427     * Searches this folder and all descendant folders using a given query.
428     * @param  query the search query.
429     * @return an Iterable containing the search results.
430     */
431    public Iterable<BoxItem.Info> search(final String query) {
432        return new Iterable<BoxItem.Info>() {
433            public Iterator<BoxItem.Info> iterator() {
434                QueryStringBuilder builder = new QueryStringBuilder();
435                builder.appendParam("query", query);
436                builder.appendParam("ancestor_folder_ids", getID());
437
438                URL url = SEARCH_URL_TEMPLATE.buildWithQuery(getAPI().getBaseURL(), builder.toString());
439                return new BoxItemIterator(getAPI(), url);
440            }
441        };
442    }
443
444    /**
445     * Contains information about a BoxFolder.
446     */
447    public class Info extends BoxItem.Info {
448        private BoxUploadEmail uploadEmail;
449        private boolean hasCollaborations;
450        private SyncState syncState;
451        private EnumSet<Permission> permissions;
452        private boolean canNonOwnersInvite;
453
454        /**
455         * Constructs an empty Info object.
456         */
457        public Info() {
458            super();
459        }
460
461        /**
462         * Constructs an Info object by parsing information from a JSON string.
463         * @param  json the JSON string to parse.
464         */
465        public Info(String json) {
466            super(json);
467        }
468
469        /**
470         * Constructs an Info object using an already parsed JSON object.
471         * @param  jsonObject the parsed JSON object.
472         */
473        Info(JsonObject jsonObject) {
474            super(jsonObject);
475        }
476
477        /**
478         * Gets the upload email for the folder.
479         * @return the upload email for the folder.
480         */
481        public BoxUploadEmail getUploadEmail() {
482            return this.uploadEmail;
483        }
484
485        /**
486         * Sets the upload email for the folder.
487         * @param uploadEmail the upload email for the folder.
488         */
489        public void setUploadEmail(BoxUploadEmail uploadEmail) {
490            if (this.uploadEmail == uploadEmail) {
491                return;
492            }
493
494            this.removeChildObject("folder_upload_email");
495            this.uploadEmail = uploadEmail;
496
497            if (uploadEmail == null) {
498                this.addPendingChange("folder_upload_email", null);
499            } else {
500                this.addChildObject("folder_upload_email", uploadEmail);
501            }
502        }
503
504        /**
505         * Gets whether or not the folder has any collaborations.
506         * @return true if the folder has collaborations; otherwise false.
507         */
508        public boolean getHasCollaborations() {
509            return this.hasCollaborations;
510        }
511
512        /**
513         * Gets the sync state of the folder.
514         * @return the sync state of the folder.
515         */
516        public SyncState getSyncState() {
517            return this.syncState;
518        }
519
520        /**
521         * Sets the sync state of the folder.
522         * @param syncState the sync state of the folder.
523         */
524        public void setSyncState(SyncState syncState) {
525            this.syncState = syncState;
526            this.addPendingChange("sync_state", syncState.toJSONValue());
527        }
528
529        /**
530         * Gets the permissions that the current user has on the folder.
531         * @return the permissions that the current user has on the folder.
532         */
533        public EnumSet<Permission> getPermissions() {
534            return this.permissions;
535        }
536
537        /**
538         * Gets whether or not the non-owners can invite collaborators to the folder.
539         * @return [description]
540         */
541        public boolean getCanNonOwnersInvite() {
542            return this.canNonOwnersInvite;
543        }
544
545        @Override
546        public BoxFolder getResource() {
547            return BoxFolder.this;
548        }
549
550        @Override
551        protected void parseJSONMember(JsonObject.Member member) {
552            super.parseJSONMember(member);
553
554            String memberName = member.getName();
555            JsonValue value = member.getValue();
556            switch (memberName) {
557                case "folder_upload_email":
558                    if (this.uploadEmail == null) {
559                        this.uploadEmail = new BoxUploadEmail(value.asObject());
560                    } else {
561                        this.uploadEmail.update(value.asObject());
562                    }
563                    break;
564                case "has_collaborations":
565                    this.hasCollaborations = value.asBoolean();
566                    break;
567                case "sync_state":
568                    this.syncState = SyncState.fromJSONValue(value.asString());
569                    break;
570                case "permissions":
571                    this.permissions = this.parsePermissions(value.asObject());
572                    break;
573                case "can_non_owners_invite":
574                    this.canNonOwnersInvite = value.asBoolean();
575                    break;
576                default:
577                    break;
578            }
579        }
580
581        private EnumSet<Permission> parsePermissions(JsonObject jsonObject) {
582            EnumSet<Permission> permissions = EnumSet.noneOf(Permission.class);
583            for (JsonObject.Member member : jsonObject) {
584                JsonValue value = member.getValue();
585                if (value.isNull() || !value.asBoolean()) {
586                    continue;
587                }
588
589                String memberName = member.getName();
590                switch (memberName) {
591                    case "can_download":
592                        permissions.add(Permission.CAN_DOWNLOAD);
593                        break;
594                    case "can_upload":
595                        permissions.add(Permission.CAN_UPLOAD);
596                        break;
597                    case "can_rename":
598                        permissions.add(Permission.CAN_RENAME);
599                        break;
600                    case "can_delete":
601                        permissions.add(Permission.CAN_DELETE);
602                        break;
603                    case "can_share":
604                        permissions.add(Permission.CAN_SHARE);
605                        break;
606                    case "can_invite_collaborator":
607                        permissions.add(Permission.CAN_INVITE_COLLABORATOR);
608                        break;
609                    case "can_set_share_access":
610                        permissions.add(Permission.CAN_SET_SHARE_ACCESS);
611                        break;
612                    default:
613                        break;
614                }
615            }
616
617            return permissions;
618        }
619    }
620
621    /**
622     * Enumerates the possible sync states that a folder can have.
623     */
624    public enum SyncState {
625        /**
626         * The folder is synced.
627         */
628        SYNCED ("synced"),
629
630        /**
631         * The folder is not synced.
632         */
633        NOT_SYNCED ("not_synced"),
634
635        /**
636         * The folder is partially synced.
637         */
638        PARTIALLY_SYNCED ("partially_synced");
639
640        private final String jsonValue;
641
642        private SyncState(String jsonValue) {
643            this.jsonValue = jsonValue;
644        }
645
646        static SyncState fromJSONValue(String jsonValue) {
647            return SyncState.valueOf(jsonValue.toUpperCase());
648        }
649
650        String toJSONValue() {
651            return this.jsonValue;
652        }
653    }
654
655    /**
656     * Enumerates the possible permissions that a user can have on a folder.
657     */
658    public enum Permission {
659        /**
660         * The user can download the folder.
661         */
662        CAN_DOWNLOAD ("can_download"),
663
664        /**
665         * The user can upload to the folder.
666         */
667        CAN_UPLOAD ("can_upload"),
668
669        /**
670         * The user can rename the folder.
671         */
672        CAN_RENAME ("can_rename"),
673
674        /**
675         * The user can delete the folder.
676         */
677        CAN_DELETE ("can_delete"),
678
679        /**
680         * The user can share the folder.
681         */
682        CAN_SHARE ("can_share"),
683
684        /**
685         * The user can invite collaborators to the folder.
686         */
687        CAN_INVITE_COLLABORATOR ("can_invite_collaborator"),
688
689        /**
690         * The user can set the access level for shared links to the folder.
691         */
692        CAN_SET_SHARE_ACCESS ("can_set_share_access");
693
694        private final String jsonValue;
695
696        private Permission(String jsonValue) {
697            this.jsonValue = jsonValue;
698        }
699
700        static Permission fromJSONValue(String jsonValue) {
701            return Permission.valueOf(jsonValue.toUpperCase());
702        }
703
704        String toJSONValue() {
705            return this.jsonValue;
706        }
707    }
708}