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}