001package com.box.sdk;
002
003import com.box.sdk.sharedlink.BoxSharedLinkWithoutPermissionsRequest;
004import com.eclipsesource.json.Json;
005import com.eclipsesource.json.JsonArray;
006import com.eclipsesource.json.JsonObject;
007import com.eclipsesource.json.JsonValue;
008import java.net.MalformedURLException;
009import java.net.URL;
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(String...)}.
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     *
041     * @param api the API connection to be used by the weblink.
042     * @param id  the ID of the weblink.
043     */
044    public BoxWebLink(BoxAPIConnection api, String id) {
045        super(api, id);
046    }
047
048    /**
049     * Creates a shared link.
050     *
051     * @param sharedLinkRequest Shared link to create
052     * @return Created shared link.
053     */
054    public BoxSharedLink createSharedLink(BoxSharedLinkWithoutPermissionsRequest sharedLinkRequest) {
055        return createSharedLink(sharedLinkRequest.asSharedLink());
056    }
057
058    private BoxSharedLink createSharedLink(BoxSharedLink sharedLink) {
059        BoxWebLink.Info info = new BoxWebLink.Info();
060        info.setSharedLink(sharedLink);
061
062        this.updateInfo(info);
063        return info.getSharedLink();
064    }
065
066
067    @Override
068    public BoxWebLink.Info copy(BoxFolder destination) {
069        return this.copy(destination, null);
070    }
071
072    @Override
073    public BoxWebLink.Info copy(BoxFolder destination, String newName) {
074        URL url = COPY_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
075
076        JsonObject parent = new JsonObject();
077        parent.add("id", destination.getID());
078
079        JsonObject copyInfo = new JsonObject();
080        copyInfo.add("parent", parent);
081        if (newName != null) {
082            copyInfo.add("name", newName);
083        }
084
085        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");
086        request.setBody(copyInfo.toString());
087        try (BoxJSONResponse response = request.send()) {
088            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
089            BoxWebLink copiedWebLink = new BoxWebLink(this.getAPI(), responseJSON.get("id").asString());
090            return copiedWebLink.new Info(responseJSON);
091        }
092    }
093
094    /**
095     * Deletes this weblink by moving it to the trash.
096     */
097    public void delete() {
098        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
099        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
100        request.send().close();
101    }
102
103    @Override
104    public BoxItem.Info move(BoxFolder destination) {
105        return this.move(destination, null);
106    }
107
108    @Override
109    public BoxItem.Info move(BoxFolder destination, String newName) {
110        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
111        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
112
113        JsonObject parent = new JsonObject();
114        parent.add("id", destination.getID());
115
116        JsonObject updateInfo = new JsonObject();
117        updateInfo.add("parent", parent);
118        if (newName != null) {
119            updateInfo.add("name", newName);
120        }
121
122        request.setBody(updateInfo.toString());
123        try (BoxJSONResponse response = request.send()) {
124            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
125            BoxWebLink movedWebLink = new BoxWebLink(this.getAPI(), responseJSON.get("id").asString());
126            return movedWebLink.new Info(responseJSON);
127        }
128    }
129
130    /**
131     * Renames this weblink.
132     *
133     * @param newName the new name of the weblink.
134     */
135    public void rename(String newName) {
136        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
137        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
138
139        JsonObject updateInfo = new JsonObject();
140        updateInfo.add("name", newName);
141
142        request.setBody(updateInfo.toString());
143        request.send().close();
144    }
145
146    @Override
147    public BoxWebLink.Info getInfo(String... fields) {
148        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
149        if (fields.length > 0) {
150            String queryString = new QueryStringBuilder().appendParam("fields", fields).toString();
151            url = WEB_LINK_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID());
152        }
153
154        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "GET");
155        try (BoxJSONResponse response = request.send()) {
156            return new Info(response.getJSON());
157        }
158    }
159
160    /**
161     * Updates the information about this weblink with any info fields that have been modified locally.
162     *
163     * <p>The only fields that will be updated are the ones that have been modified locally. For example, the following
164     * code won't update any information (or even send a network request) since none of the info's fields were
165     * changed:</p>
166     *
167     * <pre>BoxWebLink webLink = new BoxWebLink(api, id);
168     * BoxWebLink.Info info = webLink.getInfo();
169     * webLink.updateInfo(info);</pre>
170     *
171     * @param info the updated info.
172     */
173    public void updateInfo(BoxWebLink.Info info) {
174        URL url = WEB_LINK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
175        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
176        request.setBody(info.getPendingChanges());
177        try (BoxJSONResponse response = request.send()) {
178            JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
179            info.update(jsonObject);
180        }
181    }
182
183    @Override
184    public BoxWebLink.Info setCollections(BoxCollection... collections) {
185        JsonArray jsonArray = new JsonArray();
186        for (BoxCollection collection : collections) {
187            JsonObject collectionJSON = new JsonObject();
188            collectionJSON.add("id", collection.getID());
189            jsonArray.add(collectionJSON);
190        }
191        JsonObject infoJSON = new JsonObject();
192        infoJSON.add("collections", jsonArray);
193
194        String queryString = new QueryStringBuilder().appendParam("fields", ALL_FIELDS).toString();
195        URL url = WEB_LINK_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID());
196        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
197        request.setBody(infoJSON.toString());
198        try (BoxJSONResponse response = request.send()) {
199            JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
200            return new Info(jsonObject);
201        }
202    }
203
204    /**
205     * Contains information about a BoxWebLink.
206     */
207    public class Info extends BoxItem.Info {
208        private URL linkURL;
209        private String description;
210
211        /**
212         * Constructs an empty Info object.
213         */
214        public Info() {
215            super();
216        }
217
218        /**
219         * Constructs an Info object by parsing information from a JSON string.
220         *
221         * @param json the JSON string to parse.
222         */
223        public Info(String json) {
224            super(json);
225        }
226
227        /**
228         * Constructs an Info object using an already parsed JSON object.
229         *
230         * @param jsonObject the parsed JSON object.
231         */
232        public Info(JsonObject jsonObject) {
233            super(jsonObject.toString());
234        }
235
236        @Override
237        public BoxWebLink getResource() {
238            return BoxWebLink.this;
239        }
240
241        /**
242         * Gets the description of this weblink.
243         *
244         * @return the description of this weblink.
245         */
246        public String getDescription() {
247            return this.description;
248        }
249
250        /**
251         * Gets the URL this weblink points to.
252         *
253         * @return the URL this weblink points to.
254         */
255        public URL getLinkURL() {
256            return this.linkURL;
257        }
258
259        @Override
260        protected void parseJSONMember(JsonObject.Member member) {
261            super.parseJSONMember(member);
262
263            String memberName = member.getName();
264            JsonValue value = member.getValue();
265            try {
266                if (memberName.equals("url")) {
267                    try {
268                        if (value.asString().isEmpty()) {
269                            this.linkURL = null;
270                        } else {
271                            this.linkURL = new URL(value.asString());
272                        }
273                    } catch (MalformedURLException e) {
274                        throw new BoxAPIException("Couldn't parse url for weblink", e);
275                    }
276                } else if (memberName.equals("description")) {
277                    this.description = value.asString();
278                }
279            } catch (Exception e) {
280                throw new BoxDeserializationException(memberName, value.toString(), e);
281            }
282        }
283    }
284}