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