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