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        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
043        BoxJSONResponse response = (BoxJSONResponse) request.send();
044        JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
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 = Json.parse(response.getJSON()).asObject();
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 = Json.parse(response.getJSON()).asObject();
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 = Json.parse(response.getJSON()).asObject();
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     * The status of the file request.
132     */
133    public enum Status {
134        /**
135         * The file request can accept new submissions.
136         */
137        ACTIVE("active"),
138
139        /**
140         * The file request can't accept new submissions.
141         */
142        INACTIVE("inactive");
143
144        private final String jsonValue;
145
146        Status(String jsonValue) {
147            this.jsonValue = jsonValue;
148        }
149
150        static Status fromJSONString(String jsonValue) {
151            return Status.valueOf(jsonValue.toUpperCase());
152        }
153
154        String toJSONString() {
155            return this.jsonValue;
156        }
157    }
158
159    /**
160     * Contains information about a BoxFileRequest.
161     */
162    public class Info extends BoxResource.Info {
163        private String type;
164        private Date createdAt;
165        private BoxUser.Info createdBy;
166        private String description;
167        private String etag;
168        private Date expiresAt;
169        private BoxFolder.Info folder;
170        private boolean isDescriptionRequired;
171        private boolean isEmailRequired;
172        private Status status;
173        private String title;
174        private Date updatedAt;
175        private BoxUser.Info updatedBy;
176        private URL url;
177        private String path;
178        private String baseUrl;
179
180        /**
181         * Constructs an empty Info object.
182         */
183        public Info() {
184            super();
185        }
186
187        /**
188         * Constructs an Info object by parsing information from a JSON string.
189         *
190         * @param json the JSON string to parse.
191         */
192        public Info(String json) {
193            super(json);
194        }
195
196        /**
197         * Constructs an Info object using an already parsed JSON object.
198         *
199         * @param jsonObject the parsed JSON object.
200         * @param fileRequestBaseUrl Request base URL
201         */
202        Info(JsonObject jsonObject, String fileRequestBaseUrl) {
203            super(jsonObject);
204            try {
205                this.baseUrl = fileRequestBaseUrl;
206                this.url = new URL(this.baseUrl + this.path);
207            } catch (MalformedURLException e) {
208                throw new BoxAPIException("Couldn't construct url for file request", e);
209            }
210        }
211
212        @Override
213        public BoxFileRequest getResource() {
214            return BoxFileRequest.this;
215        }
216
217        /**
218         * Gets the file request type.
219         *
220         * @return the file request type.
221         */
222        public String getType() {
223            return this.type;
224        }
225
226        /**
227         * Gets the date when the file request was created.
228         *
229         * @return the date when the file request was created.
230         */
231        public Date getCreatedAt() {
232            return this.createdAt;
233        }
234
235        /**
236         * Gets the user who created this file request.
237         *
238         * @return the user who created this file request.
239         */
240        public BoxUser.Info getCreatedBy() {
241            return this.createdBy;
242        }
243
244        /**
245         * Gets the description of this file request.
246         *
247         * @return the description of this file request.
248         */
249        public String getDescription() {
250            return this.description;
251        }
252
253        /**
254         * Sets the description of this file request.
255         *
256         * @param description the file request's new description.
257         */
258        public void setDescription(String description) {
259            this.description = description;
260            this.addPendingChange("description", description);
261        }
262
263        /**
264         * Gets a unique string identifying the version of the item.
265         *
266         * @return a unique string identifying the version of the item.
267         */
268        public String getEtag() {
269            return this.etag;
270        }
271
272        /**
273         * Gets the date after which a file request will no longer accept new submissions.
274         *
275         * @return the date after which a file request will no longer accept new submissions.
276         */
277        public Date getExpiresAt() {
278            return this.expiresAt;
279        }
280
281
282        /**
283         * Sets the date after which a file request will no longer accept new submissions.
284         *
285         * @param expiresAt the date after which a file request will no longer accept new submissions.
286         */
287        public void setExpiresAt(Date expiresAt) {
288            this.expiresAt = expiresAt;
289            this.addPendingChange("expires_at", BoxDateFormat.format(expiresAt));
290        }
291
292        /**
293         * Gets the folder that this file request is associated with.
294         *
295         * @return the folder that this file request is associated with.
296         */
297        public BoxFolder.Info getFolder() {
298            return this.folder;
299        }
300
301        /**
302         * Gets whether a file request submitter is required to provide a description of the files they are submitting.
303         *
304         * @return whether a file request submitter is required to provide a description of the files they
305         * are submitting.
306         */
307        public Boolean getIsDescriptionRequired() {
308            return this.isDescriptionRequired;
309        }
310
311        /**
312         * Sets whether a file request submitter is required to provide a description of the files they are submitting.
313         *
314         * @param isDescriptionRequired whether a file request submitter is required to provide a description of the
315         *                              files they are submitting.
316         */
317        public void setIsDescriptionRequired(Boolean isDescriptionRequired) {
318            this.isDescriptionRequired = isDescriptionRequired;
319            this.addPendingChange("is_description_required", isDescriptionRequired);
320        }
321
322        /**
323         * Gets whether a file request submitter is required to provide their email address.
324         *
325         * @return whether a file request submitter is required to provide their email address.
326         */
327        public Boolean getIsEmailRequired() {
328            return this.isEmailRequired;
329        }
330
331        /**
332         * Sets whether a file request submitter is required to provide their email address.
333         *
334         * @param isEmailRequired whether a file request submitter is required to provide their email address.
335         */
336        public void setIsEmailRequired(Boolean isEmailRequired) {
337            this.isEmailRequired = isEmailRequired;
338            this.addPendingChange("is_email_required", isEmailRequired);
339        }
340
341        /**
342         * Gets the status of the file request.
343         *
344         * @return the status of the file request
345         */
346        public Status getStatus() {
347            return this.status;
348        }
349
350
351        /**
352         * Sets the status of the file request.
353         *
354         * @param status the status of the file request
355         */
356        public void setStatus(Status status) {
357            this.status = status;
358            this.addPendingChange("status", status.toJSONString());
359        }
360
361        /**
362         * Gets the title of file request.
363         *
364         * @return the title of file request.
365         */
366        public String getTitle() {
367            return this.title;
368        }
369
370        /**
371         * Sets the title of file request.
372         *
373         * @param title the title of file request.
374         */
375        public void setTitle(String title) {
376            this.title = title;
377            this.addPendingChange("title", title);
378        }
379
380        /**
381         * Gets the date when the file request was last updated.
382         *
383         * @return the date when the file request was last updated.
384         */
385        public Date getUpdatedAt() {
386            return this.updatedAt;
387        }
388
389        /**
390         * Gets the user who last modified this file request.
391         *
392         * @return the user who last modified this file request.
393         */
394        public BoxUser.Info getUpdatedBy() {
395            return this.updatedBy;
396        }
397
398        /**
399         * Gets the URL can be shared with users to let them upload files to the associated folder.
400         *
401         * @return the URL for files upload.
402         */
403        public URL getUrl() {
404            return this.url;
405        }
406
407        /**
408         * Gets the base URL for the upload files link.
409         *
410         * @return the base url including protocol and hostname.
411         */
412        public String getBaseUrl() {
413            return this.baseUrl;
414        }
415
416        /**
417         * Sets the base URL for the upload files link. Can throw an exception if format of the URL is invalid.
418         *
419         * @param baseUrl the base url including protocol and hostname.
420         * @throws MalformedURLException when baseUrl format is invalid.
421         */
422        public void setBaseUrl(String baseUrl) throws MalformedURLException {
423            this.baseUrl = baseUrl;
424            this.url = new URL(this.baseUrl + this.path);
425        }
426
427        /**
428         * Gets the URL containing only the path (e.g. "/f/123456789") shared with users to let
429         * them upload files to the associated folder.
430         *
431         * @return the path of the URL for files upload.
432         */
433        public String getPath() {
434            return this.path;
435        }
436
437        @Override
438        void parseJSONMember(JsonObject.Member member) {
439            super.parseJSONMember(member);
440
441            String memberName = member.getName();
442            JsonValue value = member.getValue();
443            try {
444                if (memberName.equals("type")) {
445                    this.type = value.asString();
446                } else if (memberName.equals("created_at")) {
447                    this.createdAt = BoxDateFormat.parse(value.asString());
448                } else if (memberName.equals("created_by")) {
449                    JsonObject userJSON = value.asObject();
450                    String userID = userJSON.get("id").asString();
451                    BoxUser user = new BoxUser(getAPI(), userID);
452                    this.createdBy = user.new Info(userJSON);
453                } else if (memberName.equals("description")) {
454                    this.description = value.asString();
455                } else if (memberName.equals("etag")) {
456                    this.etag = value.asString();
457                } else if (memberName.equals("expires_at")) {
458                    this.expiresAt = BoxDateFormat.parse(value.asString());
459                } else if (memberName.equals("folder")) {
460                    JsonObject folderJSON = value.asObject();
461                    String folderID = folderJSON.get("id").asString();
462                    BoxFolder folder = new BoxFolder(getAPI(), folderID);
463                    this.folder = folder.new Info(folderJSON);
464                } else if (memberName.equals("is_description_required")) {
465                    this.isDescriptionRequired = value.asBoolean();
466                } else if (memberName.equals("is_email_required")) {
467                    this.isEmailRequired = value.asBoolean();
468                } else if (memberName.equals("status")) {
469                    this.status = Status.fromJSONString(value.asString());
470                } else if (memberName.equals("title")) {
471                    this.title = value.asString();
472                } else if (memberName.equals("updated_at")) {
473                    this.updatedAt = BoxDateFormat.parse(value.asString());
474                } else if (memberName.equals("updated_by")) {
475                    JsonObject userJSON = value.asObject();
476                    String userID = userJSON.get("id").asString();
477                    BoxUser user = new BoxUser(getAPI(), userID);
478                    this.createdBy = user.new Info(userJSON);
479                } else if (memberName.equals("url")) {
480                    this.path = value.asString();
481                }
482            } catch (Exception e) {
483                throw new BoxDeserializationException(memberName, value.toString(), e);
484            }
485        }
486    }
487}