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