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