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