1 /** 2 * Copyright (c) 2013-2023, jcabi.com 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 1) Redistributions of source code must retain the above 8 * copyright notice, this list of conditions and the following 9 * disclaimer. 2) Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 3) Neither the name of the jcabi.com nor 13 * the names of its contributors may be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 * OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package com.jcabi.github; 31 32 import com.google.common.base.Optional; 33 import com.jcabi.aspects.Immutable; 34 import com.jcabi.aspects.Loggable; 35 import java.io.IOException; 36 import java.net.URL; 37 import java.text.ParseException; 38 import java.util.Date; 39 import javax.json.JsonObject; 40 import lombok.EqualsAndHashCode; 41 import lombok.ToString; 42 43 /** 44 * Github event. 45 * 46 * @author Yegor Bugayenko (yegor256@gmail.com) 47 * @version $Id: f031f9ed5089bcb39e3999c75ae9db2301f6e10f $ 48 * @since 0.4 49 * @see <a href="https://developer.github.com/v3/issues/events/">Issue Events API</a> 50 * @checkstyle MultipleStringLiterals (500 lines) 51 */ 52 @Immutable 53 @SuppressWarnings("PMD.TooManyMethods") 54 public interface Event extends Comparable<Event>, JsonReadable { 55 56 /** 57 * Event type. 58 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 59 */ 60 String CLOSED = "closed"; 61 62 /** 63 * Event type. 64 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 65 */ 66 String REOPENED = "reopened"; 67 68 /** 69 * Event type. 70 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 71 */ 72 String SUBSCRIBED = "subscribed"; 73 74 /** 75 * Event type. 76 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 77 */ 78 String MERGED = "merged"; 79 80 /** 81 * Event type. 82 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 83 */ 84 String REFERENCED = "referenced"; 85 86 /** 87 * Event type. 88 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 89 */ 90 String MENTIONED = "mentioned"; 91 92 /** 93 * Event type. 94 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 95 */ 96 String ASSIGNED = "assigned"; 97 98 /** 99 * Event type. 100 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 101 */ 102 String UNASSIGNED = "unassigned"; 103 104 /** 105 * Event type. 106 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 107 */ 108 String LABELED = "labeled"; 109 110 /** 111 * Event type. 112 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 113 */ 114 String UNLABELED = "unlabeled"; 115 116 /** 117 * Event type. 118 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 119 */ 120 String MILESTONED = "milestoned"; 121 122 /** 123 * Event type. 124 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 125 */ 126 String DEMILESTONED = "demilestoned"; 127 128 /** 129 * Event type. 130 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 131 */ 132 String RENAMED = "renamed"; 133 134 /** 135 * Event type. 136 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 137 */ 138 String LOCKED = "locked"; 139 140 /** 141 * Event type. 142 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 143 */ 144 String UNLOCKED = "unlocked"; 145 146 /** 147 * Event type. 148 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 149 */ 150 String HEAD_REF_DELETED = "head_ref_deleted"; 151 152 /** 153 * Event type. 154 * @see <a href="https://developer.github.com/v3/issues/events/">Event Types</a> 155 */ 156 String HEAD_REF_RESTORED = "head_ref_restored"; 157 158 /** 159 * Repository we're in. 160 * @return Repo 161 */ 162 Repo repo(); 163 164 /** 165 * Get its number. 166 * @return Issue number 167 */ 168 int number(); 169 170 /** 171 * Smart event with extra features. 172 */ 173 @Immutable 174 @ToString 175 @Loggable(Loggable.DEBUG) 176 @EqualsAndHashCode(of = { "event", "jsn" }) 177 final class Smart implements Event { 178 /** 179 * Encapsulated event. 180 */ 181 private final transient Event event; 182 /** 183 * SmartJson object for convenient JSON parsing. 184 */ 185 private final transient SmartJson jsn; 186 /** 187 * Public ctor. 188 * @param evt Event 189 */ 190 public Smart(final Event evt) { 191 this.event = evt; 192 this.jsn = new SmartJson(evt); 193 } 194 /** 195 * Does it have an author? 196 * @return TRUE if the author exists 197 * @throws IOException If there is any I/O problem 198 */ 199 public boolean hasAuthor() throws IOException { 200 return !this.event.json().isNull("actor"); 201 } 202 /** 203 * Get its author. 204 * @return Author of comment 205 * @throws IOException If there is any I/O problem 206 */ 207 public User author() throws IOException { 208 return this.event.repo().github().users().get( 209 this.event.json().getJsonObject("actor").getString("login") 210 ); 211 } 212 /** 213 * Get its type. 214 * @return State of issue 215 * @throws IOException If there is any I/O problem 216 */ 217 public String type() throws IOException { 218 return this.jsn.text("event"); 219 } 220 /** 221 * Get its URL. 222 * @return URL of issue 223 * @throws IOException If there is any I/O problem 224 */ 225 public URL url() throws IOException { 226 return new URL(this.jsn.text("url")); 227 } 228 /** 229 * When this issue was created. 230 * @return Date of creation 231 * @throws IOException If there is any I/O problem 232 */ 233 public Date createdAt() throws IOException { 234 try { 235 return new Github.Time( 236 this.jsn.text("created_at") 237 ).date(); 238 } catch (final ParseException ex) { 239 throw new IllegalStateException(ex); 240 } 241 } 242 /** 243 * Label that was added or removed in this event (if any). 244 * @return Label that was added or removed 245 * @throws IOException If there is any I/O problem 246 * @since 0.24 247 */ 248 public Optional<Label> label() throws IOException { 249 Optional<Label> lab = Optional.absent(); 250 final JsonObject lbl = this.jsn.json().getJsonObject("label"); 251 if (lbl != null) { 252 lab = Optional.of( 253 this.event.repo() 254 .labels() 255 .get(lbl.getString("name")) 256 ); 257 } 258 return lab; 259 } 260 @Override 261 public Repo repo() { 262 return this.event.repo(); 263 } 264 @Override 265 public int number() { 266 return this.event.number(); 267 } 268 @Override 269 public JsonObject json() throws IOException { 270 return this.event.json(); 271 } 272 @Override 273 public int compareTo(final Event obj) { 274 return this.event.compareTo(obj); 275 } 276 } 277 278 }