001package com.box.sdk;
002
003import com.eclipsesource.json.JsonObject;
004import com.eclipsesource.json.JsonValue;
005import java.util.Date;
006
007/**
008 * Represents a link to a file or folder on Box.
009 */
010public class BoxSharedLink extends BoxJSONObject {
011    private String url;
012    private String downloadUrl;
013    private String vanityUrl;
014    private String vanityName;
015    private boolean isPasswordEnabled;
016    private String password;
017    private Date unsharedAt;
018    private long downloadCount;
019    private long previewCount;
020    private Access access;
021    private Access effectiveAccess;
022    private Permissions permissions;
023
024    /**
025     * Constructs a BoxSharedLink with default settings.
026     */
027    public BoxSharedLink() {
028    }
029
030    /**
031     * Constructs a BoxSharedLink from a JSON string.
032     *
033     * @param json the JSON encoded shared link.
034     */
035    public BoxSharedLink(String json) {
036        super(json);
037    }
038
039    BoxSharedLink(JsonObject jsonObject) {
040        super(jsonObject);
041    }
042
043    BoxSharedLink(BoxSharedLink.Access access, Date unshareDate, BoxSharedLink.Permissions permissions) {
044        this.setAccess(access);
045        this.setPermissions(permissions);
046
047        if (unshareDate != null) {
048            this.setUnsharedDate(unshareDate);
049        }
050    }
051
052    BoxSharedLink(BoxSharedLink.Access access, Date unshareDate, BoxSharedLink.Permissions permissions,
053                  String password) {
054        this.setAccess(access);
055        this.setPermissions(permissions);
056        this.setPassword(password);
057
058        if (unshareDate != null) {
059            this.setUnsharedDate(unshareDate);
060        }
061    }
062
063    /**
064     * Get the URL of this shared link.
065     *
066     * @return the URL of this shared link.
067     */
068    public String getURL() {
069        return this.url;
070    }
071
072    /**
073     * Gets the direct download URL of this shared link.
074     *
075     * @return the direct download URL of this shared link.
076     */
077    public String getDownloadURL() {
078        return this.downloadUrl;
079    }
080
081    /**
082     * Gets the vanity URL of this shared link.
083     *
084     * @return the vanity URL of this shared link.
085     */
086    public String getVanityURL() {
087        return this.vanityUrl;
088    }
089
090    /**
091     * Returns vanity name used to create vanity URL.
092     *
093     * @return Vanity name
094     */
095    public String getVanityName() {
096        return vanityName;
097    }
098
099    /**
100     * Sets vanity name used to create vanity URL.
101     * For example:
102     * vanityName = myCustomName
103     * will produce vanityUrl as:
104     * https://app.box.com/v/myCustomName
105     * Custom URLs should not be used when sharing sensitive content
106     * as vanity URLs are a lot easier to guess than regular shared links.
107     *
108     * @param vanityName Vanity name. Vanity name must be at least 12 characters long.
109     */
110    public void setVanityName(String vanityName) {
111        if (vanityName != null && vanityName.length() < 12) {
112            throw new IllegalArgumentException("The vanityName has to be at least 12 characters long.");
113        }
114        this.vanityName = vanityName;
115        this.addPendingChange("vanity_name", vanityName);
116    }
117
118    /**
119     * Gets whether or not a password is enabled on this shared link.
120     *
121     * @return true if there's a password enabled on this shared link; otherwise false.
122     */
123    public boolean getIsPasswordEnabled() {
124        return this.isPasswordEnabled;
125    }
126
127    /**
128     * Gets the time that this shared link will be deactivated.
129     *
130     * @return the time that this shared link will be deactivated.
131     */
132    public Date getUnsharedDate() {
133        return this.unsharedAt;
134    }
135
136    /**
137     * Sets the time that this shared link will be deactivated.
138     *
139     * @param unsharedDate the time that this shared link will be deactivated.
140     */
141    public void setUnsharedDate(Date unsharedDate) {
142        this.unsharedAt = unsharedDate;
143        this.addPendingChange("unshared_at", BoxDateFormat.format(unsharedDate));
144    }
145
146    /**
147     * Gets the number of times that this shared link has been downloaded.
148     *
149     * @return the number of times that this link has been downloaded.
150     */
151    public long getDownloadCount() {
152        return this.downloadCount;
153    }
154
155    /**
156     * Gets the number of times that this shared link has been previewed.
157     *
158     * @return the number of times that this link has been previewed.
159     */
160    public long getPreviewCount() {
161        return this.previewCount;
162    }
163
164    /**
165     * Gets the access level of this shared link.
166     *
167     * @return the access level of this shared link.
168     */
169    public Access getAccess() {
170        return this.access;
171    }
172
173    /**
174     * Sets the access level of this shared link.
175     *
176     * @param access the new access level of this shared link.
177     */
178    public void setAccess(Access access) {
179        this.access = access;
180        this.addPendingChange("access", access.toJSONValue());
181    }
182
183    /**
184     * Sets the password of this shared link.
185     *
186     * @param password the password of this shared link.
187     */
188    public void setPassword(String password) {
189        this.password = password;
190        this.addPendingChange("password", password);
191    }
192
193    /**
194     * Gets the effective access level of this shared link.
195     *
196     * @return the effective access level of this shared link.
197     * <p>
198     * Note there is no setEffectiveAccess metho becaused this
199     * cannot be changed via the API
200     */
201    public Access getEffectiveAccess() {
202        return this.effectiveAccess;
203    }
204
205    /**
206     * Gets the permissions associated with this shared link.
207     *
208     * @return the permissions associated with this shared link.
209     */
210    public Permissions getPermissions() {
211        return this.permissions;
212    }
213
214    /**
215     * Sets the permissions associated with this shared link.
216     *
217     * @param permissions the new permissions for this shared link.
218     */
219    public void setPermissions(Permissions permissions) {
220        if (this.permissions != null && this.permissions.equals(permissions)) {
221            return;
222        }
223
224        this.removeChildObject("permissions");
225        this.permissions = permissions;
226        this.addChildObject("permissions", permissions);
227    }
228
229    private Access parseAccessValue(JsonValue value) {
230        String accessString = value.asString().toUpperCase();
231        return Access.valueOf(accessString);
232    }
233
234    @Override
235    void parseJSONMember(JsonObject.Member member) {
236        JsonValue value = member.getValue();
237        String memberName = member.getName();
238
239        try {
240            if (memberName.equals("url")) {
241                this.url = value.asString();
242            } else if (memberName.equals("download_url")) {
243                this.downloadUrl = value.asString();
244            } else if (memberName.equals("vanity_url")) {
245                this.vanityUrl = value.asString();
246            } else if (memberName.equals("vanity_name")) {
247                this.vanityName = value.asString();
248            } else if (memberName.equals("is_password_enabled")) {
249                this.isPasswordEnabled = value.asBoolean();
250            } else if (memberName.equals("unshared_at")) {
251                this.unsharedAt = BoxDateFormat.parse(value.asString());
252            } else if (memberName.equals("download_count")) {
253                this.downloadCount = Double.valueOf(value.toString()).longValue();
254            } else if (memberName.equals("preview_count")) {
255                this.previewCount = Double.valueOf(value.toString()).longValue();
256            } else if (memberName.equals("access")) {
257                this.access = this.parseAccessValue(value);
258            } else if (memberName.equals("effective_access")) {
259                this.effectiveAccess = this.parseAccessValue(value);
260            } else if (memberName.equals("permissions")) {
261                if (this.permissions == null) {
262                    this.setPermissions(new Permissions(value.asObject()));
263                } else {
264                    this.permissions.update(value.asObject());
265                }
266            }
267        } catch (Exception e) {
268            throw new BoxDeserializationException(memberName, value.toString(), e);
269        }
270    }
271
272    public static String getSharedLinkHeaderValue(String sharedLink, String password) {
273        String boxAPIValue = "shared_link=" + sharedLink;
274        if (password != null) {
275            boxAPIValue += "&shared_link_password=" + password;
276        }
277        return boxAPIValue;
278    }
279
280    /**
281     * Enumerates the possible access levels that can be set on a shared link.
282     */
283    public enum Access {
284        /**
285         * The default access level for the user or enterprise.
286         */
287        DEFAULT(null),
288
289        /**
290         * The link can be accessed by anyone.
291         */
292        OPEN("open"),
293
294        /**
295         * The link can be accessed by other users within the company.
296         */
297        COMPANY("company"),
298
299        /**
300         * The link can be accessed by other collaborators.
301         */
302        COLLABORATORS("collaborators");
303
304        private final String jsonValue;
305
306        Access(String jsonValue) {
307            this.jsonValue = jsonValue;
308        }
309
310        String toJSONValue() {
311            return this.jsonValue;
312        }
313    }
314
315    /**
316     * Contains permissions fields that can be set on a shared link.
317     */
318    public static class Permissions extends BoxJSONObject {
319        private boolean canDownload;
320        private boolean canPreview;
321        private boolean canEdit;
322
323        /**
324         * Constructs a Permissions object with all permissions disabled.
325         */
326        public Permissions() {
327        }
328
329        Permissions(boolean canPreview, boolean canDownload, boolean canEdit) {
330            this.setCanPreview(canPreview);
331            this.setCanDownload(canDownload);
332            this.setCanEdit(canEdit);
333        }
334
335        /**
336         * Constructs a Permissions object from a JSON string.
337         *
338         * @param json the JSON encoded shared link permissions.
339         */
340        public Permissions(String json) {
341            super(json);
342        }
343
344        Permissions(JsonObject jsonObject) {
345            super(jsonObject);
346        }
347
348        /**
349         * Gets whether the shared link can be downloaded.
350         *
351         * @return true if the shared link can be downloaded; otherwise false.
352         */
353        public boolean getCanDownload() {
354            return this.canDownload;
355        }
356
357        /**
358         * Sets whether or not the shared link can be downloaded.
359         *
360         * @param enabled true if the shared link can be downloaded; otherwise false.
361         */
362        public void setCanDownload(boolean enabled) {
363            this.canDownload = enabled;
364            this.addPendingChange("can_download", enabled);
365        }
366
367        /**
368         * Gets whether the shared link can be previewed.
369         *
370         * @return true if the shared link can be previewed; otherwise false.
371         */
372        public boolean getCanPreview() {
373            return this.canPreview;
374        }
375
376        /**
377         * Sets whether the shared link can be previewed.
378         *
379         * @param enabled true if the shared link can be previewed; otherwise false.
380         */
381        public void setCanPreview(boolean enabled) {
382            this.canPreview = enabled;
383            this.addPendingChange("can_preview", enabled);
384        }
385
386        /**
387         * Gets whether the shared link allows for editing of files.
388         *
389         * @return true if the shared link allows for editing of files; otherwise false.
390         */
391        public boolean getCanEdit() {
392            return canEdit;
393        }
394
395        /**
396         * Sets whether the shared link allows for editing of files.
397         * For folders this value will always be set to false.
398         *
399         * @param enabled true if the shared link allows for editing of files; otherwise false.
400         */
401        public void setCanEdit(boolean enabled) {
402            this.canEdit = enabled;
403            this.addPendingChange("can_edit", enabled);
404        }
405
406        @Override
407        void parseJSONMember(JsonObject.Member member) {
408            JsonValue value = member.getValue();
409            String memberName = member.getName();
410            if (memberName.equals("can_download")) {
411                this.canDownload = value.asBoolean();
412            }
413            if (memberName.equals("can_preview")) {
414                this.canPreview = value.asBoolean();
415            }
416            if (memberName.equals("can_edit")) {
417                this.canEdit = value.asBoolean();
418            }
419        }
420
421        @Override
422        public boolean equals(Object o) {
423            if (this == o) {
424                return true;
425            }
426            if (o == null || this.getClass() != o.getClass()) {
427                return false;
428            }
429
430            Permissions that = (Permissions) o;
431
432            return this.canDownload == that.canDownload
433                && this.canPreview == that.canPreview
434                && this.canEdit == that.canEdit;
435        }
436
437        @Override
438        public int hashCode() {
439            int result = (this.canDownload ? 1 : 0);
440            result = 31 * result + (this.canPreview ? 1 : 0);
441            result = 31 * result + (this.canEdit ? 1 : 0);
442            return result;
443        }
444
445        @Override
446        public String toString() {
447            return "Permissions{canDownload=" + this.canDownload
448                + ", canPreview=" + this.canPreview
449                + ", canEdit=" + this.canEdit
450                + '}';
451        }
452    }
453}