001package com.box.sdk;
002
003import com.eclipsesource.json.Json;
004import com.eclipsesource.json.JsonArray;
005import com.eclipsesource.json.JsonObject;
006import com.eclipsesource.json.JsonValue;
007import java.net.URL;
008import java.util.ArrayList;
009import java.util.Date;
010import java.util.List;
011
012/**
013 * Represents a retention policy. A retention policy blocks permanent deletion of content for a
014 * specified amount of time. Admins can create retention policies and then later assign them to
015 * specific folders or their entire enterprise.
016 *
017 * @see <a href="https://developer.box.com/reference/resources/retention-policy/">Box retention
018 *     policy</a>
019 *     <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link
020 *     BoxAPIException} (unchecked meaning that the compiler won't force you to handle it) if an
021 *     error occurs. If you wish to implement custom error handling for errors related to the Box
022 *     REST API, you should capture this exception explicitly.
023 */
024@BoxResourceType("retention_policy")
025public class BoxRetentionPolicy extends BoxResource {
026  /** The URL template used for operation with retention policies. */
027  public static final URLTemplate RETENTION_POLICIES_URL_TEMPLATE =
028      new URLTemplate("retention_policies");
029
030  /** The URL template used for operation with retention policy with given ID. */
031  public static final URLTemplate POLICY_URL_TEMPLATE = new URLTemplate("retention_policies/%s");
032
033  /** The URL template used for operation with retention policy assignments. */
034  public static final URLTemplate ASSIGNMENTS_URL_TEMPLATE =
035      new URLTemplate("retention_policies/%s/assignments");
036
037  /** Will cause the content retained by the policy to be permanently deleted. */
038  public static final String ACTION_PERMANENTLY_DELETE = "permanently_delete";
039
040  /** Will lift the retention policy from the content, allowing it to be deleted by users. */
041  public static final String ACTION_REMOVE_RETENTION = "remove_retention";
042
043  /** Status corresponding to active retention policy. */
044  public static final String STATUS_ACTIVE = "active";
045
046  /** Status corresponding to retired retention policy. */
047  public static final String STATUS_RETIRED = "retired";
048
049  /** The default limit of entries per response. */
050  private static final int DEFAULT_LIMIT = 100;
051
052  /**
053   * Constructs a retention policy for a resource with a given ID.
054   *
055   * @param api the API connection to be used by the resource.
056   * @param id the ID of the resource.
057   */
058  public BoxRetentionPolicy(BoxAPIConnection api, String id) {
059    super(api, id);
060  }
061
062  /**
063   * Used to create a new indefinite retention policy.
064   *
065   * @param api the API connection to be used by the created user.
066   * @param name the name of the retention policy.
067   * @return the created retention policy's info.
068   */
069  public static BoxRetentionPolicy.Info createIndefinitePolicy(BoxAPIConnection api, String name) {
070    return createRetentionPolicy(
071        api, name, BoxRetentionPolicyType.Indefinite, 0, BoxRetentionPolicyAction.RemoveRetention);
072  }
073
074  /**
075   * Used to create a new indefinite retention policy with optional parameters.
076   *
077   * @param api the API connection to be used by the created user.
078   * @param name the name of the retention policy.
079   * @param optionalParams the optional parameters.
080   * @return the created retention policy's info.
081   */
082  public static BoxRetentionPolicy.Info createIndefinitePolicy(
083      BoxAPIConnection api, String name, RetentionPolicyParams optionalParams) {
084    return createRetentionPolicy(
085        api,
086        name,
087        BoxRetentionPolicyType.Indefinite,
088        0,
089        BoxRetentionPolicyAction.RemoveRetention,
090        optionalParams);
091  }
092
093  /**
094   * Used to create a new finite retention policy.
095   *
096   * @param api the API connection to be used by the created user.
097   * @param name the name of the retention policy.
098   * @param length the duration in days that the retention policy will be active for after being
099   *     assigned to content.
100   * @param action the disposition action can be "permanently_delete" or "remove_retention".
101   * @return the created retention policy's info.
102   */
103  public static BoxRetentionPolicy.Info createFinitePolicy(
104      BoxAPIConnection api, String name, int length, BoxRetentionPolicyAction action) {
105    return createRetentionPolicy(api, name, BoxRetentionPolicyType.Finite, length, action);
106  }
107
108  /**
109   * Used to create a new finite retention policy with optional parameters.
110   *
111   * @param api the API connection to be used by the created user.
112   * @param name the name of the retention policy.
113   * @param length the duration in days that the retention policy will be active for after being
114   *     assigned to content.
115   * @param action the disposition action can be "permanently_delete" or "remove_retention".
116   * @param optionalParams the optional parameters.
117   * @return the created retention policy's info.
118   */
119  public static BoxRetentionPolicy.Info createFinitePolicy(
120      BoxAPIConnection api,
121      String name,
122      int length,
123      BoxRetentionPolicyAction action,
124      RetentionPolicyParams optionalParams) {
125    return createRetentionPolicy(
126        api, name, BoxRetentionPolicyType.Finite, length, action, optionalParams);
127  }
128
129  /**
130   * Used to create a new retention policy.
131   *
132   * @param api the API connection to be used by the created user.
133   * @param name the name of the retention policy.
134   * @param type the type of the retention policy. Can be "finite" or "indefinite".
135   * @param length the duration in days that the retention policy will be active for after being
136   *     assigned to content.
137   * @param action the disposition action can be "permanently_delete" or "remove_retention".
138   * @return the created retention policy's info.
139   */
140  private static BoxRetentionPolicy.Info createRetentionPolicy(
141      BoxAPIConnection api,
142      String name,
143      BoxRetentionPolicyType type,
144      int length,
145      BoxRetentionPolicyAction action) {
146    return createRetentionPolicy(api, name, type, length, action, null);
147  }
148
149  /**
150   * Used to create a new retention policy with optional parameters.
151   *
152   * @param api the API connection to be used by the created user.
153   * @param name the name of the retention policy.
154   * @param type the type of the retention policy. Can be "finite" or "indefinite".
155   * @param length the duration in days that the retention policy will be active for after being
156   *     assigned to content.
157   * @param action the disposition action can be "permanently_delete" or "remove_retention".
158   * @param optionalParams the optional parameters.
159   * @return the created retention policy's info.
160   */
161  private static BoxRetentionPolicy.Info createRetentionPolicy(
162      BoxAPIConnection api,
163      String name,
164      BoxRetentionPolicyType type,
165      int length,
166      BoxRetentionPolicyAction action,
167      RetentionPolicyParams optionalParams) {
168    URL url = RETENTION_POLICIES_URL_TEMPLATE.build(api.getBaseURL());
169    BoxJSONRequest request = new BoxJSONRequest(api, url, "POST");
170    JsonObject requestJSON =
171        new JsonObject()
172            .add("policy_name", name)
173            .add("policy_type", type.value)
174            .add("disposition_action", action.value);
175    if (type != BoxRetentionPolicyType.Indefinite) {
176      requestJSON.add("retention_length", length);
177    }
178    if (optionalParams != null) {
179      requestJSON.add("can_owner_extend_retention", optionalParams.getCanOwnerExtendRetention());
180      requestJSON.add("are_owners_notified", optionalParams.getAreOwnersNotified());
181      requestJSON.add("description", optionalParams.getDescription());
182      requestJSON.add("retention_type", optionalParams.getRetentionType().toJSONString());
183
184      List<BoxUser.Info> customNotificationRecipients =
185          optionalParams.getCustomNotificationRecipients();
186      if (customNotificationRecipients.size() > 0) {
187        JsonArray users = new JsonArray();
188        for (BoxUser.Info user : customNotificationRecipients) {
189          JsonObject userJSON = new JsonObject().add("type", "user").add("id", user.getID());
190          users.add(userJSON);
191        }
192        requestJSON.add("custom_notification_recipients", users);
193      }
194    }
195    request.setBody(requestJSON.toString());
196    try (BoxJSONResponse response = request.send()) {
197      JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
198      BoxRetentionPolicy createdPolicy =
199          new BoxRetentionPolicy(api, responseJSON.get("id").asString());
200      return createdPolicy.new Info(responseJSON);
201    }
202  }
203
204  /**
205   * Returns all the retention policies.
206   *
207   * @param api the API connection to be used by the resource.
208   * @param fields the fields to retrieve.
209   * @return an iterable with all the retention policies.
210   */
211  public static Iterable<BoxRetentionPolicy.Info> getAll(
212      final BoxAPIConnection api, String... fields) {
213    return getAll(null, null, null, DEFAULT_LIMIT, api, fields);
214  }
215
216  /**
217   * Returns all the retention policies with specified filters.
218   *
219   * @param name a name to filter the retention policies by. A trailing partial match search is
220   *     performed. Set to null if no name filtering is required.
221   * @param type a policy type to filter the retention policies by. Set to null if no type filtering
222   *     is required.
223   * @param userID a user id to filter the retention policies by. Set to null if no type filtering
224   *     is required.
225   * @param limit the limit of items per single response. The default value is 100.
226   * @param api the API connection to be used by the resource.
227   * @param fields the fields to retrieve.
228   * @return an iterable with all the retention policies met search conditions.
229   */
230  public static Iterable<BoxRetentionPolicy.Info> getAll(
231      String name,
232      String type,
233      String userID,
234      int limit,
235      final BoxAPIConnection api,
236      String... fields) {
237    QueryStringBuilder queryString = new QueryStringBuilder();
238    if (name != null) {
239      queryString.appendParam("policy_name", name);
240    }
241    if (type != null) {
242      queryString.appendParam("policy_type", type);
243    }
244    if (userID != null) {
245      queryString.appendParam("created_by_user_id", userID);
246    }
247    if (fields.length > 0) {
248      queryString.appendParam("fields", fields);
249    }
250    URL url =
251        RETENTION_POLICIES_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), queryString.toString());
252    return new BoxResourceIterable<BoxRetentionPolicy.Info>(api, url, limit) {
253
254      @Override
255      protected BoxRetentionPolicy.Info factory(JsonObject jsonObject) {
256        BoxRetentionPolicy policy = new BoxRetentionPolicy(api, jsonObject.get("id").asString());
257        return policy.new Info(jsonObject);
258      }
259    };
260  }
261
262  /**
263   * Returns iterable with all folder assignments of this retention policy.
264   *
265   * @param fields the fields to retrieve.
266   * @return an iterable containing all folder assignments.
267   */
268  public Iterable<BoxRetentionPolicyAssignment.Info> getFolderAssignments(String... fields) {
269    return this.getFolderAssignments(DEFAULT_LIMIT, fields);
270  }
271
272  /**
273   * Returns iterable with all folder assignments of this retention policy.
274   *
275   * @param limit the limit of entries per response. The default value is 100.
276   * @param fields the fields to retrieve.
277   * @return an iterable containing all folder assignments.
278   */
279  public Iterable<BoxRetentionPolicyAssignment.Info> getFolderAssignments(
280      int limit, String... fields) {
281    return this.getAssignments(BoxRetentionPolicyAssignment.TYPE_FOLDER, limit, fields);
282  }
283
284  /**
285   * Returns iterable with all enterprise assignments of this retention policy.
286   *
287   * @param fields the fields to retrieve.
288   * @return an iterable containing all enterprise assignments.
289   */
290  public Iterable<BoxRetentionPolicyAssignment.Info> getEnterpriseAssignments(String... fields) {
291    return this.getEnterpriseAssignments(DEFAULT_LIMIT, fields);
292  }
293
294  /**
295   * Returns iterable with all enterprise assignments of this retention policy.
296   *
297   * @param limit the limit of entries per response. The default value is 100.
298   * @param fields the fields to retrieve.
299   * @return an iterable containing all enterprise assignments.
300   */
301  public Iterable<BoxRetentionPolicyAssignment.Info> getEnterpriseAssignments(
302      int limit, String... fields) {
303    return this.getAssignments(BoxRetentionPolicyAssignment.TYPE_ENTERPRISE, limit, fields);
304  }
305
306  /**
307   * Returns iterable with all assignments of this retention policy.
308   *
309   * @param fields the fields to retrieve.
310   * @return an iterable containing all assignments.
311   */
312  public Iterable<BoxRetentionPolicyAssignment.Info> getAllAssignments(String... fields) {
313    return this.getAllAssignments(DEFAULT_LIMIT, fields);
314  }
315
316  /**
317   * Returns iterable with all assignments of this retention policy.
318   *
319   * @param limit the limit of entries per response. The default value is 100.
320   * @param fields the fields to retrieve.
321   * @return an iterable containing all assignments.
322   */
323  public Iterable<BoxRetentionPolicyAssignment.Info> getAllAssignments(
324      int limit, String... fields) {
325    return this.getAssignments(null, limit, fields);
326  }
327
328  /**
329   * Returns iterable with all assignments of given type of this retention policy.
330   *
331   * @param type the type of the retention policy assignment to retrieve. Can either be "folder" or
332   *     "enterprise".
333   * @param limit the limit of entries per response. The default value is 100.
334   * @param fields the fields to retrieve.
335   * @return an iterable containing all assignments of given type.
336   */
337  private Iterable<BoxRetentionPolicyAssignment.Info> getAssignments(
338      String type, int limit, String... fields) {
339    QueryStringBuilder queryString = new QueryStringBuilder();
340    if (type != null) {
341      queryString.appendParam("type", type);
342    }
343    if (fields.length > 0) {
344      queryString.appendParam("fields", fields);
345    }
346    URL url =
347        ASSIGNMENTS_URL_TEMPLATE.buildWithQuery(
348            getAPI().getBaseURL(), queryString.toString(), getID());
349    return new BoxResourceIterable<BoxRetentionPolicyAssignment.Info>(getAPI(), url, limit) {
350
351      @Override
352      protected BoxRetentionPolicyAssignment.Info factory(JsonObject jsonObject) {
353        BoxRetentionPolicyAssignment assignment =
354            new BoxRetentionPolicyAssignment(getAPI(), jsonObject.get("id").asString());
355        return assignment.new Info(jsonObject);
356      }
357    };
358  }
359
360  /**
361   * Assigns this retention policy to folder.
362   *
363   * @param folder the folder to assign policy to.
364   * @return info about created assignment.
365   */
366  public BoxRetentionPolicyAssignment.Info assignTo(BoxFolder folder) {
367    return BoxRetentionPolicyAssignment.createAssignmentToFolder(
368        this.getAPI(), this.getID(), folder.getID());
369  }
370
371  /**
372   * Assigns this retention policy to the current enterprise.
373   *
374   * @return info about created assignment.
375   */
376  public BoxRetentionPolicyAssignment.Info assignToEnterprise() {
377    return BoxRetentionPolicyAssignment.createAssignmentToEnterprise(this.getAPI(), this.getID());
378  }
379
380  /**
381   * Assigns this retention policy to a metadata template, optionally with certain field values.
382   *
383   * @param templateID the ID of the metadata template to apply to.
384   * @param fieldFilters optional field value filters.
385   * @return info about the created assignment.
386   */
387  public BoxRetentionPolicyAssignment.Info assignToMetadataTemplate(
388      String templateID, MetadataFieldFilter... fieldFilters) {
389    return assignToMetadataTemplate(templateID, null, fieldFilters);
390  }
391
392  /**
393   * Assigns this retention policy to a metadata template, optionally with certain field values.
394   *
395   * @param templateID the ID of the metadata template to apply to.
396   * @param startDateField the date the retention policy assignment begins. This field can be a date
397   *     field's metadata attribute key id.
398   * @param fieldFilters optional field value filters.
399   * @return info about the created assignment.
400   */
401  public BoxRetentionPolicyAssignment.Info assignToMetadataTemplate(
402      String templateID, String startDateField, MetadataFieldFilter... fieldFilters) {
403    return BoxRetentionPolicyAssignment.createAssignmentToMetadata(
404        this.getAPI(), this.getID(), templateID, startDateField, fieldFilters);
405  }
406
407  /**
408   * Updates the information about this retention policy with any info fields that have been
409   * modified locally.
410   *
411   * @param info the updated info.
412   */
413  public void updateInfo(BoxRetentionPolicy.Info info) {
414    URL url = POLICY_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
415    BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
416    request.setBody(info.getPendingChanges());
417    try (BoxJSONResponse response = request.send()) {
418      JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
419      info.update(responseJSON);
420    }
421  }
422
423  /**
424   * Returns information about this retention policy.
425   *
426   * @param fields the fields to retrieve.
427   * @return information about this retention policy.
428   */
429  public BoxRetentionPolicy.Info getInfo(String... fields) {
430    QueryStringBuilder builder = new QueryStringBuilder();
431    if (fields.length > 0) {
432      builder.appendParam("fields", fields);
433    }
434    URL url =
435        POLICY_URL_TEMPLATE.buildWithQuery(
436            this.getAPI().getBaseURL(), builder.toString(), this.getID());
437    BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "GET");
438    try (BoxJSONResponse response = request.send()) {
439      JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
440      return new Info(responseJSON);
441    }
442  }
443
444  /** Contains information about the retention policy. */
445  public class Info extends BoxResource.Info {
446
447    /** @see #getPolicyName() */
448    private String policyName;
449
450    /** @see #getPolicyType() */
451    private String policyType;
452
453    /** @see #getRetentionLength() */
454    private int retentionLength;
455
456    /** @see #getDispositionAction() */
457    private String dispositionAction;
458
459    /** @see #getStatus() */
460    private String status;
461
462    /** @see #getCreatedBy() */
463    private BoxUser.Info createdBy;
464
465    /** @see #getCreatedAt() */
466    private Date createdAt;
467
468    /** @see #getModifiedAt() */
469    private Date modifiedAt;
470
471    /** @see #getCanOwnerExtendRetention() */
472    private boolean canOwnerExtendRetention;
473
474    /** @see #getAreOwnersNotified() */
475    private boolean areOwnersNotified;
476
477    /** @see #getDescription() */
478    private String description;
479
480    /** @see #getRetentionType() */
481    private RetentionPolicyParams.RetentionType retentionType;
482
483    private List<BoxUser.Info> customNotificationRecipients;
484
485    /** Constructs an empty Info object. */
486    public Info() {
487      super();
488    }
489
490    /**
491     * Constructs an Info object by parsing information from a JSON string.
492     *
493     * @param json the JSON string to parse.
494     */
495    public Info(String json) {
496      super(json);
497    }
498
499    /**
500     * Constructs an Info object using an already parsed JSON object.
501     *
502     * @param jsonObject the parsed JSON object.
503     */
504    Info(JsonObject jsonObject) {
505      super(jsonObject);
506    }
507
508    /** {@inheritDoc} */
509    @Override
510    public BoxResource getResource() {
511      return BoxRetentionPolicy.this;
512    }
513
514    /**
515     * Gets the name given to the retention policy.
516     *
517     * @return name given to the retention policy.
518     */
519    public String getPolicyName() {
520      return this.policyName;
521    }
522
523    /**
524     * Update the policy name to a new value.
525     *
526     * @param policyName the new policy name.
527     */
528    public void setPolicyName(String policyName) {
529      this.policyName = policyName;
530      this.addPendingChange("policy_name", policyName);
531    }
532
533    /**
534     * Gets the type of the retention policy. A retention policy type can either be "finite", where
535     * a specific amount of time to retain the content is known upfront, or "indefinite", where the
536     * amount of time to retain the content is still unknown.
537     *
538     * @return the type of the retention policy.
539     */
540    public String getPolicyType() {
541      return this.policyType;
542    }
543
544    /**
545     * Gets the length of the retention policy. This length specifies the duration in days that the
546     * retention policy will be active for after being assigned to content.
547     *
548     * @return the length of the retention policy.
549     */
550    public int getRetentionLength() {
551      return this.retentionLength;
552    }
553
554    /** @param retentionLength The length of the retention policy. */
555    public void setRetentionLength(int retentionLength) {
556      this.retentionLength = retentionLength;
557      this.addPendingChange("retention_length", retentionLength);
558    }
559
560    /**
561     * Gets the disposition action of the retention policy. This action can be "permanently_delete",
562     * or "remove_retention".
563     *
564     * @return the disposition action of the retention policy.
565     */
566    public String getDispositionAction() {
567      return this.dispositionAction;
568    }
569
570    /**
571     * Set the action to take when retention period ends.
572     *
573     * @param dispositionAction the new action.
574     */
575    public void setDispositionAction(String dispositionAction) {
576      this.dispositionAction = dispositionAction;
577      this.addPendingChange("disposition_action", dispositionAction);
578    }
579
580    /**
581     * Gets the status of the retention policy. The status can be "active" or "retired".
582     *
583     * @return the status of the retention policy.
584     */
585    public String getStatus() {
586      return this.status;
587    }
588
589    /**
590     * Set the policy status.
591     *
592     * @param status the new status value.
593     */
594    public void setStatus(String status) {
595      this.status = status;
596      this.addPendingChange("status", status);
597    }
598
599    /**
600     * Gets info about the user created the retention policy.
601     *
602     * @return info about the user created the retention policy.
603     */
604    public BoxUser.Info getCreatedBy() {
605      return this.createdBy;
606    }
607
608    /**
609     * Gets the time that the retention policy was created.
610     *
611     * @return the time that the retention policy was created.
612     */
613    public Date getCreatedAt() {
614      return this.createdAt;
615    }
616
617    /**
618     * Gets the time that the retention policy was last modified.
619     *
620     * @return the time that the retention policy was last modified.
621     */
622    public Date getModifiedAt() {
623      return this.modifiedAt;
624    }
625
626    /**
627     * Gets the flag to denote that the owner of a retained file can extend the retention when near
628     * expiration.
629     *
630     * @return the boolean flag.
631     */
632    public boolean getCanOwnerExtendRetention() {
633      return this.canOwnerExtendRetention;
634    }
635
636    /**
637     * Gets the flag to denote that owners and co-owners of a retained file will get notified when
638     * near expiration.
639     *
640     * @return the boolean flag.
641     */
642    public boolean getAreOwnersNotified() {
643      return this.areOwnersNotified;
644    }
645
646    /**
647     * Gets the additional text desription of the retention policy.
648     *
649     * @return the additional text desription of the retention policy
650     */
651    public String getDescription() {
652      return this.description;
653    }
654
655    /**
656     * Set the additional text desription of the retention policy.
657     *
658     * @param description the new text desription of the retention policy
659     */
660    public void setDescription(String description) {
661      this.description = description;
662      this.addPendingChange("description", description);
663    }
664
665    /**
666     * @return retention type. It can be one of values: `modifiable` or `non-modifiable`.
667     *     `modifiable` means that you can modify the retention policy. For example, you can add or
668     *     remove folders, shorten or lengthen the policy duration, or delete the assignment.
669     *     `non-modifiable` means that can modify the retention policy only in a limited way: add a
670     *     folder, lengthen the duration, retire the policy, change the disposition action or
671     *     notification settings. You cannot perform other actions, such as deleting the assignment
672     *     or shortening the policy duration.
673     */
674    public RetentionPolicyParams.RetentionType getRetentionType() {
675      return retentionType;
676    }
677
678    /**
679     * It is not possible to set retention type to `modifiable` once it was set to `non-modifiable`.
680     */
681    public void setRetentionTypeToNonModifiable() {
682      this.retentionType = RetentionPolicyParams.RetentionType.NON_MODIFIABLE;
683      this.addPendingChange("retention_type", retentionType.toJSONString());
684    }
685
686    /**
687     * Gets the list of users to be notified of a retained file when near expiration.
688     *
689     * @return the list of users to be notified.
690     */
691    public List<BoxUser.Info> getCustomNotificationRecipients() {
692      return this.customNotificationRecipients;
693    }
694
695    /** {@inheritDoc} */
696    @Override
697    void parseJSONMember(JsonObject.Member member) {
698      super.parseJSONMember(member);
699      String memberName = member.getName();
700      JsonValue value = member.getValue();
701      try {
702        switch (memberName) {
703          case "policy_name":
704            this.policyName = value.asString();
705            break;
706          case "policy_type":
707            this.policyType = value.asString();
708            break;
709          case "retention_length":
710            int intVal;
711            if (value.asString().equals(BoxRetentionPolicyType.Indefinite.value)) {
712              intVal = -1;
713            } else {
714              intVal = Integer.parseInt(value.asString());
715            }
716            this.retentionLength = intVal;
717            break;
718          case "disposition_action":
719            this.dispositionAction = value.asString();
720            break;
721          case "status":
722            this.status = value.asString();
723            break;
724          case "created_by":
725            JsonObject userJSON = value.asObject();
726            if (this.createdBy == null) {
727              String userID = userJSON.get("id").asString();
728              BoxUser user = new BoxUser(getAPI(), userID);
729              this.createdBy = user.new Info(userJSON);
730            } else {
731              this.createdBy.update(userJSON);
732            }
733            break;
734          case "created_at":
735            this.createdAt = BoxDateFormat.parse(value.asString());
736            break;
737          case "modified_at":
738            this.modifiedAt = BoxDateFormat.parse(value.asString());
739            break;
740          case "can_owner_extend_retention":
741            this.canOwnerExtendRetention = value.asBoolean();
742            break;
743          case "are_owners_notified":
744            this.areOwnersNotified = value.asBoolean();
745            break;
746          case "description":
747            this.description = value.asString();
748            break;
749          case "retention_type":
750            this.retentionType =
751                RetentionPolicyParams.RetentionType.fromJSONString(value.asString());
752            break;
753          case "custom_notification_recipients":
754            List<BoxUser.Info> recipients = new ArrayList<>();
755            for (JsonValue recipientJSON : value.asArray()) {
756              String userID = recipientJSON.asObject().get("id").asString();
757              BoxUser user = new BoxUser(getAPI(), userID);
758              recipients.add(user.new Info(recipientJSON.asObject()));
759            }
760            this.customNotificationRecipients = recipients;
761            break;
762          default:
763            break;
764        }
765      } catch (Exception e) {
766        throw new BoxDeserializationException(memberName, value.toString(), e);
767      }
768    }
769  }
770
771  private enum BoxRetentionPolicyType {
772    /** Type for finite retention policies. Finite retention policies has the duration. */
773    Finite("finite"),
774    /**
775     * Type for indefinite retention policies. Indefinite retention policies can have only {@link
776     * BoxRetentionPolicyAction#RemoveRetention} assigned action.
777     */
778    Indefinite("indefinite");
779
780    private final String value;
781
782    BoxRetentionPolicyType(String value) {
783      this.value = value;
784    }
785  }
786
787  /** The disposition action of the retention policy. */
788  public enum BoxRetentionPolicyAction {
789    /** Will cause the content retained by the policy to be permanently deleted. */
790    PermanentlyDelete("permanently_delete"),
791
792    /** Will lift the retention policy from the content, allowing it to be deleted by users. */
793    RemoveRetention("remove_retention");
794
795    private final String value;
796
797    BoxRetentionPolicyAction(String value) {
798      this.value = value;
799    }
800  }
801}