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