001package com.box.sdk;
002
003import java.net.MalformedURLException;
004import java.net.URL;
005import java.util.Date;
006
007import com.eclipsesource.json.JsonArray;
008import com.eclipsesource.json.JsonObject;
009import com.eclipsesource.json.JsonValue;
010
011/**
012 * Represents an individual WebLink file on Box. This class can be used to retrieve the link's URL or perform other
013 * common file operations (move, copy, delete, etc.).
014 *
015 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked
016 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error
017 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p>
018 */
019@BoxResourceType("web_link")
020public class BoxWebLink extends BoxItem {
021
022    /**
023     * An array of all possible weblink fields that can be requested when calling {@link #getInfo()}.
024     */
025    public static final String[] ALL_FIELDS = {"type", "id", "sequence_id", "etag", "name", "url", "description",
026        "path_collection", "created_at", "modified_at", "trashed_at", "purged_at", "created_by", "modified_by",
027        "owned_by", "shared_link", "parent", "item_status", "collections"};
028
029    /**
030     * Copy URL Template.
031     */
032    public static final URLTemplate COPY_URL_TEMPLATE = new URLTemplate("web_links/%s/copy");
033    /**
034     * Web Link URL Template.
035     */
036    public static final URLTemplate WEB_LINK_URL_TEMPLATE = new URLTemplate("web_links/%s");
037
038    /**
039     * Constructs a BoxWebLink for a weblink with a given ID.
040     * @param  api the API connection to be used by the weblink.
041     * @param  id  the ID of the weblink.
042     */
043    public BoxWebLink(BoxAPIConnection api, String id) {
044        super(api, id);
045    }
046
047    @Override
048    public BoxSharedLink createSharedLink(BoxSharedLink.Access access, Date unshareDate,
049        BoxSharedLink.Permissions permissions) {
050
051        BoxSharedLink sharedLink = new BoxSharedLink(access, unshareDate, permissions);
052        Info info = new Info();
053        info.setSharedLink(sharedLink);
054
055        this.updateInfo(info);
056        return info.getSharedLink();
057    }
058
059    /**
060     * Creates new SharedLink for a BoxWebLink with a password.
061     *
062     * @param access        The access level of the shared link.
063     * @param unshareDate   A specified date to unshare the Box web link.
064     * @param permissions   The permissions to set on the shared link for the Box web link.
065     * @param password      Password set on the shared link to give access to the Box web link.
066     * @return information about the newly created shared link.
067     */
068    public BoxSharedLink createSharedLink(BoxSharedLink.Access access, Date unshareDate,
069        BoxSharedLink.Permissions permissions, String password) {
070
071        BoxSharedLink sharedLink = new BoxSharedLink(access, unshareDate, permissions, password);
072        Info info = new Info();
073        info.setSharedLink(sharedLink);
074
075        this.updateInfo(info);
076        return info.getSharedLink();
077    }
078
079    @Override
080    public BoxWebLink.Info copy(BoxFolder destination) {
081        return this.copy(destination, null);
082    }
083
084    @Override
085    public BoxWebLink.Info copy(BoxFolder destination, String newName) {
086        URL url = COPY_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
087
088        JsonObject parent = new JsonObject();
089        parent.add("id", destination.getID());
090
091        JsonObject copyInfo = new JsonObject();
092        copyInfo.add("parent", parent);
093        if (newName != null) {
094            copyInfo.add("name", newName);
095        }
096
097        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");
098        request.setBody(copyInfo.toString());
099        BoxJSONResponse response = (BoxJSONResponse) request.send();
100        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
101        BoxWebLink copiedWebLink = new BoxWebLink(this.getAPI(), responseJSON.get("id").asString());
102        return copiedWebLink.new Info(responseJSON);
103    }
104
105    /**
106     * Deletes this weblink by moving it to the trash.
107     */
108    public void delete() {
109        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
110        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
111        BoxAPIResponse response = request.send();
112        response.disconnect();
113    }
114
115    @Override
116    public BoxItem.Info move(BoxFolder destination) {
117        return this.move(destination, null);
118    }
119
120    @Override
121    public BoxItem.Info move(BoxFolder destination, String newName) {
122        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
123        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
124
125        JsonObject parent = new JsonObject();
126        parent.add("id", destination.getID());
127
128        JsonObject updateInfo = new JsonObject();
129        updateInfo.add("parent", parent);
130        if (newName != null) {
131            updateInfo.add("name", newName);
132        }
133
134        request.setBody(updateInfo.toString());
135        BoxJSONResponse response = (BoxJSONResponse) request.send();
136        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
137        BoxWebLink movedWebLink = new BoxWebLink(this.getAPI(), responseJSON.get("id").asString());
138        return movedWebLink.new Info(responseJSON);
139    }
140
141    /**
142     * Renames this weblink.
143     * @param newName the new name of the weblink.
144     */
145    public void rename(String newName) {
146        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
147        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
148
149        JsonObject updateInfo = new JsonObject();
150        updateInfo.add("name", newName);
151
152        request.setBody(updateInfo.toString());
153        BoxAPIResponse response = request.send();
154        response.disconnect();
155    }
156
157    @Override
158    public BoxWebLink.Info getInfo() {
159        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
160        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
161        BoxJSONResponse response = (BoxJSONResponse) request.send();
162        return new Info(response.getJSON());
163    }
164
165    @Override
166    public BoxWebLink.Info getInfo(String... fields) {
167        String queryString = new QueryStringBuilder().appendParam("fields", fields).toString();
168        URL url = WEB_LINK_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID());
169
170        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
171        BoxJSONResponse response = (BoxJSONResponse) request.send();
172        return new Info(response.getJSON());
173    }
174
175    /**
176     * Updates the information about this weblink with any info fields that have been modified locally.
177     *
178     * <p>The only fields that will be updated are the ones that have been modified locally. For example, the following
179     * code won't update any information (or even send a network request) since none of the info's fields were
180     * changed:</p>
181     *
182     * <pre>BoxWebLink webLink = new BoxWebLink(api, id);
183     *BoxWebLink.Info info = webLink.getInfo();
184     *webLink.updateInfo(info);</pre>
185     *
186     * @param  info the updated info.
187     */
188    public void updateInfo(BoxWebLink.Info info) {
189        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
190        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
191        request.setBody(info.getPendingChanges());
192        String body = info.getPendingChanges();
193        BoxJSONResponse response = (BoxJSONResponse) request.send();
194        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
195        info.update(jsonObject);
196    }
197
198    @Override
199    public BoxWebLink.Info setCollections(BoxCollection... collections) {
200        JsonArray jsonArray = new JsonArray();
201        for (BoxCollection collection : collections) {
202            JsonObject collectionJSON = new JsonObject();
203            collectionJSON.add("id", collection.getID());
204            jsonArray.add(collectionJSON);
205        }
206        JsonObject infoJSON = new JsonObject();
207        infoJSON.add("collections", jsonArray);
208
209        String queryString = new QueryStringBuilder().appendParam("fields", ALL_FIELDS).toString();
210        URL url = WEB_LINK_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID());
211        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
212        request.setBody(infoJSON.toString());
213        BoxJSONResponse response = (BoxJSONResponse) request.send();
214        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
215        return new Info(jsonObject);
216    }
217
218    /**
219     * Contains information about a BoxWebLink.
220     */
221    public class Info extends BoxItem.Info {
222        private URL linkURL;
223        private String description;
224
225        /**
226         * Constructs an empty Info object.
227         */
228        public Info() {
229            super();
230        }
231
232        /**
233         * Constructs an Info object by parsing information from a JSON string.
234         * @param  json the JSON string to parse.
235         */
236        public Info(String json) {
237            super(json);
238        }
239
240        /**
241         * Constructs an Info object using an already parsed JSON object.
242         * @param  jsonObject the parsed JSON object.
243         */
244        public Info(JsonObject jsonObject) {
245            super(jsonObject.toString());
246        }
247
248        @Override
249        public BoxWebLink getResource() {
250            return BoxWebLink.this;
251        }
252
253        /**
254         * Gets the description of this weblink.
255         * @return the description of this weblink.
256         */
257        public String getDescription() {
258            return this.description;
259        }
260
261        /**
262         * Gets the URL this weblink points to.
263         * @return the URL this weblink points to.
264         */
265        public URL getLinkURL() {
266            return this.linkURL;
267        }
268
269        @Override
270        protected void parseJSONMember(JsonObject.Member member) {
271            super.parseJSONMember(member);
272
273            String memberName = member.getName();
274            JsonValue value = member.getValue();
275            if (memberName.equals("url")) {
276                try {
277                    this.linkURL = new URL(value.asString());
278                } catch (MalformedURLException e) {
279                    throw new BoxAPIException("Couldn't parse url for weblink", e);
280                }
281            } else if (memberName.equals("description")) {
282                this.description = value.asString();
283            }
284        }
285    }
286}