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