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