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 011 * of the Policy, such as name, description, and filter dates. 012 * 013 * @see <a href="https://developer.box.com/reference/resources/legal-hold-policy/">Box legal 014 * holds</a> 015 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link 016 * BoxAPIException} (unchecked meaning that the compiler won't force you to handle it) if an 017 * error occurs. If you wish to implement custom error handling for errors related to the Box 018 * REST API, you should capture this exception explicitly. 019 */ 020@BoxResourceType("legal_hold") 021public class BoxLegalHoldPolicy extends BoxResource { 022 /** Legal Hold URL Template. */ 023 public static final URLTemplate LEGAL_HOLD_URL_TEMPLATE = 024 new URLTemplate("legal_hold_policies/%s"); 025 /** All Legal Hold URL Template. */ 026 public static final URLTemplate ALL_LEGAL_HOLD_URL_TEMPLATE = 027 new URLTemplate("legal_hold_policies"); 028 /** Legal Hold Assignments URL Template. */ 029 public static final URLTemplate LEGAL_HOLD_ASSIGNMENTS_URL_TEMPLATE = 030 new URLTemplate("legal_hold_policies/%s/assignments"); 031 /** List of File Version Holds URL Template. */ 032 public static final URLTemplate LIST_OF_FILE_VERSION_HOLDS_URL_TEMPLATE = 033 new URLTemplate("file_version_legal_holds"); 034 035 private static final int DEFAULT_LIMIT = 100; 036 037 /** 038 * Constructs a BoxLegalHoldPolicy for a resource with a given ID. 039 * 040 * @param api the API connection to be used by the resource. 041 * @param id the ID of the resource. 042 */ 043 public BoxLegalHoldPolicy(BoxAPIConnection api, String id) { 044 super(api, id); 045 } 046 047 /** 048 * Creates a new Legal Hold Policy. 049 * 050 * @param api the API connection to be used by the resource. 051 * @param name the name of Legal Hold Policy. 052 * @return information about the Legal Hold Policy created. 053 */ 054 public static BoxLegalHoldPolicy.Info create(BoxAPIConnection api, String name) { 055 return createOngoing(api, name, null); 056 } 057 058 /** 059 * Creates a new Legal Hold Policy. 060 * 061 * @param api the API connection to be used by the resource. 062 * @param name the name of Legal Hold Policy. 063 * @param description the description of Legal Hold Policy. 064 * @param filterStartedAt optional date filter applies to Custodian assignments only. 065 * @param filterEndedAt optional date filter applies to Custodian assignments only. 066 * @return information about the Legal Hold Policy created. 067 */ 068 public static BoxLegalHoldPolicy.Info create( 069 BoxAPIConnection api, 070 String name, 071 String description, 072 Date filterStartedAt, 073 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().add("policy_name", name); 077 if (description != null) { 078 requestJSON.add("description", description); 079 } 080 if (filterStartedAt != null) { 081 requestJSON.add("filter_started_at", BoxDateFormat.format(filterStartedAt)); 082 } 083 if (filterEndedAt != null) { 084 requestJSON.add("filter_ended_at", BoxDateFormat.format(filterEndedAt)); 085 } 086 request.setBody(requestJSON.toString()); 087 try (BoxJSONResponse response = request.send()) { 088 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 089 BoxLegalHoldPolicy createdPolicy = 090 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( 104 BoxAPIConnection api, String name, String description) { 105 return createOngoing(api, name, description, null); 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 URL url = ALL_LEGAL_HOLD_URL_TEMPLATE.build(api.getBaseURL()); 120 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 121 JsonObject requestJSON = new JsonObject().add("policy_name", name).add("is_ongoing", true); 122 if (description != null) { 123 requestJSON.add("description", description); 124 } 125 if (filterStartedAt != null) { 126 requestJSON.add("filter_started_at", BoxDateFormat.format(filterStartedAt)); 127 } 128 request.setBody(requestJSON.toString()); 129 try (BoxJSONResponse response = request.send()) { 130 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 131 BoxLegalHoldPolicy createdPolicy = 132 new BoxLegalHoldPolicy(api, responseJSON.get("id").asString()); 133 return createdPolicy.new Info(responseJSON); 134 } 135 } 136 137 /** 138 * Retrieves a list of Legal Hold Policies that belong to your Enterprise as an Iterable. 139 * 140 * @param api api the API connection to be used by the resource. 141 * @return the Iterable of Legal Hold Policies in your Enterprise. 142 */ 143 public static Iterable<BoxLegalHoldPolicy.Info> getAll(final BoxAPIConnection api) { 144 return getAll(api, null, DEFAULT_LIMIT); 145 } 146 147 /** 148 * Retrieves a list of Legal Hold Policies that belong to your Enterprise as an Iterable. 149 * 150 * @param api api the API connection to be used by the resource. 151 * @param policyName case insensitive prefix-match filter on Policy name. 152 * @param limit the limit of retrieved entries per page. 153 * @param fields the optional fields to retrieve. 154 * @return the Iterable of Legal Hold Policies in your Enterprise that match the filter 155 * parameters. 156 */ 157 public static Iterable<BoxLegalHoldPolicy.Info> getAll( 158 final BoxAPIConnection api, String policyName, int limit, String... fields) { 159 QueryStringBuilder builder = new QueryStringBuilder(); 160 if (policyName != null) { 161 builder.appendParam("policy_name", policyName); 162 } 163 if (fields.length > 0) { 164 builder.appendParam("fields", fields); 165 } 166 return new BoxResourceIterable<BoxLegalHoldPolicy.Info>( 167 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 = 191 LEGAL_HOLD_URL_TEMPLATE.buildWithQuery( 192 this.getAPI().getBaseURL(), builder.toString(), this.getID()); 193 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "GET"); 194 try (BoxJSONResponse response = request.send()) { 195 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 196 return new Info(responseJSON); 197 } 198 } 199 200 /** Deletes the legal hold policy. */ 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. Only 209 * 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. Currently only {@link BoxFile}, 225 * {@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(), 233 this.getID(), 234 BoxResource.getResourceType(resource.getClass()), 235 resource.getID()); 236 } 237 238 /** 239 * Returns iterable containing assignments for this single legal hold policy. 240 * 241 * @param fields the fields to retrieve. 242 * @return an iterable containing assignments for this single legal hold policy. 243 */ 244 public Iterable<BoxLegalHoldAssignment.Info> getAssignments(String... fields) { 245 return this.getAssignments(null, null, DEFAULT_LIMIT, fields); 246 } 247 248 /** 249 * Returns iterable containing assignments for this single legal hold policy. Parameters can be 250 * used to filter retrieved assignments. 251 * 252 * @param type filter assignments of this type only. Can be "file_version", "file", "folder", 253 * "user" or null if no type filter is necessary. 254 * @param id filter assignments to this ID only. Can be null if no id filter is necessary. 255 * @param limit the limit of entries per page. Default limit is 100. 256 * @param fields the fields to retrieve. 257 * @return an iterable containing assignments for this single legal hold policy. 258 */ 259 public Iterable<BoxLegalHoldAssignment.Info> getAssignments( 260 String type, String id, int limit, String... fields) { 261 QueryStringBuilder builder = new QueryStringBuilder(); 262 if (type != null) { 263 builder.appendParam("assign_to_type", type); 264 } 265 if (id != null) { 266 builder.appendParam("assign_to_id", id); 267 } 268 if (fields.length > 0) { 269 builder.appendParam("fields", fields); 270 } 271 return new BoxResourceIterable<BoxLegalHoldAssignment.Info>( 272 this.getAPI(), 273 LEGAL_HOLD_ASSIGNMENTS_URL_TEMPLATE.buildWithQuery( 274 this.getAPI().getBaseURL(), builder.toString(), this.getID()), 275 limit) { 276 277 @Override 278 protected BoxLegalHoldAssignment.Info factory(JsonObject jsonObject) { 279 BoxLegalHoldAssignment assignment = 280 new BoxLegalHoldAssignment( 281 BoxLegalHoldPolicy.this.getAPI(), jsonObject.get("id").asString()); 282 return assignment.new Info(jsonObject); 283 } 284 }; 285 } 286 287 /** 288 * Returns iterable with all non-deleted file version legal holds for this legal hold policy. 289 * 290 * @param fields the fields to retrieve. 291 * @return an iterable containing file version legal holds info. 292 */ 293 public Iterable<BoxFileVersionLegalHold.Info> getFileVersionHolds(String... fields) { 294 return this.getFileVersionHolds(DEFAULT_LIMIT, fields); 295 } 296 297 /** 298 * Returns iterable with all non-deleted file version legal holds for this legal hold policy. 299 * 300 * @param limit the limit of entries per response. The default value is 100. 301 * @param fields the fields to retrieve. 302 * @return an iterable containing file version legal holds info. 303 */ 304 public Iterable<BoxFileVersionLegalHold.Info> getFileVersionHolds(int limit, String... fields) { 305 QueryStringBuilder queryString = 306 new QueryStringBuilder().appendParam("policy_id", this.getID()); 307 if (fields.length > 0) { 308 queryString.appendParam("fields", fields); 309 } 310 URL url = 311 LIST_OF_FILE_VERSION_HOLDS_URL_TEMPLATE.buildWithQuery( 312 getAPI().getBaseURL(), queryString.toString()); 313 return new BoxResourceIterable<BoxFileVersionLegalHold.Info>(getAPI(), url, limit) { 314 315 @Override 316 protected BoxFileVersionLegalHold.Info factory(JsonObject jsonObject) { 317 BoxFileVersionLegalHold assignment = 318 new BoxFileVersionLegalHold(getAPI(), jsonObject.get("id").asString()); 319 return assignment.new Info(jsonObject); 320 } 321 }; 322 } 323 324 /** Contains information about the legal hold policy. */ 325 public class Info extends BoxResource.Info { 326 327 /** @see #getPolicyName() */ 328 private String policyName; 329 330 /** @see #getDescription() */ 331 private String description; 332 333 /** @see #getStatus() */ 334 private String status; 335 336 /** @see #getAssignmentCountUser() */ 337 private int assignmentCountUser; 338 339 /** @see #getAssignmentCountFolder() */ 340 private int assignmentCountFolder; 341 342 /** @see #getAssignmentCountFile() */ 343 private int assignmentCountFile; 344 345 /** @see #getAssignmentCountFileVersion() */ 346 private int assignmentCountFileVersion; 347 348 /** @see #getCreatedAt() */ 349 private BoxUser.Info createdBy; 350 351 /** @see #getCreatedAt() */ 352 private Date createdAt; 353 354 /** @see #getModifiedAt() */ 355 private Date modifiedAt; 356 357 /** @see #getDeletedAt() */ 358 private Date deletedAt; 359 360 /** @see #getFilterStartedAt() */ 361 private Date filterStartedAt; 362 363 /** @see #getFilterEndedAt() */ 364 private Date filterEndedAt; 365 366 /** @see #getReleaseNotes() */ 367 private String releaseNotes; 368 369 /** @see #getIsOngoing() */ 370 private Boolean isOngoing; 371 372 /** Constructs an empty Info object. */ 373 public Info() { 374 super(); 375 } 376 377 /** 378 * Constructs an Info object by parsing information from a JSON string. 379 * 380 * @param json the JSON string to parse. 381 */ 382 public Info(String json) { 383 super(json); 384 } 385 386 /** 387 * Constructs an Info object using an already parsed JSON object. 388 * 389 * @param jsonObject the parsed JSON object. 390 */ 391 Info(JsonObject jsonObject) { 392 super(jsonObject); 393 } 394 395 /** {@inheritDoc} */ 396 @Override 397 public BoxResource getResource() { 398 return BoxLegalHoldPolicy.this; 399 } 400 401 /** @return the name of the policy. */ 402 public String getPolicyName() { 403 return this.policyName; 404 } 405 406 /** 407 * Sets the policy's name. 408 * 409 * @param policyName the policy's new name. 410 */ 411 public void setPolicyName(String policyName) { 412 this.policyName = policyName; 413 this.addPendingChange("policy_name", policyName); 414 } 415 416 /** @return the description of the policy. */ 417 public String getDescription() { 418 return this.description; 419 } 420 421 /** 422 * Sets the policy's description. 423 * 424 * @param description the policy's new description. 425 */ 426 public void setDescription(String description) { 427 this.description = description; 428 this.addPendingChange("description", description); 429 } 430 431 /** 432 * Status can be "active", "applying", "releasing" or "released". 433 * 434 * @return the status of the policy. 435 */ 436 public String getStatus() { 437 return this.status; 438 } 439 440 /** @return count of users this policy assigned to. */ 441 public int getAssignmentCountUser() { 442 return this.assignmentCountUser; 443 } 444 445 /** @return count of folders this policy assigned to. */ 446 public int getAssignmentCountFolder() { 447 return this.assignmentCountFolder; 448 } 449 450 /** @return count of files this policy assigned to. */ 451 public int getAssignmentCountFile() { 452 return this.assignmentCountFile; 453 } 454 455 /** @return count of file versions this policy assigned to. */ 456 public int getAssignmentCountFileVersion() { 457 return this.assignmentCountFileVersion; 458 } 459 460 /** @return info about the user who created this policy. */ 461 public BoxUser.Info getCreatedBy() { 462 return this.createdBy; 463 } 464 465 /** @return time the policy was created. */ 466 public Date getCreatedAt() { 467 return this.createdAt; 468 } 469 470 /** @return time the policy was modified. */ 471 public Date getModifiedAt() { 472 return this.modifiedAt; 473 } 474 475 /** @return time that the policy release request was sent. */ 476 public Date getDeletedAt() { 477 return this.deletedAt; 478 } 479 480 /** @return optional date filter applies to Custodian assignments only. */ 481 public Date getFilterStartedAt() { 482 return this.filterStartedAt; 483 } 484 485 /** @return optional date filter applies to Custodian assignments only. */ 486 public Date getFilterEndedAt() { 487 return this.filterEndedAt; 488 } 489 490 /** @return notes around why the policy was released. */ 491 public String getReleaseNotes() { 492 return this.releaseNotes; 493 } 494 495 /** 496 * Sets the policy's release notes. 497 * 498 * @param releaseNotes the policy's new release notes. 499 */ 500 public void setReleaseNotes(String releaseNotes) { 501 this.releaseNotes = releaseNotes; 502 this.addPendingChange("release_notes", releaseNotes); 503 } 504 505 /** 506 * @return boolean indicating whether the policy will continue applying to files based on 507 * events, indefinitely. 508 */ 509 public Boolean getIsOngoing() { 510 return this.isOngoing; 511 } 512 513 /** {@inheritDoc} */ 514 @Override 515 void parseJSONMember(JsonObject.Member member) { 516 super.parseJSONMember(member); 517 String memberName = member.getName(); 518 JsonValue value = member.getValue(); 519 try { 520 if (memberName.equals("policy_name")) { 521 this.policyName = value.asString(); 522 } else if (memberName.equals("description")) { 523 this.description = value.asString(); 524 } else if (memberName.equals("status")) { 525 this.status = value.asString(); 526 } else if (memberName.equals("release_notes")) { 527 this.releaseNotes = value.asString(); 528 } else if (memberName.equals("assignment_counts")) { 529 JsonObject countsJSON = value.asObject(); 530 this.assignmentCountUser = countsJSON.get("user").asInt(); 531 this.assignmentCountFolder = countsJSON.get("folder").asInt(); 532 this.assignmentCountFile = countsJSON.get("file").asInt(); 533 this.assignmentCountFileVersion = countsJSON.get("file_version").asInt(); 534 } else if (memberName.equals("created_by")) { 535 JsonObject userJSON = value.asObject(); 536 if (this.createdBy == null) { 537 String userID = userJSON.get("id").asString(); 538 BoxUser user = new BoxUser(getAPI(), userID); 539 this.createdBy = user.new Info(userJSON); 540 } else { 541 this.createdBy.update(userJSON); 542 } 543 } else if (memberName.equals("created_at")) { 544 this.createdAt = BoxDateFormat.parse(value.asString()); 545 } else if (memberName.equals("modified_at")) { 546 this.modifiedAt = BoxDateFormat.parse(value.asString()); 547 } else if (memberName.equals("deleted_at")) { 548 this.deletedAt = BoxDateFormat.parse(value.asString()); 549 } else if (memberName.equals("filter_started_at")) { 550 this.filterStartedAt = BoxDateFormat.parse(value.asString()); 551 } else if (memberName.equals("filter_ended_at")) { 552 this.filterEndedAt = BoxDateFormat.parse(value.asString()); 553 } else if (memberName.equals("is_ongoing")) { 554 this.isOngoing = value.asBoolean(); 555 } 556 } catch (Exception e) { 557 throw new BoxDeserializationException(memberName, value.toString(), e); 558 } 559 } 560 } 561}