001package com.box.sdk; 002 003import com.box.sdk.internal.utils.CollectionUtils; 004import com.box.sdk.internal.utils.CollectionUtils.Mapper; 005import com.eclipsesource.json.Json; 006import com.eclipsesource.json.JsonArray; 007import com.eclipsesource.json.JsonObject; 008import com.eclipsesource.json.JsonValue; 009import java.net.MalformedURLException; 010import java.net.URL; 011import java.text.ParseException; 012import java.util.Arrays; 013import java.util.Collection; 014import java.util.Collections; 015import java.util.Date; 016import java.util.HashSet; 017import java.util.Set; 018 019/** 020 * Box WebHook resource. 021 * 022 * @since 2.2.1 023 */ 024@BoxResourceType("webhook") 025public class BoxWebHook extends BoxResource { 026 027 /** 028 * {@link URLTemplate} for {@link BoxWebHook}s resource. 029 */ 030 public static final URLTemplate WEBHOOKS_URL_TEMPLATE = new URLTemplate("webhooks"); 031 /** 032 * {@link URLTemplate} for single {@link BoxWebHook} resource. 033 */ 034 public static final URLTemplate WEBHOOK_URL_TEMPLATE = new URLTemplate("webhooks/%s"); 035 036 /** 037 * JSON Key for {@link BoxWebHook} {@link #getID()}. 038 */ 039 private static final String JSON_KEY_ID = "id"; 040 041 /** 042 * JSON Key for {@link BoxWebHook.Info#getTarget()}. 043 */ 044 private static final String JSON_KEY_TARGET = "target"; 045 046 /** 047 * JSON Key for {@link BoxWebHook.Target#getType()}. 048 */ 049 private static final String JSON_KEY_TARGET_TYPE = "type"; 050 051 /** 052 * JSON Key for {@link BoxWebHook.Target#getId()}. 053 */ 054 private static final String JSON_KEY_TARGET_ID = "id"; 055 056 /** 057 * JSON Key for {@link BoxWebHook.Info#getAddress()}. 058 */ 059 private static final String JSON_KEY_ADDRESS = "address"; 060 061 /** 062 * JSON Key for {@link BoxWebHook.Info#getTriggers()}. 063 */ 064 private static final String JSON_KEY_TRIGGERS = "triggers"; 065 066 /** 067 * JSON Key for {@link BoxWebHook.Info#getCreatedBy()}. 068 */ 069 private static final String JSON_KEY_CREATED_BY = "created_by"; 070 071 /** 072 * JSON Key for {@link BoxWebHook.Info#getCreatedAt()}. 073 */ 074 private static final String JSON_KEY_CREATED_AT = "created_at"; 075 076 /** 077 * Maps a {@link Trigger} to its {@link Trigger#getValue()}. 078 */ 079 private static final Mapper<String, BoxWebHook.Trigger> TRIGGER_TO_VALUE = Trigger::getValue; 080 081 private static final Mapper<Trigger, JsonValue> JSON_VALUE_TO_TRIGGER = 082 value -> Trigger.fromValue(value.asString()); 083 084 /** 085 * Constructor. 086 * 087 * @param api {@link #getAPI()} 088 * @param id {@link #getID()} 089 */ 090 public BoxWebHook(BoxAPIConnection api, String id) { 091 super(api, id); 092 } 093 094 /** 095 * Adds a {@link BoxWebHook} to a provided {@link BoxResource}. 096 * 097 * @param target {@link BoxResource} web resource 098 * @param address {@link URL} where the notification should send to 099 * @param triggers events this {@link BoxWebHook} is interested in 100 * @return created {@link BoxWebHook} 101 * @see #create(BoxResource, URL, Set) 102 */ 103 public static BoxWebHook.Info create(BoxResource target, URL address, BoxWebHook.Trigger... triggers) { 104 return create(target, address, new HashSet<>(Arrays.asList(triggers))); 105 } 106 107 /** 108 * Adds a {@link BoxWebHook} to a provided {@link BoxResource}. 109 * 110 * @param target {@link BoxResource} web resource 111 * @param address {@link URL} where the notification should send to 112 * @param triggers events this {@link BoxWebHook} is interested in 113 * @return created {@link BoxWebHook} 114 * @see #create(BoxResource, URL, Trigger...) 115 */ 116 public static BoxWebHook.Info create(BoxResource target, URL address, Set<BoxWebHook.Trigger> triggers) { 117 BoxAPIConnection api = target.getAPI(); 118 119 String type = BoxResource.getResourceType(target.getClass()); 120 validateTriggers(type, triggers); 121 122 JsonObject targetJSON = new JsonObject() 123 .add(JSON_KEY_TARGET_TYPE, type) 124 .add(JSON_KEY_TARGET_ID, target.getID()); 125 126 JsonObject requestJSON = new JsonObject() 127 .add(JSON_KEY_TARGET, targetJSON) 128 .add(JSON_KEY_ADDRESS, address.toExternalForm()) 129 .add(JSON_KEY_TRIGGERS, toJsonArray(CollectionUtils.map(triggers, TRIGGER_TO_VALUE))); 130 131 URL url = WEBHOOKS_URL_TEMPLATE.build(api.getBaseURL()); 132 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 133 request.setBody(requestJSON.toString()); 134 135 try (BoxJSONResponse response = request.send()) { 136 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 137 138 BoxWebHook webHook = new BoxWebHook(api, responseJSON.get(JSON_KEY_ID).asString()); 139 return webHook.new Info(responseJSON); 140 } 141 } 142 143 /** 144 * Helper function to create JsonArray from collection. 145 * 146 * @param values collection of values to convert to JsonArray 147 * @return JsonArray with collection values 148 */ 149 private static JsonArray toJsonArray(Collection<String> values) { 150 JsonArray array = new JsonArray(); 151 for (String value : values) { 152 array.add(value); 153 } 154 return array; 155 156 } 157 158 /** 159 * Returns iterator over all {@link BoxWebHook}-s. 160 * 161 * @param api the API connection to be used by the resource 162 * @return existing {@link BoxWebHook.Info}-s 163 */ 164 public static Iterable<BoxWebHook.Info> all(final BoxAPIConnection api) { 165 return new BoxResourceIterable<BoxWebHook.Info>(api, WEBHOOKS_URL_TEMPLATE.build(api.getBaseURL()), 64) { 166 167 @Override 168 protected BoxWebHook.Info factory(JsonObject jsonObject) { 169 BoxWebHook webHook = new BoxWebHook(api, jsonObject.get("id").asString()); 170 return webHook.new Info(jsonObject); 171 } 172 173 }; 174 } 175 176 /** 177 * Returns iterator over all {@link BoxWebHook}-s. 178 * 179 * @param api the API connection to be used by the resource 180 * @param fields the fields to retrieve. 181 * @return existing {@link BoxWebHook.Info}-s 182 */ 183 public static Iterable<BoxWebHook.Info> all(final BoxAPIConnection api, String... fields) { 184 QueryStringBuilder builder = new QueryStringBuilder(); 185 if (fields.length > 0) { 186 builder.appendParam("fields", fields); 187 } 188 return new BoxResourceIterable<BoxWebHook.Info>( 189 api, WEBHOOKS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString()), 64) { 190 191 @Override 192 protected BoxWebHook.Info factory(JsonObject jsonObject) { 193 BoxWebHook webHook = new BoxWebHook(api, jsonObject.get("id").asString()); 194 return webHook.new Info(jsonObject); 195 } 196 197 }; 198 } 199 200 /** 201 * Validates that provided {@link BoxWebHook.Trigger}-s can be applied on the provided {@link BoxResourceType}. 202 * 203 * @param targetType on which target the triggers should be applied to 204 * @param triggers for check 205 * @see #validateTrigger(String, Trigger) 206 */ 207 public static void validateTriggers(String targetType, Collection<BoxWebHook.Trigger> triggers) { 208 for (BoxWebHook.Trigger trigger : triggers) { 209 validateTrigger(targetType, trigger); 210 } 211 } 212 213 /** 214 * Validates that provided {@link BoxWebHook.Trigger} can be applied on the provided {@link BoxResourceType}. 215 * 216 * @param targetType on which targets the trigger should be applied to 217 * @param trigger for check 218 * @see #validateTriggers(String, Collection) 219 */ 220 private static void validateTrigger(String targetType, BoxWebHook.Trigger trigger) { 221 for (String type : trigger.getTypes()) { 222 if (targetType.equals(type)) { 223 return; 224 } 225 } 226 throw new IllegalArgumentException(String.format( 227 "Provided trigger '%s' is not supported on provided target '%s'.", trigger.name(), targetType)); 228 } 229 230 /** 231 * @param fields the fields to retrieve. 232 * @return Gets information about this {@link BoxWebHook}. 233 */ 234 public BoxWebHook.Info getInfo(String... fields) { 235 URL url = WEBHOOK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 236 if (fields.length > 0) { 237 QueryStringBuilder builder = new QueryStringBuilder().appendParam("fields", fields); 238 url = WEBHOOK_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID()); 239 } 240 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "GET"); 241 try (BoxJSONResponse response = request.send()) { 242 return new Info(Json.parse(response.getJSON()).asObject()); 243 } 244 } 245 246 /** 247 * Updates {@link BoxWebHook} information. 248 * 249 * @param info new state 250 */ 251 public void updateInfo(BoxWebHook.Info info) { 252 URL url = WEBHOOK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 253 BoxJSONRequest request = new BoxJSONRequest(getAPI(), url, "PUT"); 254 request.setBody(info.getPendingChanges()); 255 256 try (BoxJSONResponse response = request.send()) { 257 JsonObject jsonObject = Json.parse(response.getJSON()).asObject(); 258 info.update(jsonObject); 259 } 260 } 261 262 /** 263 * Deletes this webhook. 264 */ 265 public void delete() { 266 URL url = WEBHOOK_URL_TEMPLATE.build(getAPI().getBaseURL(), this.getID()); 267 BoxAPIRequest request = new BoxAPIRequest(getAPI(), url, "DELETE"); 268 request.send().close(); 269 } 270 271 /** 272 * A Box related triggers. 273 */ 274 public enum Trigger { 275 276 // BoxFolder related triggers. 277 278 /** 279 * Triggered when a {@link BoxFolder} gets created. 280 */ 281 FOLDER_CREATED("FOLDER.CREATED", BoxResource.getResourceType(BoxFolder.class)), 282 283 /** 284 * Triggered when a {@link BoxFolder} gets copied. 285 */ 286 FOLDER_COPIED("FOLDER.COPIED", BoxResource.getResourceType(BoxFolder.class)), 287 288 /** 289 * Triggered when a {@link BoxFolder} gets moved. 290 */ 291 FOLDER_MOVED("FOLDER.MOVED", BoxResource.getResourceType(BoxFolder.class)), 292 293 /** 294 * Triggered when a {@link BoxFolder} is downloaded. 295 */ 296 FOLDER_DOWNLOADED("FOLDER.DOWNLOADED", BoxResource.getResourceType(BoxFolder.class)), 297 298 /** 299 * Triggered when a {@link BoxFolder} is trashed. 300 */ 301 FOLDER_TRASHED("FOLDER.TRASHED", BoxResource.getResourceType(BoxFolder.class)), 302 303 /** 304 * Triggered when a {@link BoxFolder} gets restored. 305 */ 306 FOLDER_RESTORED("FOLDER.RESTORED", BoxResource.getResourceType(BoxFolder.class)), 307 308 /** 309 * Triggered when a {@link BoxFolder} gets deleted. 310 */ 311 FOLDER_DELETED("FOLDER.DELETED", BoxResource.getResourceType(BoxFolder.class)), 312 313 /** 314 * Triggered when a {@link BoxFolder} is renamed. 315 */ 316 FOLDER_RENAMED("FOLDER.RENAMED", BoxResource.getResourceType(BoxFolder.class)), 317 318 // BoxFile related triggers. 319 320 /** 321 * Triggered when a {@link BoxFile} gets uploaded. 322 */ 323 FILE_UPLOADED("FILE.UPLOADED", BoxResource.getResourceType(BoxFolder.class)), 324 325 /** 326 * Triggered when a {@link BoxFile} gets copied. 327 */ 328 FILE_COPIED("FILE.COPIED", 329 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 330 331 /** 332 * Triggered when a {@link BoxFile} gets copied. 333 */ 334 FILE_MOVED("FILE.MOVED", 335 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 336 337 /** 338 * Triggered when a {@link BoxFile} is previewed. 339 */ 340 FILE_PREVIEWED("FILE.PREVIEWED", 341 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 342 343 /** 344 * Triggered when a {@link BoxFile} is downloaded. 345 */ 346 FILE_DOWNLOADED("FILE.DOWNLOADED", 347 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 348 349 /** 350 * Triggered when a {@link BoxFile} gets locked. 351 */ 352 FILE_LOCKED("FILE.LOCKED", 353 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 354 355 /** 356 * Triggered when a {@link BoxFile} gets unlocked. 357 */ 358 FILE_UNLOCKED("FILE.UNLOCKED", 359 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 360 361 /** 362 * Triggered when a {@link BoxFile} is trashed. Do not include file versions for now. 363 */ 364 FILE_TRASHED("FILE.TRASHED", 365 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 366 367 /** 368 * Triggered when a {@link BoxFile} gets restored. 369 */ 370 FILE_RESTORED("FILE.RESTORED", 371 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 372 373 /** 374 * Triggered when a {@link BoxFile} is permanently deleted. 375 */ 376 FILE_DELETED("FILE.DELETED", 377 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 378 379 /** 380 * Triggered when a {@link BoxFile} is renamed. 381 */ 382 FILE_RENAMED("FILE.RENAMED", 383 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 384 385 /** 386 * Triggered when a {@link BoxComment} was created. 387 */ 388 COMMENT_CREATED("COMMENT.CREATED", 389 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 390 391 /** 392 * Triggered when a {@link BoxComment} was updated. 393 */ 394 COMMENT_UPDATED("COMMENT.UPDATED", 395 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 396 397 /** 398 * Triggered when a {@link BoxComment} was deleted. 399 */ 400 COMMENT_DELETED("COMMENT.DELETED", 401 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 402 403 /** 404 * Triggered when a {@link BoxTaskAssignment} is created. 405 */ 406 TASK_ASSIGNMENT_CREATED("TASK_ASSIGNMENT.CREATED", 407 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 408 409 /** 410 * Triggered when a {@link BoxTaskAssignment} is updated. 411 */ 412 TASK_ASSIGNMENT_UPDATED("TASK_ASSIGNMENT.UPDATED", 413 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 414 415 /** 416 * Triggered when a metadata template is associated to a {@link BoxFile} or {@link BoxFolder}. 417 */ 418 METADATA_INSTANCE_CREATED("METADATA_INSTANCE.CREATED", 419 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 420 421 /** 422 * Triggered when a field is updated in the metadata on a {@link BoxFile} or {@link BoxFolder}. 423 */ 424 METADATA_INSTANCE_UPDATED("METADATA_INSTANCE.UPDATED", 425 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 426 427 /** 428 * Triggered when a metadata template is removed from a {@link BoxFile} or {@link BoxFolder}. 429 */ 430 METADATA_INSTANCE_DELETED("METADATA_INSTANCE.DELETED", 431 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 432 433 /** 434 * Triggered when a {@link BoxWebHook} is deleted. 435 */ 436 WEBHOOK_DELETED("WEBHOOK.DELETED"), 437 438 /** 439 * Triggered when a {@link BoxCollaboration} is created. 440 */ 441 COLLABORATION_CREATED("COLLABORATION.CREATED", 442 BoxResource.getResourceType(BoxFolder.class)), 443 444 /** 445 * Triggered when a {@link BoxCollaboration} is accepted. 446 */ 447 COLLABORATION_ACCEPTED("COLLABORATION.ACCEPTED", 448 BoxResource.getResourceType(BoxFolder.class)), 449 450 /** 451 * Triggered when a {@link BoxCollaboration} is rejected. 452 */ 453 COLLABORATION_REJECTED("COLLABORATION.REJECTED", 454 BoxResource.getResourceType(BoxFolder.class)), 455 456 /** 457 * Triggered when a {@link BoxCollaboration} is removed. 458 */ 459 COLLABORATION_REMOVED("COLLABORATION.REMOVED", 460 BoxResource.getResourceType(BoxFolder.class)), 461 462 /** 463 * Triggered when a {@link BoxCollaboration} is updated. 464 */ 465 COLLABORATION_UPDATED("COLLABORATION.UPDATED", 466 BoxResource.getResourceType(BoxFolder.class)), 467 468 /** 469 * Triggered when a {@link BoxSharedLink} is created. 470 */ 471 SHARED_LINK_CRATED("SHARED_LINK.CREATED", 472 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 473 474 /** 475 * Triggered when a {@link BoxSharedLink} is updated. 476 */ 477 SHARED_LINK_UPDATED("SHARED_LINK.UPDATED", 478 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 479 480 /** 481 * Triggered when a {@link BoxSharedLink} is deleted. 482 */ 483 SHARED_LINK_DELETED("SHARED_LINK.DELETED", 484 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 485 486 /** 487 * Triggered when {@link BoxSignRequest} is completed. 488 */ 489 SIGN_REQUEST_COMPLETED("SIGN_REQUEST.COMPLETED", 490 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 491 /** 492 * Triggered when {@link BoxFile} is declined. 493 */ 494 SIGN_REQUEST_DECLINED("SIGN_REQUEST.DECLINED", 495 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)), 496 /** 497 * Triggered when {@link BoxFile} is expired. 498 */ 499 SIGN_REQUEST_EXPIRED("SIGN_REQUEST.EXPIRED", 500 BoxResource.getResourceType(BoxFolder.class), BoxResource.getResourceType(BoxFile.class)); 501 502 /** 503 * @see #getValue() 504 */ 505 private final String value; 506 507 /** 508 * @see #getTypes() 509 */ 510 private final String[] types; 511 512 /** 513 * Constructor. 514 * 515 * @param value {@link #getValue()} 516 * @param types {@link #getTypes()} 517 */ 518 Trigger(String value, String... types) { 519 this.value = value; 520 this.types = types; 521 } 522 523 /** 524 * @param value value to get the Trigger enum value for 525 * @return Trigger for given value 526 */ 527 public static Trigger fromValue(String value) { 528 for (Trigger trigger : Trigger.values()) { 529 if (trigger.getValue().equals(value)) { 530 return trigger; 531 } 532 } 533 throw new IllegalArgumentException("No Trigger for value: " + value); 534 } 535 536 /** 537 * @return {@link String} representation for {@link Trigger}. 538 */ 539 public String getValue() { 540 return this.value; 541 } 542 543 /** 544 * @return Supported types for a web-hook. 545 */ 546 public String[] getTypes() { 547 return this.types; 548 } 549 550 } 551 552 /** 553 * WebHook target - file or folder. 554 */ 555 public static class Target { 556 557 /** 558 * @see #getType() 559 */ 560 private final String type; 561 562 /** 563 * @see #getId() 564 */ 565 private final String id; 566 567 /** 568 * Constructor. 569 * 570 * @param type {@link #getType()} 571 * @param id {@link #getId()} 572 */ 573 public Target(String type, String id) { 574 this.type = type; 575 this.id = id; 576 } 577 578 /** 579 * @return Type of target. 580 * @see BoxResourceType 581 */ 582 public String getType() { 583 return this.type; 584 } 585 586 /** 587 * @return {@link BoxResource#getID()} 588 */ 589 public String getId() { 590 return this.id; 591 } 592 593 } 594 595 /** 596 * Contains information for a {@link BoxWebHook} instance. 597 */ 598 public class Info extends BoxResource.Info { 599 600 /** 601 * @see #getTarget() 602 */ 603 private Target target; 604 605 /** 606 * @see #getAddress() 607 */ 608 private URL address; 609 610 /** 611 * @see #getTriggers() 612 */ 613 private Set<Trigger> triggers; 614 615 /** 616 * @see #getCreatedBy() 617 */ 618 private BoxUser.Info createdBy; 619 620 /** 621 * @see #getCreatedAt() 622 */ 623 private Date createdAt; 624 625 /** 626 * Constructs an Info object with current target. 627 */ 628 public Info() { 629 super(); 630 this.target = BoxWebHook.this.getInfo().getTarget(); 631 } 632 633 /** 634 * Constructs an Info object by parsing information from a JSON string. 635 * 636 * @param json the JSON string to parse. 637 */ 638 public Info(String json) { 639 this(Json.parse(json).asObject()); 640 } 641 642 /** 643 * Constructor. 644 * 645 * @param jsonObject a parsed JSON object 646 */ 647 public Info(JsonObject jsonObject) { 648 super(jsonObject); 649 650 if (jsonObject.get(JSON_KEY_TARGET) != null) { 651 JsonObject targetObject = jsonObject.get(JSON_KEY_TARGET).asObject(); 652 String targetType = targetObject.get(JSON_KEY_TARGET_TYPE).asString(); 653 String targetId = targetObject.get(JSON_KEY_TARGET_ID).asString(); 654 this.target = new Target(targetType, targetId); 655 } 656 657 if (jsonObject.get(JSON_KEY_TRIGGERS) != null) { 658 this.triggers = new HashSet<>( 659 CollectionUtils.map(jsonObject.get(JSON_KEY_TRIGGERS).asArray().values(), JSON_VALUE_TO_TRIGGER) 660 ); 661 } 662 if (jsonObject.get(JSON_KEY_ADDRESS) != null) { 663 try { 664 this.address = new URL(jsonObject.get(JSON_KEY_ADDRESS).asString()); 665 } catch (MalformedURLException e) { 666 throw new RuntimeException(e); 667 } 668 } 669 670 if (jsonObject.get(JSON_KEY_CREATED_BY) != null) { 671 JsonObject userJSON = jsonObject.get(JSON_KEY_CREATED_BY).asObject(); 672 if (this.createdBy == null) { 673 BoxUser user = new BoxUser(getAPI(), userJSON.get(JSON_KEY_TARGET_ID).asString()); 674 this.createdBy = user.new Info(userJSON); 675 } else { 676 this.createdBy.update(userJSON); 677 } 678 } 679 680 if (jsonObject.get(JSON_KEY_CREATED_AT) != null) { 681 try { 682 this.createdAt = BoxDateFormat.parse(jsonObject.get(JSON_KEY_CREATED_AT).asString()); 683 } catch (ParseException e) { 684 assert false : "A ParseException indicates a bug in the SDK."; 685 } 686 } 687 } 688 689 /** 690 * {@inheritDoc} 691 */ 692 @Override 693 public BoxWebHook getResource() { 694 return BoxWebHook.this; 695 } 696 697 /** 698 * @return WebHook target / {@link BoxResource}. 699 */ 700 public Target getTarget() { 701 return this.target; 702 } 703 704 /** 705 * @return {@link URL} where the notification should send to. 706 */ 707 public URL getAddress() { 708 return this.address; 709 } 710 711 /** 712 * Setter for {@link #getAddress()}. 713 * 714 * @param address {@link #getAddress()} 715 * @return itself 716 */ 717 public Info setAddress(URL address) { 718 if (address == null) { 719 throw new IllegalArgumentException("Address cannot be null"); 720 } 721 if (this.address == null || !this.address.equals(address)) { 722 this.address = address; 723 this.addPendingChange(JSON_KEY_ADDRESS, address.toExternalForm()); 724 } 725 726 return this; 727 } 728 729 /** 730 * @return Events this webhook is interested in. 731 */ 732 public Set<Trigger> getTriggers() { 733 return this.triggers; 734 } 735 736 /** 737 * Sets {@link #getTriggers()}. 738 * 739 * @param triggers {@link #getTriggers()} 740 * @return itself 741 */ 742 public Info setTriggers(BoxWebHook.Trigger... triggers) { 743 return this.setTriggers(new HashSet<>(Arrays.asList(triggers))); 744 } 745 746 /** 747 * Setter for {@link #getTriggers()}. 748 * 749 * @param triggers {@link #getTriggers()} 750 * @return itself 751 */ 752 public Info setTriggers(Set<BoxWebHook.Trigger> triggers) { 753 validateTriggers(this.target.getType(), triggers); 754 755 JsonArray oldValue; 756 if (this.triggers != null) { 757 oldValue = toJsonArray(CollectionUtils.map(this.triggers, TRIGGER_TO_VALUE)); 758 } else { 759 oldValue = null; 760 } 761 JsonArray newValue = toJsonArray(CollectionUtils.map(triggers, TRIGGER_TO_VALUE)); 762 763 if (!newValue.equals(oldValue)) { 764 this.triggers = Collections.unmodifiableSet(triggers); 765 this.addPendingChange(JSON_KEY_TRIGGERS, newValue); 766 } 767 768 return this; 769 } 770 771 /** 772 * @return Info about the user who created this webhook. 773 */ 774 public BoxUser.Info getCreatedBy() { 775 return this.createdBy; 776 } 777 778 /** 779 * @return the time this webhook was created. 780 */ 781 public Date getCreatedAt() { 782 return this.createdAt; 783 } 784 785 /** 786 * {@inheritDoc} 787 */ 788 @Override 789 void parseJSONMember(JsonObject.Member member) { 790 super.parseJSONMember(member); 791 String memberName = member.getName(); 792 JsonValue value = member.getValue(); 793 try { 794 if (memberName.equals(JSON_KEY_TARGET)) { 795 String targetType = value.asObject().get(JSON_KEY_TARGET_TYPE).asString(); 796 String targetId = value.asObject().get(JSON_KEY_TARGET_ID).asString(); 797 this.target = new Target(targetType, targetId); 798 } else if (memberName.equals(JSON_KEY_TRIGGERS)) { 799 this.triggers = new HashSet<>( 800 CollectionUtils.map(value.asArray().values(), JSON_VALUE_TO_TRIGGER) 801 ); 802 } else if (memberName.equals(JSON_KEY_ADDRESS)) { 803 this.address = new URL(value.asString()); 804 } else if (memberName.equals(JSON_KEY_CREATED_BY)) { 805 JsonObject userJSON = value.asObject(); 806 if (this.createdBy == null) { 807 String userID = userJSON.get(JSON_KEY_ID).asString(); 808 BoxUser user = new BoxUser(getAPI(), userID); 809 this.createdBy = user.new Info(userJSON); 810 } else { 811 this.createdBy.update(userJSON); 812 } 813 } else if (memberName.equals("created_at")) { 814 this.createdAt = BoxDateFormat.parse(value.asString()); 815 } 816 } catch (Exception e) { 817 throw new BoxDeserializationException(memberName, value.toString(), e); 818 } 819 } 820 821 } 822 823}