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