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