001package com.box.sdk;
002
003import com.eclipsesource.json.JsonObject;
004import com.eclipsesource.json.JsonValue;
005import java.net.URL;
006import java.util.Date;
007
008/**
009 * Represents a legal hold policy. Legal Hold Policy information describes the basic characteristics of the Policy, such
010 * as name, description, and filter dates.
011 *
012 * @see <a href="https://developer.box.com/reference/resources/legal-hold-policy/">Box legal holds</a>
013 *
014 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked
015 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error
016 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p>
017 */
018@BoxResourceType("legal_hold")
019public class BoxLegalHoldPolicy extends BoxResource {
020    /**
021     * Legal Hold URL Template.
022     */
023    public static final URLTemplate LEGAL_HOLD_URL_TEMPLATE = new URLTemplate("legal_hold_policies/%s");
024    /**
025     * All Legal Hold URL Template.
026     */
027    public static final URLTemplate ALL_LEGAL_HOLD_URL_TEMPLATE = new URLTemplate("legal_hold_policies");
028    /**
029     * Legal Hold Assignments URL Template.
030     */
031    public static final URLTemplate LEGAL_HOLD_ASSIGNMENTS_URL_TEMPLATE
032        = new URLTemplate("legal_hold_policies/%s/assignments");
033    /**
034     * List of File Version Holds URL Template.
035     */
036    public static final URLTemplate LIST_OF_FILE_VERSION_HOLDS_URL_TEMPLATE
037        = new URLTemplate("file_version_legal_holds");
038    private static final int DEFAULT_LIMIT = 100;
039
040    /**
041     * Constructs a BoxLegalHoldPolicy for a resource with a given ID.
042     *
043     * @param api the API connection to be used by the resource.
044     * @param id  the ID of the resource.
045     */
046    public BoxLegalHoldPolicy(BoxAPIConnection api, String id) {
047        super(api, id);
048    }
049
050    /**
051     * Creates a new Legal Hold Policy.
052     *
053     * @param api  the API connection to be used by the resource.
054     * @param name the name of Legal Hold Policy.
055     * @return information about the Legal Hold Policy created.
056     */
057    public static BoxLegalHoldPolicy.Info create(BoxAPIConnection api, String name) {
058        return createOngoing(api, name, null);
059    }
060
061    /**
062     * Creates a new Legal Hold Policy.
063     *
064     * @param api             the API connection to be used by the resource.
065     * @param name            the name of Legal Hold Policy.
066     * @param description     the description of Legal Hold Policy.
067     * @param filterStartedAt optional date filter applies to Custodian assignments only.
068     * @param filterEndedAt   optional date filter applies to Custodian assignments only.
069     * @return information about the Legal Hold Policy created.
070     */
071    public static BoxLegalHoldPolicy.Info create(BoxAPIConnection api, String name, String description,
072                                                 Date filterStartedAt, Date filterEndedAt) {
073        URL url = ALL_LEGAL_HOLD_URL_TEMPLATE.build(api.getBaseURL());
074        BoxJSONRequest request = new BoxJSONRequest(api, url, "POST");
075        JsonObject requestJSON = new JsonObject()
076            .add("policy_name", name);
077        if (description != null) {
078            requestJSON.add("description", description);
079        }
080        if (filterStartedAt != null) {
081            requestJSON.add("filter_started_at", BoxDateFormat.format(filterStartedAt));
082        }
083        if (filterEndedAt != null) {
084            requestJSON.add("filter_ended_at", BoxDateFormat.format(filterEndedAt));
085        }
086        request.setBody(requestJSON.toString());
087        BoxJSONResponse response = (BoxJSONResponse) request.send();
088        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
089        BoxLegalHoldPolicy createdPolicy = new BoxLegalHoldPolicy(api, responseJSON.get("id").asString());
090        return createdPolicy.new Info(responseJSON);
091    }
092
093    /**
094     * Creates a new ongoing Legal Hold Policy.
095     *
096     * @param api         the API connection to be used by the resource.
097     * @param name        the name of Legal Hold Policy.
098     * @param description the description of Legal Hold Policy.
099     * @return information about the Legal Hold Policy created.
100     */
101    public static BoxLegalHoldPolicy.Info createOngoing(BoxAPIConnection api, String name, String description) {
102        URL url = ALL_LEGAL_HOLD_URL_TEMPLATE.build(api.getBaseURL());
103        BoxJSONRequest request = new BoxJSONRequest(api, url, "POST");
104        JsonObject requestJSON = new JsonObject()
105            .add("policy_name", name)
106            .add("is_ongoing", true);
107        if (description != null) {
108            requestJSON.add("description", description);
109        }
110        request.setBody(requestJSON.toString());
111        BoxJSONResponse response = (BoxJSONResponse) request.send();
112        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
113        BoxLegalHoldPolicy createdPolicy = new BoxLegalHoldPolicy(api, responseJSON.get("id").asString());
114        return createdPolicy.new Info(responseJSON);
115    }
116
117    /**
118     * Retrieves a list of Legal Hold Policies that belong to your Enterprise as an Iterable.
119     *
120     * @param api api the API connection to be used by the resource.
121     * @return the Iterable of Legal Hold Policies in your Enterprise.
122     */
123    public static Iterable<BoxLegalHoldPolicy.Info> getAll(final BoxAPIConnection api) {
124        return getAll(api, null, DEFAULT_LIMIT);
125    }
126
127    /**
128     * Retrieves a list of Legal Hold Policies that belong to your Enterprise as an Iterable.
129     *
130     * @param api        api the API connection to be used by the resource.
131     * @param policyName case insensitive prefix-match filter on Policy name.
132     * @param limit      the limit of retrieved entries per page.
133     * @param fields     the optional fields to retrieve.
134     * @return the Iterable of Legal Hold Policies in your Enterprise that match the filter parameters.
135     */
136    public static Iterable<BoxLegalHoldPolicy.Info> getAll(
137        final BoxAPIConnection api, String policyName, int limit, String... fields) {
138        QueryStringBuilder builder = new QueryStringBuilder();
139        if (policyName != null) {
140            builder.appendParam("policy_name", policyName);
141        }
142        if (fields.length > 0) {
143            builder.appendParam("fields", fields);
144        }
145        return new BoxResourceIterable<BoxLegalHoldPolicy.Info>(api,
146            ALL_LEGAL_HOLD_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString()),
147            limit) {
148
149            @Override
150            protected BoxLegalHoldPolicy.Info factory(JsonObject jsonObject) {
151                BoxLegalHoldPolicy policy = new BoxLegalHoldPolicy(api, jsonObject.get("id").asString());
152                return policy.new Info(jsonObject);
153            }
154        };
155    }
156
157    /**
158     * Gets information about the Legal Hold.
159     *
160     * @param fields the fields to retrieve.
161     * @return information about this legal hold policy.
162     */
163    public Info getInfo(String... fields) {
164        QueryStringBuilder builder = new QueryStringBuilder();
165        if (fields.length > 0) {
166            builder.appendParam("fields", fields);
167        }
168        URL url = LEGAL_HOLD_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID());
169        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
170        BoxJSONResponse response = (BoxJSONResponse) request.send();
171        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
172        return new Info(responseJSON);
173    }
174
175    /**
176     * Deletes the legal hold policy.
177     */
178    public void delete() {
179        URL url = LEGAL_HOLD_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
180        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
181        BoxAPIResponse response = request.send();
182        response.disconnect();
183    }
184
185    /**
186     * Updates the information about this retention policy with modified locally info.
187     * Only policy_name, description and release_notes can be modified.
188     *
189     * @param info the updated info.
190     */
191    public void updateInfo(BoxLegalHoldPolicy.Info info) {
192        URL url = LEGAL_HOLD_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
193        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
194        request.setBody(info.getPendingChanges());
195        BoxJSONResponse response = (BoxJSONResponse) request.send();
196        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
197        info.update(responseJSON);
198    }
199
200    /**
201     * Assigns this legal holds policy to the given box resource.
202     * Currently only {@link BoxFile}, {@link BoxFileVersion}, {@link BoxFolder} and {@link BoxUser} are supported.
203     *
204     * @param resource the box resource to assign legal hold policy to.
205     * @return info about created legal hold policy assignment.
206     */
207    public BoxLegalHoldAssignment.Info assignTo(BoxResource resource) {
208        return BoxLegalHoldAssignment.create(
209            this.getAPI(), this.getID(), BoxResource.getResourceType(resource.getClass()), resource.getID());
210    }
211
212    /**
213     * Returns iterable containing assignments for this single legal hold policy.
214     *
215     * @param fields the fields to retrieve.
216     * @return an iterable containing assignments for this single legal hold policy.
217     */
218    public Iterable<BoxLegalHoldAssignment.Info> getAssignments(String... fields) {
219        return this.getAssignments(null, null, DEFAULT_LIMIT, fields);
220    }
221
222    /**
223     * Returns iterable containing assignments for this single legal hold policy.
224     * Parameters can be used to filter retrieved assignments.
225     *
226     * @param type   filter assignments of this type only.
227     *               Can be "file_version", "file", "folder", "user" or null if no type filter is necessary.
228     * @param id     filter assignments to this ID only. Can be null if no id filter is necessary.
229     * @param limit  the limit of entries per page. Default limit is 100.
230     * @param fields the fields to retrieve.
231     * @return an iterable containing assignments for this single legal hold policy.
232     */
233    public Iterable<BoxLegalHoldAssignment.Info> getAssignments(String type, String id, int limit, String... fields) {
234        QueryStringBuilder builder = new QueryStringBuilder();
235        if (type != null) {
236            builder.appendParam("assign_to_type", type);
237        }
238        if (id != null) {
239            builder.appendParam("assign_to_id", id);
240        }
241        if (fields.length > 0) {
242            builder.appendParam("fields", fields);
243        }
244        return new BoxResourceIterable<BoxLegalHoldAssignment.Info>(
245            this.getAPI(), LEGAL_HOLD_ASSIGNMENTS_URL_TEMPLATE.buildWithQuery(
246            this.getAPI().getBaseURL(), builder.toString(), this.getID()), limit) {
247
248            @Override
249            protected BoxLegalHoldAssignment.Info factory(JsonObject jsonObject) {
250                BoxLegalHoldAssignment assignment = new BoxLegalHoldAssignment(
251                    BoxLegalHoldPolicy.this.getAPI(), jsonObject.get("id").asString());
252                return assignment.new Info(jsonObject);
253            }
254        };
255    }
256
257    /**
258     * Returns iterable with all non-deleted file version legal holds for this legal hold policy.
259     *
260     * @param fields the fields to retrieve.
261     * @return an iterable containing file version legal holds info.
262     */
263    public Iterable<BoxFileVersionLegalHold.Info> getFileVersionHolds(String... fields) {
264        return this.getFileVersionHolds(DEFAULT_LIMIT, fields);
265    }
266
267    /**
268     * Returns iterable with all non-deleted file version legal holds for this legal hold policy.
269     *
270     * @param limit  the limit of entries per response. The default value is 100.
271     * @param fields the fields to retrieve.
272     * @return an iterable containing file version legal holds info.
273     */
274    public Iterable<BoxFileVersionLegalHold.Info> getFileVersionHolds(int limit, String... fields) {
275        QueryStringBuilder queryString = new QueryStringBuilder().appendParam("policy_id", this.getID());
276        if (fields.length > 0) {
277            queryString.appendParam("fields", fields);
278        }
279        URL url = LIST_OF_FILE_VERSION_HOLDS_URL_TEMPLATE.buildWithQuery(getAPI().getBaseURL(), queryString.toString());
280        return new BoxResourceIterable<BoxFileVersionLegalHold.Info>(getAPI(), url, limit) {
281
282            @Override
283            protected BoxFileVersionLegalHold.Info factory(JsonObject jsonObject) {
284                BoxFileVersionLegalHold assignment
285                    = new BoxFileVersionLegalHold(getAPI(), jsonObject.get("id").asString());
286                return assignment.new Info(jsonObject);
287            }
288
289        };
290    }
291
292    /**
293     * Contains information about the legal hold policy.
294     */
295    public class Info extends BoxResource.Info {
296
297        /**
298         * @see #getPolicyName()
299         */
300        private String policyName;
301
302        /**
303         * @see #getDescription()
304         */
305        private String description;
306
307        /**
308         * @see #getStatus()
309         */
310        private String status;
311
312        /**
313         * @see #getAssignmentCountUser()
314         */
315        private int assignmentCountUser;
316
317        /**
318         * @see #getAssignmentCountFolder()
319         */
320        private int assignmentCountFolder;
321
322        /**
323         * @see #getAssignmentCountFile()
324         */
325        private int assignmentCountFile;
326
327        /**
328         * @see #getAssignmentCountFileVersion()
329         */
330        private int assignmentCountFileVersion;
331
332        /**
333         * @see #getCreatedAt()
334         */
335        private BoxUser.Info createdBy;
336
337        /**
338         * @see #getCreatedAt()
339         */
340        private Date createdAt;
341
342        /**
343         * @see #getModifiedAt()
344         */
345        private Date modifiedAt;
346
347        /**
348         * @see #getDeletedAt()
349         */
350        private Date deletedAt;
351
352        /**
353         * @see #getFilterStartedAt()
354         */
355        private Date filterStartedAt;
356
357        /**
358         * @see #getFilterEndedAt()
359         */
360        private Date filterEndedAt;
361
362        /**
363         * @see #getReleaseNotes()
364         */
365        private String releaseNotes;
366
367        /**
368         * @see #getIsOngoing()
369         */
370        private Boolean isOngoing;
371
372        /**
373         * Constructs an empty Info object.
374         */
375        public Info() {
376            super();
377        }
378
379        /**
380         * Constructs an Info object by parsing information from a JSON string.
381         *
382         * @param json the JSON string to parse.
383         */
384        public Info(String json) {
385            super(json);
386        }
387
388        /**
389         * Constructs an Info object using an already parsed JSON object.
390         *
391         * @param jsonObject the parsed JSON object.
392         */
393        Info(JsonObject jsonObject) {
394            super(jsonObject);
395        }
396
397        /**
398         * {@inheritDoc}
399         */
400        @Override
401        public BoxResource getResource() {
402            return BoxLegalHoldPolicy.this;
403        }
404
405        /**
406         * @return the name of the policy.
407         */
408        public String getPolicyName() {
409            return this.policyName;
410        }
411
412        /**
413         * Sets the policy's name.
414         *
415         * @param policyName the policy's new name.
416         */
417        public void setPolicyName(String policyName) {
418            this.policyName = policyName;
419            this.addPendingChange("policy_name", policyName);
420        }
421
422        /**
423         * @return the description of the policy.
424         */
425        public String getDescription() {
426            return this.description;
427        }
428
429        /**
430         * Sets the policy's description.
431         *
432         * @param description the policy's new description.
433         */
434        public void setDescription(String description) {
435            this.description = description;
436            this.addPendingChange("description", description);
437        }
438
439        /**
440         * Status can be "active", "applying", "releasing" or "released".
441         *
442         * @return the status of the policy.
443         */
444        public String getStatus() {
445            return this.status;
446        }
447
448        /**
449         * @return count of users this policy assigned to.
450         */
451        public int getAssignmentCountUser() {
452            return this.assignmentCountUser;
453        }
454
455        /**
456         * @return count of folders this policy assigned to.
457         */
458        public int getAssignmentCountFolder() {
459            return this.assignmentCountFolder;
460        }
461
462        /**
463         * @return count of files this policy assigned to.
464         */
465        public int getAssignmentCountFile() {
466            return this.assignmentCountFile;
467        }
468
469        /**
470         * @return count of file versions this policy assigned to.
471         */
472        public int getAssignmentCountFileVersion() {
473            return this.assignmentCountFileVersion;
474        }
475
476        /**
477         * @return info about the user who created this policy.
478         */
479        public BoxUser.Info getCreatedBy() {
480            return this.createdBy;
481        }
482
483        /**
484         * @return time the policy was created.
485         */
486        public Date getCreatedAt() {
487            return this.createdAt;
488        }
489
490        /**
491         * @return time the policy was modified.
492         */
493        public Date getModifiedAt() {
494            return this.modifiedAt;
495        }
496
497        /**
498         * @return time that the policy release request was sent.
499         */
500        public Date getDeletedAt() {
501            return this.deletedAt;
502        }
503
504        /**
505         * @return optional date filter applies to Custodian assignments only.
506         */
507        public Date getFilterStartedAt() {
508            return this.filterStartedAt;
509        }
510
511        /**
512         * @return optional date filter applies to Custodian assignments only.
513         */
514        public Date getFilterEndedAt() {
515            return this.filterEndedAt;
516        }
517
518        /**
519         * @return notes around why the policy was released.
520         */
521        public String getReleaseNotes() {
522            return this.releaseNotes;
523        }
524
525        /**
526         * Sets the policy's release notes.
527         *
528         * @param releaseNotes the policy's new release notes.
529         */
530        public void setReleaseNotes(String releaseNotes) {
531            this.releaseNotes = releaseNotes;
532            this.addPendingChange("release_notes", releaseNotes);
533        }
534
535        /**
536         * @return boolean indicating whether the policy will continue applying to files based on events, indefinitely.
537         */
538        public Boolean getIsOngoing() {
539            return this.isOngoing;
540        }
541
542        /**
543         * {@inheritDoc}
544         */
545        @Override
546        void parseJSONMember(JsonObject.Member member) {
547            super.parseJSONMember(member);
548            String memberName = member.getName();
549            JsonValue value = member.getValue();
550            try {
551                if (memberName.equals("policy_name")) {
552                    this.policyName = value.asString();
553                } else if (memberName.equals("description")) {
554                    this.description = value.asString();
555                } else if (memberName.equals("status")) {
556                    this.status = value.asString();
557                } else if (memberName.equals("release_notes")) {
558                    this.releaseNotes = value.asString();
559                } else if (memberName.equals("assignment_counts")) {
560                    JsonObject countsJSON = value.asObject();
561                    this.assignmentCountUser = countsJSON.get("user").asInt();
562                    this.assignmentCountFolder = countsJSON.get("folder").asInt();
563                    this.assignmentCountFile = countsJSON.get("file").asInt();
564                    this.assignmentCountFileVersion = countsJSON.get("file_version").asInt();
565                } else if (memberName.equals("created_by")) {
566                    JsonObject userJSON = value.asObject();
567                    if (this.createdBy == null) {
568                        String userID = userJSON.get("id").asString();
569                        BoxUser user = new BoxUser(getAPI(), userID);
570                        this.createdBy = user.new Info(userJSON);
571                    } else {
572                        this.createdBy.update(userJSON);
573                    }
574                } else if (memberName.equals("created_at")) {
575                    this.createdAt = BoxDateFormat.parse(value.asString());
576                } else if (memberName.equals("modified_at")) {
577                    this.modifiedAt = BoxDateFormat.parse(value.asString());
578                } else if (memberName.equals("deleted_at")) {
579                    this.deletedAt = BoxDateFormat.parse(value.asString());
580                } else if (memberName.equals("filter_started_at")) {
581                    this.filterStartedAt = BoxDateFormat.parse(value.asString());
582                } else if (memberName.equals("filter_ended_at")) {
583                    this.filterEndedAt = BoxDateFormat.parse(value.asString());
584                } else if (memberName.equals("is_ongoing")) {
585                    this.isOngoing = value.asBoolean();
586                }
587            } catch (Exception e) {
588                throw new BoxDeserializationException(memberName, value.toString(), e);
589            }
590        }
591    }
592}