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