001package com.box.sdk;
002
003import java.net.URL;
004import java.util.ArrayList;
005import java.util.Collection;
006import java.util.Iterator;
007import java.util.List;
008
009import com.eclipsesource.json.JsonArray;
010import com.eclipsesource.json.JsonObject;
011import com.eclipsesource.json.JsonValue;
012
013/**
014 * Represents a Box user account.
015 *
016 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked
017 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error
018 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p>
019 */
020@BoxResourceType("user")
021public class BoxUser extends BoxCollaborator {
022
023    /**
024     * An array of all possible file fields that can be requested when calling {@link #getInfo(String...)}.
025     */
026    public static final String[] ALL_FIELDS = {"type", "id", "name", "login", "created_at", "modified_at", "role",
027        "language", "timezone", "space_amount", "space_used", "max_upload_size", "tracking_codes",
028        "can_see_managed_users", "is_sync_enabled", "is_external_collab_restricted", "status", "job_title", "phone",
029        "address", "avatar_url", "is_exempt_from_device_limits", "is_exempt_from_login_verification", "enterprise",
030        "my_tags", "hostname", "is_platform_access_only", "external_app_user_id"};
031
032    /**
033     * User URL Template.
034     */
035    public static final URLTemplate USER_URL_TEMPLATE = new URLTemplate("users/%s");
036    /**
037     * Get Me URL Template.
038     */
039    public static final URLTemplate GET_ME_URL = new URLTemplate("users/me");
040    /**
041     * Users URL Template.
042     */
043    public static final URLTemplate USERS_URL_TEMPLATE = new URLTemplate("users");
044    /**
045     * User Memberships URL Template.
046     */
047    public static final URLTemplate USER_MEMBERSHIPS_URL_TEMPLATE = new URLTemplate("users/%s/memberships");
048    /**
049     * E-Mail Alias URL Template.
050     */
051    public static final URLTemplate EMAIL_ALIAS_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases/%s");
052    /**
053     * E-Mail Aliases URL Template.
054     */
055    public static final URLTemplate EMAIL_ALIASES_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases");
056    /**
057     * Move Folder To User Template.
058     */
059    public static final URLTemplate MOVE_FOLDER_TO_USER_TEMPLATE = new URLTemplate("users/%s/folders/%s");
060
061    /**
062     * Constructs a BoxUser for a user with a given ID.
063     * @param  api the API connection to be used by the user.
064     * @param  id  the ID of the user.
065     */
066    public BoxUser(BoxAPIConnection api, String id) {
067        super(api, id);
068    }
069
070    /**
071     * Provisions a new app user in an enterprise using Box Developer Edition.
072     * @param  api   the API connection to be used by the created user.
073     * @param  name  the name of the user.
074     * @return       the created user's info.
075     */
076    public static BoxUser.Info createAppUser(BoxAPIConnection api, String name) {
077        return createAppUser(api, name, new CreateUserParams());
078    }
079
080    /**
081     * Provisions a new app user in an enterprise with additional user information using Box Developer Edition.
082     * @param  api    the API connection to be used by the created user.
083     * @param  name   the name of the user.
084     * @param  params additional user information.
085     * @return        the created user's info.
086     */
087    public static BoxUser.Info createAppUser(BoxAPIConnection api, String name,
088        CreateUserParams params) {
089
090        params.setIsPlatformAccessOnly(true);
091        return createEnterpriseUser(api, null, name, params);
092    }
093
094    /**
095     * Provisions a new user in an enterprise.
096     * @param  api   the API connection to be used by the created user.
097     * @param  login the email address the user will use to login.
098     * @param  name  the name of the user.
099     * @return       the created user's info.
100     */
101    public static BoxUser.Info createEnterpriseUser(BoxAPIConnection api, String login, String name) {
102        return createEnterpriseUser(api, login, name, null);
103    }
104
105    /**
106     * Provisions a new user in an enterprise with additional user information.
107     * @param  api    the API connection to be used by the created user.
108     * @param  login  the email address the user will use to login.
109     * @param  name   the name of the user.
110     * @param  params additional user information.
111     * @return        the created user's info.
112     */
113    public static BoxUser.Info createEnterpriseUser(BoxAPIConnection api, String login, String name,
114        CreateUserParams params) {
115
116        JsonObject requestJSON = new JsonObject();
117        requestJSON.add("login", login);
118        requestJSON.add("name", name);
119
120        if (params != null) {
121            if (params.getRole() != null) {
122                requestJSON.add("role", params.getRole().toJSONValue());
123            }
124
125            if (params.getStatus() != null) {
126                requestJSON.add("status", params.getStatus().toJSONValue());
127            }
128
129            requestJSON.add("language", params.getLanguage());
130            requestJSON.add("is_sync_enabled", params.getIsSyncEnabled());
131            requestJSON.add("job_title", params.getJobTitle());
132            requestJSON.add("phone", params.getPhone());
133            requestJSON.add("address", params.getAddress());
134            requestJSON.add("space_amount", params.getSpaceAmount());
135            requestJSON.add("can_see_managed_users", params.getCanSeeManagedUsers());
136            requestJSON.add("timezone", params.getTimezone());
137            requestJSON.add("is_exempt_from_device_limits", params.getIsExemptFromDeviceLimits());
138            requestJSON.add("is_exempt_from_login_verification", params.getIsExemptFromLoginVerification());
139            requestJSON.add("is_platform_access_only", params.getIsPlatformAccessOnly());
140            requestJSON.add("external_app_user_id", params.getExternalAppUserId());
141        }
142
143        URL url = USERS_URL_TEMPLATE.build(api.getBaseURL());
144        BoxJSONRequest request = new BoxJSONRequest(api, url, "POST");
145        request.setBody(requestJSON.toString());
146        BoxJSONResponse response = (BoxJSONResponse) request.send();
147        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
148
149        BoxUser createdUser = new BoxUser(api, responseJSON.get("id").asString());
150        return createdUser.new Info(responseJSON);
151    }
152
153    /**
154     * Gets the current user.
155     * @param  api the API connection of the current user.
156     * @return     the current user.
157     */
158    public static BoxUser getCurrentUser(BoxAPIConnection api) {
159        URL url = GET_ME_URL.build(api.getBaseURL());
160        BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
161        BoxJSONResponse response = (BoxJSONResponse) request.send();
162        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
163        return new BoxUser(api, jsonObject.get("id").asString());
164    }
165
166    /**
167     * Returns an iterable containing all the enterprise users.
168     * @param  api the API connection to be used when retrieving the users.
169     * @return     an iterable containing all the enterprise users.
170     */
171    public static Iterable<BoxUser.Info> getAllEnterpriseUsers(final BoxAPIConnection api) {
172        return getAllEnterpriseUsers(api, null);
173    }
174
175    /**
176     * Returns an iterable containing all the enterprise users that matches the filter and specifies which child fields
177     * to retrieve from the API.
178     * @param  api        the API connection to be used when retrieving the users.
179     * @param  filterTerm used to filter the results to only users starting with this string in either the name or the
180     *                    login. Can be null to not filter the results.
181     * @param  fields     the fields to retrieve. Leave this out for the standard fields.
182     * @return            an iterable containing all the enterprise users that matches the filter.
183     */
184    public static Iterable<BoxUser.Info> getAllEnterpriseUsers(final BoxAPIConnection api, final String filterTerm,
185            final String... fields) {
186        return getUsersInfoForType(api, filterTerm, null, null, fields);
187    }
188
189    /**
190     * Gets a limited set of information about an external user. (A user collaborating
191     * on content owned by the enterprise). Note: Only fields the user has permission to
192     * see will be returned with values. Other fields will return a value of null.
193     * @param  api        the API connection to be used when retrieving the users.
194     * @param  filterTerm used to filter the results to only users matching the given login.
195     *                    This does exact match only, so if no filter term is passed in, nothing
196     *                    will be returned.
197     * @param  fields     the fields to retrieve. Leave this out for the standard fields.
198     * @return an iterable containing external users matching the given email
199     */
200    public static Iterable<BoxUser.Info> getExternalUsers(final BoxAPIConnection api, final String filterTerm,
201          final String... fields) {
202        return getUsersInfoForType(api, filterTerm, "external", null, fields);
203    }
204
205    /**
206     * Gets any managed users that match the filter term as well as any external users that
207     * match the filter term. For managed users it matches any users names or emails that
208     * start with the term. For external, it only does full match on email. This method
209     * is ideal to use in the case where you have a full email for a user and you don't
210     * know if they're managed or external.
211     * @param  api        the API connection to be used when retrieving the users.
212     * @param filterTerm    The filter term to lookup users by (login for external, login or name for managed)
213     * @param fields        the fields to retrieve. Leave this out for the standard fields.
214     * @return an iterable containing users matching the given email
215     */
216    public static Iterable<BoxUser.Info> getAllEnterpriseOrExternalUsers(final BoxAPIConnection api,
217           final String filterTerm, final String... fields) {
218        return getUsersInfoForType(api, filterTerm, "all", null, fields);
219    }
220
221    /**
222     * Gets any app users that has an exact match with the externalAppUserId term.
223     * @param api                 the API connection to be used when retrieving the users.
224     * @param externalAppUserId    the external app user id that has been set for app user
225     * @param fields               the fields to retrieve. Leave this out for the standard fields.
226     * @return an iterable containing users matching the given email
227     */
228    public static Iterable<BoxUser.Info> getAppUsersByExternalAppUserID(final BoxAPIConnection api,
229           final String externalAppUserId, final String... fields) {
230        return getUsersInfoForType(api, null, null, externalAppUserId, fields);
231    }
232
233    /**
234     * Helper method to abstract out the common logic from the various users methods.
235     *
236     * @param api               the API connection to be used when retrieving the users.
237     * @param filterTerm        The filter term to lookup users by (login for external, login or name for managed)
238     * @param userType          The type of users we want to search with this request.
239     *                          Valid values are 'managed' (enterprise users), 'external' or 'all'
240     * @param externalAppUserId the external app user id that has been set for an app user
241     * @param fields            the fields to retrieve. Leave this out for the standard fields.
242     * @return                  An iterator over the selected users.
243     */
244    private static Iterable<BoxUser.Info> getUsersInfoForType(final BoxAPIConnection api,
245          final String filterTerm, final String userType, final String externalAppUserId, final String... fields) {
246        return new Iterable<BoxUser.Info>() {
247            public Iterator<BoxUser.Info> iterator() {
248                QueryStringBuilder builder = new QueryStringBuilder();
249                if (filterTerm != null) {
250                    builder.appendParam("filter_term", filterTerm);
251                }
252                if (userType != null) {
253                    builder.appendParam("user_type", userType);
254                }
255                if (externalAppUserId != null) {
256                    builder.appendParam("external_app_user_id", externalAppUserId);
257                }
258                if (fields.length > 0) {
259                    builder.appendParam("fields", fields);
260                }
261                URL url = USERS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString());
262                return new BoxUserIterator(api, url);
263            }
264        };
265    }
266
267    /**
268     * Gets information about this user.
269     * @param  fields the optional fields to retrieve.
270     * @return        info about this user.
271     */
272    public BoxUser.Info getInfo(String... fields) {
273        URL url;
274        if (fields.length > 0) {
275            String queryString = new QueryStringBuilder().appendParam("fields", fields).toString();
276            url = USER_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID());
277        } else {
278            url = USER_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
279        }
280        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
281        BoxJSONResponse response = (BoxJSONResponse) request.send();
282        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
283        return new Info(jsonObject);
284    }
285
286    /**
287     * Gets information about all of the group memberships for this user.
288     * Does not support paging.
289     *
290     * <p>Note: This method is only available to enterprise admins.</p>
291     *
292     * @return a collection of information about the group memberships for this user.
293     */
294    public Collection<BoxGroupMembership.Info> getMemberships() {
295        BoxAPIConnection api = this.getAPI();
296        URL url = USER_MEMBERSHIPS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
297
298        BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
299        BoxJSONResponse response = (BoxJSONResponse) request.send();
300        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
301
302        int entriesCount = responseJSON.get("total_count").asInt();
303        Collection<BoxGroupMembership.Info> memberships = new ArrayList<BoxGroupMembership.Info>(entriesCount);
304        JsonArray entries = responseJSON.get("entries").asArray();
305        for (JsonValue entry : entries) {
306            JsonObject entryObject = entry.asObject();
307            BoxGroupMembership membership = new BoxGroupMembership(api, entryObject.get("id").asString());
308            BoxGroupMembership.Info info = membership.new Info(entryObject);
309            memberships.add(info);
310        }
311
312        return memberships;
313    }
314
315    /**
316     * Gets information about all of the group memberships for this user as iterable with paging support.
317     * @param fields the fields to retrieve.
318     * @return an iterable with information about the group memberships for this user.
319     */
320    public Iterable<BoxGroupMembership.Info> getAllMemberships(String ... fields) {
321        final QueryStringBuilder builder = new QueryStringBuilder();
322        if (fields.length > 0) {
323            builder.appendParam("fields", fields);
324        }
325        return new Iterable<BoxGroupMembership.Info>() {
326            public Iterator<BoxGroupMembership.Info> iterator() {
327                URL url = USER_MEMBERSHIPS_URL_TEMPLATE.buildWithQuery(
328                        BoxUser.this.getAPI().getBaseURL(), builder.toString(), BoxUser.this.getID());
329                return new BoxGroupMembershipIterator(BoxUser.this.getAPI(), url);
330            }
331        };
332    }
333
334    /**
335     * Adds a new email alias to this user's account.
336     * @param  email the email address to add as an alias.
337     * @return       the newly created email alias.
338     */
339    public EmailAlias addEmailAlias(String email) {
340        return this.addEmailAlias(email, false);
341    }
342
343    /**
344     * Adds a new email alias to this user's account and confirms it without user interaction.
345     * This functionality is only available for enterprise admins.
346     * @param email the email address to add as an alias.
347     * @param isConfirmed whether or not the email alias should be automatically confirmed.
348     * @return the newly created email alias.
349     */
350    public EmailAlias addEmailAlias(String email, boolean isConfirmed) {
351        URL url = EMAIL_ALIASES_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
352        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");
353
354        JsonObject requestJSON = new JsonObject()
355                .add("email", email);
356
357        if (isConfirmed) {
358            requestJSON.add("is_confirmed", isConfirmed);
359        }
360
361        request.setBody(requestJSON.toString());
362        BoxJSONResponse response = (BoxJSONResponse) request.send();
363        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
364        return new EmailAlias(responseJSON);
365    }
366
367    /**
368     * Deletes an email alias from this user's account.
369     *
370     * <p>The IDs of the user's email aliases can be found by calling {@link #getEmailAliases}.</p>
371     *
372     * @param emailAliasID the ID of the email alias to delete.
373     */
374    public void deleteEmailAlias(String emailAliasID) {
375        URL url = EMAIL_ALIAS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), emailAliasID);
376        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
377        BoxAPIResponse response = request.send();
378        response.disconnect();
379    }
380
381    /**
382     * Gets a collection of all the email aliases for this user.
383     *
384     * <p>Note that the user's primary login email is not included in the collection of email aliases.</p>
385     *
386     * @return a collection of all the email aliases for this user.
387     */
388    public Collection<EmailAlias> getEmailAliases() {
389        URL url = EMAIL_ALIASES_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
390        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
391        BoxJSONResponse response = (BoxJSONResponse) request.send();
392        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
393
394        int totalCount = responseJSON.get("total_count").asInt();
395        Collection<EmailAlias> emailAliases = new ArrayList<EmailAlias>(totalCount);
396        JsonArray entries = responseJSON.get("entries").asArray();
397        for (JsonValue value : entries) {
398            JsonObject emailAliasJSON = value.asObject();
399            emailAliases.add(new EmailAlias(emailAliasJSON));
400        }
401
402        return emailAliases;
403    }
404
405    /**
406     * Deletes a user from an enterprise account.
407     * @param notifyUser whether or not to send an email notification to the user that their account has been deleted.
408     * @param force      whether or not this user should be deleted even if they still own files.
409     */
410    public void delete(boolean notifyUser, boolean force) {
411        String queryString = new QueryStringBuilder()
412            .appendParam("notify", String.valueOf(notifyUser))
413            .appendParam("force", String.valueOf(force))
414            .toString();
415
416        URL url = USER_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID());
417        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
418        BoxAPIResponse response = request.send();
419        response.disconnect();
420    }
421
422    /**
423     * Updates the information about this user with any info fields that have been modified locally.
424     *
425     * <p>Note: This method is only available to enterprise admins.</p>
426     *
427     * @param info info the updated info.
428     */
429    public void updateInfo(BoxUser.Info info) {
430        URL url = USER_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
431        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
432        request.setBody(info.getPendingChanges());
433        BoxJSONResponse response = (BoxJSONResponse) request.send();
434        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
435        info.update(jsonObject);
436    }
437
438    /**
439     * Moves all of the owned content from within one user’s folder into a new folder in another user's account.
440     * You can move folders across users as long as the you have administrative permissions and the 'source'
441     * user owns the folders. Per the documentation at the link below, this will move everything from the root
442     * folder, as this is currently the only mode of operation supported.
443     *
444     * See also https://box-content.readme.io/reference#move-folder-into-another-users-folder
445     *
446     * @param sourceUserID the user id of the user whose files will be the source for this operation
447     * @return info for the newly created folder
448     */
449    public BoxFolder.Info moveFolderToUser(String sourceUserID) {
450        // Currently the API only supports moving of the root folder (0), hence the hard coded "0"
451        URL url = MOVE_FOLDER_TO_USER_TEMPLATE.build(this.getAPI().getBaseURL(), sourceUserID, "0");
452        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
453        JsonObject idValue = new JsonObject();
454        idValue.add("id", this.getID());
455        JsonObject ownedBy = new JsonObject();
456        ownedBy.add("owned_by", idValue);
457        request.setBody(ownedBy.toString());
458        BoxJSONResponse response = (BoxJSONResponse) request.send();
459        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
460        BoxFolder movedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString());
461
462        return movedFolder.new Info(responseJSON);
463    }
464
465
466    /**
467     * Enumerates the possible roles that a user can have within an enterprise.
468     */
469    public enum Role {
470        /**
471         * The user is an administrator of their enterprise.
472         */
473        ADMIN ("admin"),
474
475        /**
476         * The user is a co-administrator of their enterprise.
477         */
478        COADMIN ("coadmin"),
479
480        /**
481         * The user is a regular user within their enterprise.
482         */
483        USER ("user");
484
485        private final String jsonValue;
486
487        private Role(String jsonValue) {
488            this.jsonValue = jsonValue;
489        }
490
491        static Role fromJSONValue(String jsonValue) {
492            return Role.valueOf(jsonValue.toUpperCase());
493        }
494
495        String toJSONValue() {
496            return this.jsonValue;
497        }
498    }
499
500    /**
501     * Enumerates the possible statuses that a user's account can have.
502     */
503    public enum Status {
504        /**
505         * The user's account is active.
506         */
507        ACTIVE ("active"),
508
509        /**
510         * The user's account is inactive.
511         */
512        INACTIVE ("inactive"),
513
514        /**
515         * The user's account cannot delete or edit content.
516         */
517        CANNOT_DELETE_EDIT ("cannot_delete_edit"),
518
519        /**
520         * The user's account cannot delete, edit, or upload content.
521         */
522        CANNOT_DELETE_EDIT_UPLOAD ("cannot_delete_edit_upload");
523
524        private final String jsonValue;
525
526        private Status(String jsonValue) {
527            this.jsonValue = jsonValue;
528        }
529
530        static Status fromJSONValue(String jsonValue) {
531            return Status.valueOf(jsonValue.toUpperCase());
532        }
533
534        String toJSONValue() {
535            return this.jsonValue;
536        }
537    }
538
539    /**
540     * Contains information about a BoxUser.
541     */
542    public class Info extends BoxCollaborator.Info {
543        private String login;
544        private Role role;
545        private String language;
546        private String timezone;
547        private long spaceAmount;
548        private long spaceUsed;
549        private long maxUploadSize;
550        private boolean canSeeManagedUsers;
551        private boolean isSyncEnabled;
552        private boolean isExternalCollabRestricted;
553        private Status status;
554        private String jobTitle;
555        private String phone;
556        private String address;
557        private String avatarURL;
558        private boolean isExemptFromDeviceLimits;
559        private boolean isExemptFromLoginVerification;
560        private boolean isPasswordResetRequired;
561        private boolean isPlatformAccessOnly;
562        private String externalAppUserId;
563        private BoxEnterprise enterprise;
564        private List<String> myTags;
565        private String hostname;
566
567        /**
568         * Constructs an empty Info object.
569         */
570        public Info() {
571            super();
572        }
573
574        Info(JsonObject jsonObject) {
575            super(jsonObject);
576        }
577
578        @Override
579        public BoxUser getResource() {
580            return BoxUser.this;
581        }
582
583        /**
584         * Gets the email address the user uses to login.
585         * @return the email address the user uses to login.
586         */
587        public String getLogin() {
588            return this.login;
589        }
590
591        /**
592         * Sets the email address the user uses to login. The new login must be one of the user's already confirmed
593         * email aliases.
594         * @param  login one of the user's confirmed email aliases.
595         */
596        public void setLogin(String login) {
597            this.login = login;
598            this.addPendingChange("login", login);
599        }
600
601        /**
602         * Gets the user's enterprise role.
603         * @return the user's enterprise role.
604         */
605        public Role getRole() {
606            return this.role;
607        }
608
609        /**
610         * Sets the user's role in their enterprise.
611         * @param role the user's new role in their enterprise.
612         */
613        public void setRole(Role role) {
614            this.role = role;
615            this.addPendingChange("role", role.name().toLowerCase());
616        }
617
618        /**
619         * Gets the language of the user.
620         * @return the language of the user.
621         */
622        public String getLanguage() {
623            return this.language;
624        }
625
626        /**
627         * Sets the language of the user.
628         * @param language the new language of the user.
629         */
630        public void setLanguage(String language) {
631            this.language = language;
632            this.addPendingChange("language", language);
633        }
634
635        /**
636         * Gets the timezone of the user.
637         * @return the timezone of the user.
638         */
639        public String getTimezone() {
640            return this.timezone;
641        }
642
643        /**
644         * Sets the timezone of the user.
645         * @param timezone the new timezone of the user.
646         */
647        public void setTimezone(String timezone) {
648            this.timezone = timezone;
649            this.addPendingChange("timezone", timezone);
650        }
651
652        /**
653         * Gets the user's total available space in bytes.
654         * @return the user's total available space in bytes.
655         */
656        public long getSpaceAmount() {
657            return this.spaceAmount;
658        }
659
660        /**
661         * Sets the user's total available space in bytes.
662         * @param spaceAmount the new amount of space available to the user in bytes, or -1 for unlimited storage.
663         */
664        public void setSpaceAmount(long spaceAmount) {
665            this.spaceAmount = spaceAmount;
666            this.addPendingChange("space_amount", spaceAmount);
667        }
668
669        /**
670         * Gets the amount of space the user has used in bytes.
671         * @return the amount of space the user has used in bytes.
672         */
673        public long getSpaceUsed() {
674            return this.spaceUsed;
675        }
676
677        /**
678         * Gets the maximum individual file size in bytes the user can have.
679         * @return the maximum individual file size in bytes the user can have.
680         */
681        public long getMaxUploadSize() {
682            return this.maxUploadSize;
683        }
684
685        /**
686         * Gets the user's current account status.
687         * @return the user's current account status.
688         */
689        public Status getStatus() {
690            return this.status;
691        }
692
693        /**
694         * Sets the user's current account status.
695         * @param status the user's new account status.
696         */
697        public void setStatus(Status status) {
698            this.status = status;
699            this.addPendingChange("status", status.name().toLowerCase());
700        }
701
702        /**
703         * Gets the job title of the user.
704         * @return the job title of the user.
705         */
706        public String getJobTitle() {
707            return this.jobTitle;
708        }
709
710        /**
711         * Sets the job title of the user.
712         * @param jobTitle the new job title of the user.
713         */
714        public void setJobTitle(String jobTitle) {
715            this.jobTitle = jobTitle;
716            this.addPendingChange("job_title", jobTitle);
717        }
718
719        /**
720         * Gets the phone number of the user.
721         * @return the phone number of the user.
722         */
723        public String getPhone() {
724            return this.phone;
725        }
726
727        /**
728         * Sets the phone number of the user.
729         * @param phone the new phone number of the user.
730         */
731        public void setPhone(String phone) {
732            this.phone = phone;
733            this.addPendingChange("phone", phone);
734        }
735
736        /**
737         * Gets the address of the user.
738         * @return the address of the user.
739         */
740        public String getAddress() {
741            return this.address;
742        }
743
744        /**
745         * Sets the address of the user.
746         * @param address the new address of the user.
747         */
748        public void setAddress(String address) {
749            this.address = address;
750            this.addPendingChange("address", address);
751        }
752
753        /**
754         * Gets the URL of the user's avatar.
755         * @return the URL of the user's avatar.
756         */
757        public String getAvatarURL() {
758            return this.avatarURL;
759        }
760
761        /**
762         * Gets the enterprise that the user belongs to.
763         * @return the enterprise that the user belongs to.
764         */
765        public BoxEnterprise getEnterprise() {
766            return this.enterprise;
767        }
768
769        /**
770         * Removes the user from their enterprise and converts them to a standalone free user.
771         */
772        public void removeEnterprise() {
773            this.removeChildObject("enterprise");
774            this.enterprise = null;
775            this.addChildObject("enterprise", null);
776        }
777
778        /**
779         * Gets whether or not the user can use Box Sync.
780         * @return true if the user can use Box Sync; otherwise false.
781         */
782        public boolean getIsSyncEnabled() {
783            return this.isSyncEnabled;
784        }
785
786        /**
787         * Gets whether this user is allowed to collaborate with users outside their enterprise.
788         * @return true if this user is allowed to collaborate with users outside their enterprise; otherwise false.
789         */
790        public boolean getIsExternalCollabRestricted() {
791            return this.isExternalCollabRestricted;
792        }
793
794        /**
795         * Sets whether or not the user can use Box Sync.
796         * @param enabled whether or not the user can use Box Sync.
797         */
798        public void setIsSyncEnabled(boolean enabled) {
799            this.isSyncEnabled = enabled;
800            this.addPendingChange("is_sync_enabled", enabled);
801        }
802
803        /**
804         * Gets whether or not the user can see other enterprise users in their contact list.
805         * @return true if the user can see other enterprise users in their contact list; otherwise false.
806         */
807        public boolean getCanSeeManagedUsers() {
808            return this.canSeeManagedUsers;
809        }
810
811        /**
812         * Sets whether or not the user can see other enterprise users in their contact list.
813         * @param canSeeManagedUsers whether or not the user can see other enterprise users in their contact list.
814         */
815        public void setCanSeeManagedUsers(boolean canSeeManagedUsers) {
816            this.canSeeManagedUsers = canSeeManagedUsers;
817            this.addPendingChange("can_see_managed_users", canSeeManagedUsers);
818        }
819
820        /**
821         * Gets whether or not the user is exempt from enterprise device limits.
822         * @return true if the user is exempt from enterprise device limits; otherwise false.
823         */
824        public boolean getIsExemptFromDeviceLimits() {
825            return this.isExemptFromDeviceLimits;
826        }
827
828        /**
829         * Sets whether or not the user is exempt from enterprise device limits.
830         * @param isExemptFromDeviceLimits whether or not the user is exempt from enterprise device limits.
831         */
832        public void setIsExemptFromDeviceLimits(boolean isExemptFromDeviceLimits) {
833            this.isExemptFromDeviceLimits = isExemptFromDeviceLimits;
834            this.addPendingChange("is_exempt_from_device_limits", isExemptFromDeviceLimits);
835        }
836
837        /**
838         * Gets whether or not the user must use two-factor authentication.
839         * @return true if the user must use two-factor authentication; otherwise false.
840         */
841        public boolean getIsExemptFromLoginVerification() {
842            return this.isExemptFromLoginVerification;
843        }
844
845        /**
846         * Sets whether or not the user must use two-factor authentication.
847         * @param isExemptFromLoginVerification whether or not the user must use two-factor authentication.
848         */
849        public void setIsExemptFromLoginVerification(boolean isExemptFromLoginVerification) {
850            this.isExemptFromLoginVerification = isExemptFromLoginVerification;
851            this.addPendingChange("is_exempt_from_login_verification", isExemptFromLoginVerification);
852        }
853
854        /**
855         * Gets whether or not the user is required to reset password.
856         * @return true if the user is required to reset password; otherwise false.
857         */
858        public boolean getIsPasswordResetRequired() {
859            return this.isPasswordResetRequired;
860        }
861
862        /**
863         * Sets whether or not the user is required to reset password.
864         * @param isPasswordResetRequired whether or not the user is required to reset password.
865         */
866        public void setIsPasswordResetRequired(boolean isPasswordResetRequired) {
867            this.isPasswordResetRequired = isPasswordResetRequired;
868            this.addPendingChange("is_password_reset_required", isPasswordResetRequired);
869        }
870
871        /**
872         * Gets whether or not the user we are creating is an app user with Box Developer Edition.
873         * @return true if the new user is an app user for Box Developer Addition; otherwise false.
874         */
875        public boolean getIsPlatformAccessOnly() {
876            return this.isPlatformAccessOnly;
877        }
878
879        /**
880         * Gets the external app user id that has been set for the app user.
881         * @return the external app user id.
882         */
883        public String getExternalAppUserId() {
884            return this.externalAppUserId;
885        }
886
887        /**
888         * Sets the external app user id.
889         * @param externalAppUserId external app user id.
890         */
891        public void setExternalAppUserId(String externalAppUserId) {
892            this.externalAppUserId = externalAppUserId;
893            this.addPendingChange("external_app_user_id", externalAppUserId);
894        }
895
896        /**
897         * Gets the tags for all files and folders owned by this user.
898         * @return the tags for all files and folders owned by this user.
899         */
900        public List<String> getMyTags() {
901            return this.myTags;
902        }
903
904        /**
905         * Gets the root (protocol, subdomain, domain) of any links that need to be generated for this user.
906         * @return the root (protocol, subdomain, domain) of any links that need to be generated for this user.
907         */
908        public String getHostname() {
909            return this.hostname;
910        }
911
912        @Override
913        protected void parseJSONMember(JsonObject.Member member) {
914            super.parseJSONMember(member);
915
916            JsonValue value = member.getValue();
917            String memberName = member.getName();
918            if (memberName.equals("login")) {
919                this.login = value.asString();
920            } else if (memberName.equals("role")) {
921                this.role = Role.fromJSONValue(value.asString());
922            } else if (memberName.equals("language")) {
923                this.language = value.asString();
924            } else if (memberName.equals("timezone")) {
925                this.timezone = value.asString();
926            } else if (memberName.equals("space_amount")) {
927                this.spaceAmount = Double.valueOf(value.toString()).longValue();
928            } else if (memberName.equals("space_used")) {
929                this.spaceUsed = Double.valueOf(value.toString()).longValue();
930            } else if (memberName.equals("max_upload_size")) {
931                this.maxUploadSize = Double.valueOf(value.toString()).longValue();
932            } else if (memberName.equals("status")) {
933                this.status = Status.fromJSONValue(value.asString());
934            } else if (memberName.equals("job_title")) {
935                this.jobTitle = value.asString();
936            } else if (memberName.equals("phone")) {
937                this.phone = value.asString();
938            } else if (memberName.equals("address")) {
939                this.address = value.asString();
940            } else if (memberName.equals("avatar_url")) {
941                this.avatarURL = value.asString();
942            } else if (memberName.equals("can_see_managed_users")) {
943                this.canSeeManagedUsers = value.asBoolean();
944            } else if (memberName.equals("is_sync_enabled")) {
945                this.isSyncEnabled = value.asBoolean();
946            } else if (memberName.equals("is_external_collab_restricted")) {
947                this.isExternalCollabRestricted = value.asBoolean();
948            } else if (memberName.equals("is_exempt_from_device_limits")) {
949                this.isExemptFromDeviceLimits = value.asBoolean();
950            } else if (memberName.equals("is_exempt_from_login_verification")) {
951                this.isExemptFromLoginVerification = value.asBoolean();
952            } else if (memberName.equals("is_password_reset_required")) {
953                this.isPasswordResetRequired = value.asBoolean();
954            } else if (memberName.equals("is_platform_access_only")) {
955                this.isPlatformAccessOnly = value.asBoolean();
956            } else if (memberName.equals("external_app_user_id")) {
957                this.externalAppUserId = value.asString();
958            } else if (memberName.equals("enterprise")) {
959                JsonObject jsonObject = value.asObject();
960                if (this.enterprise == null) {
961                    this.enterprise = new BoxEnterprise(jsonObject);
962                } else {
963                    this.enterprise.update(jsonObject);
964                }
965            } else if (memberName.equals("my_tags")) {
966                this.myTags = this.parseMyTags(value.asArray());
967            } else if (memberName.equals("hostname")) {
968                this.hostname = value.asString();
969            }
970        }
971
972        private List<String> parseMyTags(JsonArray jsonArray) {
973            List<String> myTags = new ArrayList<String>(jsonArray.size());
974            for (JsonValue value : jsonArray) {
975                myTags.add(value.asString());
976            }
977
978            return myTags;
979        }
980    }
981}