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