001package com.box.sdk;
002
003import java.net.URL;
004import java.text.ParseException;
005import java.util.Date;
006
007import com.eclipsesource.json.JsonObject;
008import com.eclipsesource.json.JsonValue;
009
010/**
011 * Represents a retention policy.
012 * A retention policy blocks permanent deletion of content for a specified amount of time.
013 * Admins can create retention policies and then later assign them to specific folders or their entire enterprise.
014 *
015 * @see <a href="https://docs.box.com/reference#retention-policy-object">Box retention policy</a>
016 *
017 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked
018 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error
019 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p>
020 */
021@BoxResourceType("retention_policy")
022public class BoxRetentionPolicy extends BoxResource {
023
024    /**
025     *  Will cause the content retained by the policy to be permanently deleted.
026     */
027    public static final String ACTION_PERMANENTLY_DELETE = "permanently_delete";
028
029    /**
030     * Will lift the retention policy from the content, allowing it to be deleted by users.
031     */
032    public static final String ACTION_REMOVE_RETENTION = "remove_retention";
033
034    /**
035     * Status corresponding to active retention policy.
036     */
037    public static final String STATUS_ACTIVE = "active";
038
039    /**
040     * Status corresponding to retired retention policy.
041     */
042    public static final String STATUS_RETIRED = "retired";
043
044    /**
045     * Type for finite retention policies. Finite retention policies has the duration.
046     */
047    private static final String TYPE_FINITE = "finite";
048
049    /**
050     * Type for indefinite retention policies. Indefinite retention policies can have only "remove_retention"
051     * assigned action.
052     */
053    private static final String TYPE_INDEFINITE = "indefinite";
054
055    /**
056     * The default limit of entries per response.
057     */
058    private static final int DEFAULT_LIMIT = 100;
059
060    /**
061     * The URL template used for operation with retention policies.
062     */
063    private static final URLTemplate RETENTION_POLICIES_URL_TEMPLATE = new URLTemplate("retention_policies");
064
065    /**
066     * The URL template used for operation with retention policy with given ID.
067     */
068    private static final URLTemplate POLICY_URL_TEMPLATE = new URLTemplate("retention_policies/%s");
069
070    /**
071     * The URL template used for operation with retention policy assignments.
072     */
073    private static final URLTemplate ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("retention_policies/%s/assignments");
074
075    /**
076     * Constructs a retention policy for a resource with a given ID.
077     *
078     * @param api the API connection to be used by the resource.
079     * @param id  the ID of the resource.
080     */
081    public BoxRetentionPolicy(BoxAPIConnection api, String id) {
082        super(api, id);
083    }
084
085    /**
086     * Used to create a new indefinite retention policy.
087     * @param api the API connection to be used by the created user.
088     * @param name the name of the retention policy.
089     * @return the created retention policy's info.
090     */
091    public static BoxRetentionPolicy.Info createIndefinitePolicy(BoxAPIConnection api, String name) {
092        return createRetentionPolicy(api, name, TYPE_INDEFINITE, 0, ACTION_REMOVE_RETENTION);
093    }
094
095    /**
096     * Used to create a new finite retention policy.
097     * @param api the API connection to be used by the created user.
098     * @param name the name of the retention policy.
099     * @param length the duration in days that the retention policy will be active for after being 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(BoxAPIConnection api, String name, int length,
104                                                                      String action) {
105        return createRetentionPolicy(api, name, TYPE_FINITE, length, action);
106    }
107
108    /**
109     * Used to create a new 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 type the type of the retention policy. Can be "finite" or "indefinite".
113     * @param length the duration in days that the retention policy will be active for after being assigned to content.
114     * @param action the disposition action can be "permanently_delete" or "remove_retention".
115     * @return the created retention policy's info.
116     */
117    private static BoxRetentionPolicy.Info createRetentionPolicy(BoxAPIConnection api, String name, String type,
118                                                                int length, String action) {
119        URL url = RETENTION_POLICIES_URL_TEMPLATE.build(api.getBaseURL());
120        BoxJSONRequest request = new BoxJSONRequest(api, url, "POST");
121        JsonObject requestJSON = new JsonObject()
122                .add("policy_name", name)
123                .add("policy_type", type)
124                .add("disposition_action", action);
125        if (!type.equals(TYPE_INDEFINITE)) {
126            requestJSON.add("retention_length", length);
127        }
128        request.setBody(requestJSON.toString());
129        BoxJSONResponse response = (BoxJSONResponse) request.send();
130        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
131        BoxRetentionPolicy createdPolicy = new BoxRetentionPolicy(api, responseJSON.get("id").asString());
132        return createdPolicy.new Info(responseJSON);
133    }
134
135    /**
136     * Returns iterable with all folder assignments of this retention policy.
137     * @param fields the fields to retrieve.
138     * @return an iterable containing all folder assignments.
139     */
140    public Iterable<BoxRetentionPolicyAssignment.Info> getFolderAssignments(String ... fields) {
141        return this.getFolderAssignments(DEFAULT_LIMIT, fields);
142    }
143
144    /**
145     * Returns iterable with all folder assignments of this retention policy.
146     * @param limit the limit of entries per response. The default value is 100.
147     * @param fields the fields to retrieve.
148     * @return an iterable containing all folder assignments.
149     */
150    public Iterable<BoxRetentionPolicyAssignment.Info> getFolderAssignments(int limit, String ... fields) {
151        return this.getAssignments(BoxRetentionPolicyAssignment.TYPE_FOLDER, limit, fields);
152    }
153
154    /**
155     * Returns iterable with all enterprise assignments of this retention policy.
156     * @param fields the fields to retrieve.
157     * @return an iterable containing all enterprise assignments.
158     */
159    public Iterable<BoxRetentionPolicyAssignment.Info> getEnterpriseAssignments(String ... fields) {
160        return this.getEnterpriseAssignments(DEFAULT_LIMIT, fields);
161    }
162
163    /**
164     * Returns iterable with all enterprise assignments of this retention policy.
165     * @param limit the limit of entries per response. The default value is 100.
166     * @param fields the fields to retrieve.
167     * @return an iterable containing all enterprise assignments.
168     */
169    public Iterable<BoxRetentionPolicyAssignment.Info> getEnterpriseAssignments(int limit, String ... fields) {
170        return this.getAssignments(BoxRetentionPolicyAssignment.TYPE_ENTERPRISE, limit, fields);
171    }
172
173    /**
174     * Returns iterable with all assignments of this retention policy.
175     * @param fields the fields to retrieve.
176     * @return an iterable containing all assignments.
177     */
178    public Iterable<BoxRetentionPolicyAssignment.Info> getAllAssignments(String ... fields) {
179        return this.getAllAssignments(DEFAULT_LIMIT, fields);
180    }
181
182    /**
183     * Returns iterable with all assignments of this retention policy.
184     * @param limit the limit of entries per response. The default value is 100.
185     * @param fields the fields to retrieve.
186     * @return an iterable containing all assignments.
187     */
188    public Iterable<BoxRetentionPolicyAssignment.Info> getAllAssignments(int limit, String ... fields) {
189        return this.getAssignments(null, limit, fields);
190    }
191
192    /**
193     * Returns iterable with all assignments of given type of this retention policy.
194     * @param type the type of the retention policy assignment to retrieve. Can either be "folder" or "enterprise".
195     * @param limit the limit of entries per response. The default value is 100.
196     * @param fields the fields to retrieve.
197     * @return an iterable containing all assignments of given type.
198     */
199    private Iterable<BoxRetentionPolicyAssignment.Info> getAssignments(String type, int limit, String ... fields) {
200        QueryStringBuilder queryString = new QueryStringBuilder();
201        if (type != null) {
202            queryString.appendParam("type", type);
203        }
204        if (fields.length > 0) {
205            queryString.appendParam("fields", fields);
206        }
207        URL url = ASSIGNMENTS_URL_TEMPLATE.buildWithQuery(getAPI().getBaseURL(), queryString.toString(), getID());
208        return new BoxResourceIterable<BoxRetentionPolicyAssignment.Info>(getAPI(), url, limit) {
209
210            @Override
211            protected BoxRetentionPolicyAssignment.Info factory(JsonObject jsonObject) {
212                BoxRetentionPolicyAssignment assignment
213                    = new BoxRetentionPolicyAssignment(getAPI(), jsonObject.get("id").asString());
214                return assignment.new Info(jsonObject);
215            }
216
217        };
218    }
219
220    /**
221     * Assigns this retention policy to folder.
222     * @param folder the folder to assign policy to.
223     * @return info about created assignment.
224     */
225    public BoxRetentionPolicyAssignment.Info assignTo(BoxFolder folder) {
226        return BoxRetentionPolicyAssignment.createAssignmentToFolder(this.getAPI(), this.getID(), folder.getID());
227    }
228
229    /**
230     * Assigns this retention policy to the current enterprise.
231     * @return info about created assignment.
232     */
233    public BoxRetentionPolicyAssignment.Info assignToEnterprise() {
234        return BoxRetentionPolicyAssignment.createAssignmentToEnterprise(this.getAPI(), this.getID());
235    }
236
237    /**
238     * Updates the information about this retention policy with any info fields that have been modified locally.
239     * @param info the updated info.
240     */
241    public void updateInfo(BoxRetentionPolicy.Info info) {
242        URL url = POLICY_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
243        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
244        request.setBody(info.getPendingChanges());
245        BoxJSONResponse response = (BoxJSONResponse) request.send();
246        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
247        info.update(responseJSON);
248    }
249
250    /**
251     * Returns information about this retention policy.
252     * @param fields the fields to retrieve.
253     * @return information about this retention policy.
254     */
255    public BoxRetentionPolicy.Info getInfo(String ... fields) {
256        QueryStringBuilder builder = new QueryStringBuilder();
257        if (fields.length > 0) {
258            builder.appendParam("fields", fields);
259        }
260        URL url = POLICY_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID());
261        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
262        BoxJSONResponse response = (BoxJSONResponse) request.send();
263        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
264        return new Info(responseJSON);
265    }
266
267
268    /**
269     * Returns all the retention policies.
270     * @param api the API connection to be used by the resource.
271     * @param fields the fields to retrieve.
272     * @return an iterable with all the retention policies.
273     */
274    public static Iterable<BoxRetentionPolicy.Info> getAll(final BoxAPIConnection api, String ... fields) {
275        return getAll(null, null, null, DEFAULT_LIMIT, api, fields);
276    }
277
278    /**
279     * Returns all the retention policies with specified filters.
280     * @param name a name to filter the retention policies by. A trailing partial match search is performed.
281     *             Set to null if no name filtering is required.
282     * @param type a policy type to filter the retention policies by. Set to null if no type filtering is required.
283     * @param userID a user id to filter the retention policies by. Set to null if no type filtering is required.
284     * @param limit the limit of items per single response. The default value is 100.
285     * @param api the API connection to be used by the resource.
286     * @param fields the fields to retrieve.
287     * @return an iterable with all the retention policies met search conditions.
288     */
289    public static Iterable<BoxRetentionPolicy.Info> getAll(
290            String name, String type, String userID, int limit, final BoxAPIConnection api, String ... fields) {
291        QueryStringBuilder queryString = new QueryStringBuilder();
292        if (name != null) {
293            queryString.appendParam("policy_name", name);
294        }
295        if (type != null) {
296            queryString.appendParam("policy_type", type);
297        }
298        if (userID != null) {
299            queryString.appendParam("created_by_user_id", userID);
300        }
301        if (fields.length > 0) {
302            queryString.appendParam("fields", fields);
303        }
304        URL url = RETENTION_POLICIES_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), queryString.toString());
305        return new BoxResourceIterable<BoxRetentionPolicy.Info>(api, url, limit) {
306
307            @Override
308            protected BoxRetentionPolicy.Info factory(JsonObject jsonObject) {
309                BoxRetentionPolicy policy = new BoxRetentionPolicy(api, jsonObject.get("id").asString());
310                return policy.new Info(jsonObject);
311            }
312
313        };
314    }
315
316    /**
317     * Contains information about the retention policy.
318     */
319    public class Info extends BoxResource.Info {
320
321        /**
322         * @see #getPolicyName()
323         */
324        private String policyName;
325
326        /**
327         * @see #getPolicyType()
328         */
329        private String policyType;
330
331        /**
332         * @see #getRetentionLength()
333         */
334        private int retentionLength;
335
336        /**
337         * @see #getDispositionAction()
338         */
339        private String dispositionAction;
340
341        /**
342         * @see #getStatus()
343         */
344        private String status;
345
346        /**
347         * @see #getCreatedBy()
348         */
349        private BoxUser.Info createdBy;
350
351        /**
352         * @see #getCreatedAt()
353         */
354        private Date createdAt;
355
356        /**
357         * @see #getModifiedAt()
358         */
359        private Date modifiedAt;
360
361        /**
362         * Constructs an empty Info object.
363         */
364        public Info() {
365            super();
366        }
367
368        /**
369         * Constructs an Info object by parsing information from a JSON string.
370         * @param  json the JSON string to parse.
371         */
372        public Info(String json) {
373            super(json);
374        }
375
376        /**
377         * Constructs an Info object using an already parsed JSON object.
378         * @param  jsonObject the parsed JSON object.
379         */
380        Info(JsonObject jsonObject) {
381            super(jsonObject);
382        }
383
384        /**
385         * {@inheritDoc}
386         */
387        @Override
388        public BoxResource getResource() {
389            return BoxRetentionPolicy.this;
390        }
391
392        /**
393         * Gets the name given to the retention policy.
394         * @return name given to the retention policy.
395         */
396        public String getPolicyName() {
397            return this.policyName;
398        }
399
400        /**
401         * Gets the type of the retention policy.
402         * A retention policy type can either be "finite",
403         * where a specific amount of time to retain the content is known upfront,
404         * or "indefinite", where the amount of time to retain the content is still unknown.
405         * @return the type of the retention policy.
406         */
407        public String getPolicyType() {
408            return this.policyType;
409        }
410
411        /**
412         * Gets the length of the retention policy. This length specifies the duration
413         * in days that the retention policy will be active for after being assigned to content.
414         * @return the length of the retention policy.
415         */
416        public int getRetentionLength() {
417            return this.retentionLength;
418        }
419
420        /**
421         * Gets the disposition action of the retention policy.
422         * This action can be "permanently_delete", or "remove_retention".
423         * @return the disposition action of the retention policy.
424         */
425        public String getDispositionAction() {
426            return this.dispositionAction;
427        }
428
429        /**
430         * Gets the status of the retention policy.
431         * The status can be "active" or "retired".
432         * @return the status of the retention policy.
433         */
434        public String getStatus() {
435            return this.status;
436        }
437
438        /**
439         * Gets info about the user created the retention policy.
440         * @return info about the user created the retention policy.
441         */
442        public BoxUser.Info getCreatedBy() {
443            return this.createdBy;
444        }
445
446        /**
447         * Gets the time that the retention policy was created.
448         * @return the time that the retention policy was created.
449         */
450        public Date getCreatedAt() {
451            return this.createdAt;
452        }
453
454        /**
455         * Gets the time that the retention policy was last modified.
456         * @return the time that the retention policy was last modified.
457         */
458        public Date getModifiedAt() {
459            return this.modifiedAt;
460        }
461
462        /**
463         * {@inheritDoc}
464         */
465        @Override
466        void parseJSONMember(JsonObject.Member member) {
467            super.parseJSONMember(member);
468            String memberName = member.getName();
469            JsonValue value = member.getValue();
470            try {
471                if (memberName.equals("policy_name")) {
472                    this.policyName = value.asString();
473                } else if (memberName.equals("policy_type")) {
474                    this.policyType = value.asString();
475                } else if (memberName.equals("retention_length")) {
476                    this.retentionLength = value.asInt();
477                } else if (memberName.equals("disposition_action")) {
478                    this.dispositionAction = value.asString();
479                } else if (memberName.equals("status")) {
480                    this.status = value.asString();
481                } else if (memberName.equals("created_by")) {
482                    JsonObject userJSON = value.asObject();
483                    if (this.createdBy == null) {
484                        String userID = userJSON.get("id").asString();
485                        BoxUser user = new BoxUser(getAPI(), userID);
486                        this.createdBy = user.new Info(userJSON);
487                    } else {
488                        this.createdBy.update(userJSON);
489                    }
490                } else if (memberName.equals("created_at")) {
491                    this.createdAt = BoxDateFormat.parse(value.asString());
492                } else if (memberName.equals("modified_at")) {
493                    this.modifiedAt = BoxDateFormat.parse(value.asString());
494                }
495            } catch (ParseException e) {
496                assert false : "A ParseException indicates a bug in the SDK.";
497            }
498        }
499    }
500}