001package com.box.sdk;
002
003import java.net.MalformedURLException;
004import java.net.URL;
005import java.util.Date;
006
007import com.eclipsesource.json.JsonObject;
008import com.eclipsesource.json.JsonValue;
009
010/**
011 * Represents a file request on Box.
012 */
013@BoxResourceType("file_request")
014public class BoxFileRequest extends BoxResource {
015
016    /**
017     * File Request URL Template.
018     */
019    public static final URLTemplate FILE_REQUEST_URL_TEMPLATE = new URLTemplate("file_requests/%s");
020    /**
021     * Copy File Request URL Template.
022     */
023    public static final URLTemplate COPY_FILE_REQUEST_URL_TEMPLATE = new URLTemplate("file_requests/%s/copy");
024
025    /**
026     * Constructs a BoxFileRequest for a file request with a given ID.
027     *
028     * @param api the API connection to be used by the file request.
029     * @param id  the ID of the file request.
030     */
031    public BoxFileRequest(BoxAPIConnection api, String id) {
032        super(api, id);
033    }
034
035    /**
036     * Gets information about this file request.
037     *
038     * @return info about this file request.
039     */
040    public BoxFileRequest.Info getInfo() {
041        URL url = FILE_REQUEST_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
042        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
043        BoxJSONResponse response = (BoxJSONResponse) request.send();
044        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
045        return new Info(responseJSON, this.getAPI().getBaseAppUrl());
046    }
047
048    /**
049     * Copies this file request that is already present on one folder, and applies it to another folder.
050     *
051     * @param folderId the ID of the folder for the file request.
052     * @return info about the newly copied file request.
053     */
054    public BoxFileRequest.Info copyInfo(String folderId) {
055        URL url = COPY_FILE_REQUEST_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
056        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");
057        JsonObject body = new JsonObject();
058        JsonObject folderBody = new JsonObject();
059        folderBody.add("id", folderId);
060        folderBody.add("type", "folder");
061        body.add("folder", folderBody);
062        request.setBody(body.toString());
063        BoxJSONResponse response = (BoxJSONResponse) request.send();
064        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
065        return new Info(jsonObject, this.getAPI().getBaseAppUrl());
066    }
067
068    /**
069     * Copies this file request that is already present on one folder, and applies it to another folder.
070     *
071     * <p>Info fields that have been modified locally will overwrite the values in the original file request.
072     *
073     * @param info     the info.
074     * @param folderId the ID of the folder for the file request.
075     * @return info about the newly copied file request.
076     */
077    public BoxFileRequest.Info copyInfo(BoxFileRequest.Info info, String folderId) {
078        URL url = COPY_FILE_REQUEST_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
079        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");
080        JsonObject body = new JsonObject();
081        JsonObject pendingChanges = info.getPendingChangesAsJsonObject();
082        if (pendingChanges != null) {
083            body = pendingChanges;
084        }
085        JsonObject folderBody = new JsonObject();
086        folderBody.add("id", folderId);
087        folderBody.add("type", "folder");
088        body.add("folder", folderBody);
089        request.setBody(body.toString());
090        BoxJSONResponse response = (BoxJSONResponse) request.send();
091        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
092        info.update(jsonObject);
093        return new Info(jsonObject, this.getAPI().getBaseAppUrl());
094    }
095
096    /**
097     * Updates the information about this file request with any info fields that have been modified locally.
098     *
099     * <p>The only fields that will be updated are the ones that have been modified locally. For example, the following
100     * code won't update any information (or even send a network request) since none of the info's fields were
101     * changed:</p>
102     *
103     * <pre>BoxFileRequest fileRequest = new BoxFileRequest(api, id);
104     * BoxFileRequest.Info info = fileRequest.getInfo();
105     * info.updateInfo(info);</pre>
106     *
107     * @param info the updated info.
108     * @return info about the updated file request.
109     */
110    public BoxFileRequest.Info updateInfo(BoxFileRequest.Info info) {
111        URL url = FILE_REQUEST_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
112        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
113        request.setBody(info.getPendingChanges());
114        BoxJSONResponse response = (BoxJSONResponse) request.send();
115        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
116        info.update(jsonObject);
117        return info;
118    }
119
120    /**
121     * Delete this file request.
122     */
123    public void delete() {
124        URL url = FILE_REQUEST_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
125        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
126        BoxAPIResponse response = request.send();
127        response.disconnect();
128    }
129
130    /**
131     * Contains information about a BoxFileRequest.
132     */
133    public class Info extends BoxResource.Info {
134        private String type;
135        private Date createdAt;
136        private BoxUser.Info createdBy;
137        private String description;
138        private String etag;
139        private Date expiresAt;
140        private BoxFolder.Info folder;
141        private boolean isDescriptionRequired;
142        private boolean isEmailRequired;
143        private Status status;
144        private String title;
145        private Date updatedAt;
146        private BoxUser.Info updatedBy;
147        private URL url;
148        private String path;
149        private String baseUrl;
150
151        /**
152         * Constructs an empty Info object.
153         */
154        public Info() {
155            super();
156        }
157
158        /**
159         * Constructs an Info object by parsing information from a JSON string.
160         *
161         * @param json the JSON string to parse.
162         */
163        public Info(String json) {
164            super(json);
165        }
166
167        /**
168         * Constructs an Info object using an already parsed JSON object.
169         *
170         * @param jsonObject the parsed JSON object.
171         */
172        Info(JsonObject jsonObject, String fileRequestBaseUrl) {
173            super(jsonObject);
174            try {
175                this.baseUrl = fileRequestBaseUrl;
176                this.url = new URL(this.baseUrl + this.path);
177            } catch (MalformedURLException e) {
178                throw new BoxAPIException("Couldn't construct url for file request", e);
179            }
180        }
181
182        @Override
183        public BoxFileRequest getResource() {
184            return BoxFileRequest.this;
185        }
186
187        /**
188         * Gets the file request type.
189         *
190         * @return the file request type.
191         */
192        public String getType() {
193            return this.type;
194        }
195
196        /**
197         * Gets the date when the file request was created.
198         *
199         * @return the date when the file request was created.
200         */
201        public Date getCreatedAt() {
202            return this.createdAt;
203        }
204
205        /**
206         * Gets the user who created this file request.
207         *
208         * @return the user who created this file request.
209         */
210        public BoxUser.Info getCreatedBy() {
211            return this.createdBy;
212        }
213
214        /**
215         * Gets the description of this file request.
216         *
217         * @return the description of this file request.
218         */
219        public String getDescription() {
220            return this.description;
221        }
222
223        /**
224         * Sets the description of this file request.
225         *
226         * @param description the file request's new description.
227         */
228        public void setDescription(String description) {
229            this.description = description;
230            this.addPendingChange("description", description);
231        }
232
233        /**
234         * Gets a unique string identifying the version of the item.
235         *
236         * @return a unique string identifying the version of the item.
237         */
238        public String getEtag() {
239            return this.etag;
240        }
241
242        /**
243         * Gets the date after which a file request will no longer accept new submissions.
244         *
245         * @return the date after which a file request will no longer accept new submissions.
246         */
247        public Date getExpiresAt() {
248            return this.expiresAt;
249        }
250
251
252        /**
253         * Sets the date after which a file request will no longer accept new submissions.
254         *
255         * @param expiresAt the date after which a file request will no longer accept new submissions.
256         */
257        public void setExpiresAt(Date expiresAt) {
258            this.expiresAt = expiresAt;
259            this.addPendingChange("expires_at", BoxDateFormat.format(expiresAt));
260        }
261
262        /**
263         * Gets the folder that this file request is associated with.
264         *
265         * @return the folder that this file request is associated with.
266         */
267        public BoxFolder.Info getFolder() {
268            return this.folder;
269        }
270
271        /**
272         * Gets whether a file request submitter is required to provide a description of the files they are submitting.
273         *
274         * @return whether a file request submitter is required to provide a description of the files they
275         * are submitting.
276         */
277        public Boolean getIsDescriptionRequired() {
278            return this.isDescriptionRequired;
279        }
280
281        /**
282         * Sets whether a file request submitter is required to provide a description of the files they are submitting.
283         *
284         * @param isDescriptionRequired whether a file request submitter is required to provide a description of the
285         *                              files they are submitting.
286         */
287        public void setIsDescriptionRequired(Boolean isDescriptionRequired) {
288            this.isDescriptionRequired = isDescriptionRequired;
289            this.addPendingChange("is_description_required", isDescriptionRequired);
290        }
291
292        /**
293         * Gets whether a file request submitter is required to provide their email address.
294         *
295         * @return whether a file request submitter is required to provide their email address.
296         */
297        public Boolean getIsEmailRequired() {
298            return this.isEmailRequired;
299        }
300
301        /**
302         * Sets whether a file request submitter is required to provide their email address.
303         *
304         * @param isEmailRequired whether a file request submitter is required to provide their email address.
305         */
306        public void setIsEmailRequired(Boolean isEmailRequired) {
307            this.isEmailRequired = isEmailRequired;
308            this.addPendingChange("is_email_required", isEmailRequired);
309        }
310
311        /**
312         * Gets the status of the file request.
313         *
314         * @return the status of the file request
315         */
316        public Status getStatus() {
317            return this.status;
318        }
319
320
321        /**
322         * Sets the status of the file request.
323         *
324         * @param status the status of the file request
325         */
326        public void setStatus(Status status) {
327            this.status = status;
328            this.addPendingChange("status", status.toJSONString());
329        }
330
331        /**
332         * Gets the title of file request.
333         *
334         * @return the title of file request.
335         */
336        public String getTitle() {
337            return this.title;
338        }
339
340        /**
341         * Sets the title of file request.
342         *
343         * @param title the title of file request.
344         */
345        public void setTitle(String title) {
346            this.title = title;
347            this.addPendingChange("title", title);
348        }
349
350        /**
351         * Gets the date when the file request was last updated.
352         *
353         * @return the date when the file request was last updated.
354         */
355        public Date getUpdatedAt() {
356            return this.updatedAt;
357        }
358
359        /**
360         * Gets the user who last modified this file request.
361         *
362         * @return the user who last modified this file request.
363         */
364        public BoxUser.Info getUpdatedBy() {
365            return this.updatedBy;
366        }
367
368        /**
369         * Gets the URL can be shared with users to let them upload files to the associated folder.
370         *
371         * @return the URL for files upload.
372         */
373        public URL getUrl() {
374            return this.url;
375        }
376
377        /**
378         * Gets the base URL for the upload files link.
379         *
380         * @return the base url including protocol and hostname.
381         */
382        public String getBaseUrl() {
383            return this.baseUrl;
384        }
385
386        /**
387         * Gets the URL containing only the path (e.g. "/f/123456789") shared with users to let
388         * them upload files to the associated folder.
389         *
390         * @return the path of the URL for files upload.
391         */
392        public String getPath() {
393            return this.path;
394        }
395
396        /**
397         * Sets the base URL for the upload files link. Can throw an exception if format of the URL is invalid.
398         *
399         * @param baseUrl the base url including protocol and hostname.
400         * @throws MalformedURLException when baseUrl format is invalid.
401         */
402        public void setBaseUrl(String baseUrl) throws MalformedURLException {
403            this.baseUrl = baseUrl;
404            this.url = new URL(this.baseUrl + this.path);
405        }
406
407        @Override
408        void parseJSONMember(JsonObject.Member member) {
409            super.parseJSONMember(member);
410
411            String memberName = member.getName();
412            JsonValue value = member.getValue();
413            try {
414                if (memberName.equals("type")) {
415                    this.type = value.asString();
416                } else if (memberName.equals("created_at")) {
417                    this.createdAt = BoxDateFormat.parse(value.asString());
418                } else if (memberName.equals("created_by")) {
419                    JsonObject userJSON = value.asObject();
420                    String userID = userJSON.get("id").asString();
421                    BoxUser user = new BoxUser(getAPI(), userID);
422                    this.createdBy = user.new Info(userJSON);
423                } else if (memberName.equals("description")) {
424                    this.description = value.asString();
425                } else if (memberName.equals("etag")) {
426                    this.etag = value.asString();
427                } else if (memberName.equals("expires_at")) {
428                    this.expiresAt = BoxDateFormat.parse(value.asString());
429                } else if (memberName.equals("folder")) {
430                    JsonObject folderJSON = value.asObject();
431                    String folderID = folderJSON.get("id").asString();
432                    BoxFolder folder = new BoxFolder(getAPI(), folderID);
433                    this.folder = folder.new Info(folderJSON);
434                } else if (memberName.equals("is_description_required")) {
435                    this.isDescriptionRequired = value.asBoolean();
436                } else if (memberName.equals("is_email_required")) {
437                    this.isEmailRequired = value.asBoolean();
438                } else if (memberName.equals("status")) {
439                    this.status = Status.fromJSONString(value.asString());
440                } else if (memberName.equals("title")) {
441                    this.title = value.asString();
442                } else if (memberName.equals("updated_at")) {
443                    this.updatedAt = BoxDateFormat.parse(value.asString());
444                } else if (memberName.equals("updated_by")) {
445                    JsonObject userJSON = value.asObject();
446                    String userID = userJSON.get("id").asString();
447                    BoxUser user = new BoxUser(getAPI(), userID);
448                    this.createdBy = user.new Info(userJSON);
449                } else if (memberName.equals("url")) {
450                    this.path = value.asString();
451                }
452            } catch (Exception e) {
453                throw new BoxDeserializationException(memberName, value.toString(), e);
454            }
455        }
456    }
457
458    /**
459     * The status of the file request.
460     */
461    public enum Status {
462        /**
463         * The file request can accept new submissions.
464         */
465        ACTIVE("active"),
466
467        /**
468         * The file request can't accept new submissions.
469         */
470        INACTIVE("inactive");
471
472        private final String jsonValue;
473
474        private Status(String jsonValue) {
475            this.jsonValue = jsonValue;
476        }
477
478        static Status fromJSONString(String jsonValue) {
479            return Status.valueOf(jsonValue.toUpperCase());
480        }
481
482        String toJSONString() {
483            return this.jsonValue;
484        }
485    }
486}