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