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