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