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