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