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