View Javadoc
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.jcabi.aspects.Immutable;
33  import com.jcabi.aspects.Loggable;
34  import java.io.IOException;
35  import java.net.URL;
36  import java.text.ParseException;
37  import java.util.Date;
38  import javax.json.JsonObject;
39  import lombok.EqualsAndHashCode;
40  import lombok.ToString;
41  
42  /**
43   * Github user.
44   * @author Yegor Bugayenko (yegor256@gmail.com)
45   * @version $Id: 48081d00dcc7539b7a9cb39a53ca95d8c9b6bbf6 $
46   * @checkstyle MultipleStringLiterals (500 lines)
47   * @see <a href="https://developer.github.com/v3/users/">User API</a>
48   * @since 0.1
49   */
50  @Immutable
51  @SuppressWarnings({"PMD.TooManyMethods", "PMD.ExcessivePublicCount",
52      "PMD.GodClass" })
53  public interface User extends JsonReadable, JsonPatchable {
54  
55      /**
56       * Github we're in.
57       * @return Github
58       * @since 0.4
59       */
60      Github github();
61  
62      /**
63       * Get his login.
64       * @return Login name
65       * @throws IOException If it fails
66       */
67      String login() throws IOException;
68  
69      /**
70       * Get his organizations.
71       * @return UserOrganizations organizations
72       */
73      UserOrganizations organizations();
74  
75      /**
76       * Get his keys.
77       * @return PublicKeys keys
78       */
79      PublicKeys keys();
80  
81      /**
82       * Get user's emails.
83       * @return User's emails
84       * @since 0.8
85       */
86      UserEmails emails();
87  
88      /**
89       * Notifications for this user.
90       * Wraps the call "List your notifications". See "List your notifications"
91       * at https://developer.github.com/v3/activity/notifications/
92       * @see <a href="https://developer.github.com/v3/activity/notifications/#list-your-notifications">List your notifications</a>
93       * @return Notifications for this user.
94       * @throws IOException Thrown, if an error during sending request and/or
95       *  receiving response occurs.
96       */
97      Notifications notifications() throws IOException;
98  
99      /**
100      * Marks notifications as read.
101      * @param lastread Describes the last point that notifications were
102      *  checked.
103      * @see <a href="https://developer.github.com/v3/activity/notifications/#mark-as-read">Mark as read</a>
104      * @throws IOException Thrown, if an error during sending request and/or
105      *  receiving response occurs.
106      */
107     void markAsRead(final Date lastread) throws IOException;
108 
109     /**
110      * Smart user with extra features.
111      * @see <a href="https://developer.github.com/v3/users/#get-a-single-user">Get a Single User</a>
112      */
113     @Immutable
114     @ToString
115     @Loggable(Loggable.DEBUG)
116     @EqualsAndHashCode(of = { "user", "jsn" })
117     final class Smart implements User {
118         /**
119          * Encapsulated user.
120          */
121         private final transient User user;
122         /**
123          * SmartJson object for convenient JSON parsing.
124          */
125         private final transient SmartJson jsn;
126 
127         /**
128          * Public ctor.
129          * @param usr User
130          */
131         public Smart(final User usr) {
132             this.user = usr;
133             this.jsn = new SmartJson(usr);
134         }
135 
136         /**
137          * Does it exist in GitHub?
138          * @return TRUE if this user truly exists
139          * @throws IOException If it fails
140          * @since 0.34
141          */
142         public boolean exists() throws IOException {
143             return new Existence(this.user).check();
144         }
145 
146         /**
147          * Get his ID.
148          * @return Unique user ID
149          * @throws IOException If it fails
150          * @checkstyle MethodName (3 lines)
151          */
152         @SuppressWarnings("PMD.ShortMethodName")
153         public int id() throws IOException {
154             return this.user.json().getJsonNumber("id").intValue();
155         }
156 
157         /**
158          * Get his avatar URL.
159          * @return URL of the avatar
160          * @throws IOException If it fails
161          */
162         public URL avatarUrl() throws IOException {
163             return new URL(this.jsn.text("avatar_url"));
164         }
165 
166         /**
167          * Get his URL.
168          * @return URL of the user
169          * @throws IOException If it fails
170          */
171         public URL url() throws IOException {
172             return new URL(this.jsn.text("url"));
173         }
174 
175         /**
176          * Get his name.
177          * @return User name
178          * @throws IOException If it fails
179          */
180         public String name() throws IOException {
181             final JsonObject json = this.json();
182             if (!json.containsKey("name")) {
183                 throw new IllegalStateException(
184                     String.format(
185                         // @checkstyle LineLength (1 line)
186                         "User %s doesn't have a name specified in his/her Github account; use #hasName() first.",
187                         this.login()
188                     )
189                 );
190             }
191             return json.getString("name");
192         }
193 
194         /**
195          * Check if user has name.
196          * @return True if user has name
197          * @throws IOException If it fails
198          */
199         public boolean hasName() throws IOException {
200             return this.json().containsKey("name");
201         }
202 
203         /**
204          * Get his company.
205          * @return Company name
206          * @throws IOException If it fails
207          */
208         public String company() throws IOException {
209             return this.jsn.text("company");
210         }
211 
212         /**
213          * Get his location.
214          * @return Location name
215          * @throws IOException If it fails
216          */
217         public String location() throws IOException {
218             return this.jsn.text("location");
219         }
220 
221         /**
222          * Get his email.
223          * @return Email
224          * @throws IOException If it fails
225          */
226         public String email() throws IOException {
227             return this.jsn.text("email");
228         }
229 
230         @Override
231         public Github github() {
232             return this.user.github();
233         }
234 
235         @Override
236         public String login() throws IOException {
237             return this.user.login();
238         }
239 
240         @Override
241         public UserOrganizations organizations() {
242             return this.user.organizations();
243         }
244 
245         @Override
246         public PublicKeys keys() {
247             return this.user.keys();
248         }
249 
250         @Override
251         public UserEmails emails() {
252             return this.user.emails();
253         }
254 
255         @Override
256         public Notifications notifications() throws IOException {
257             return this.user.notifications();
258         }
259 
260         @Override
261         public void markAsRead(final Date lastread) throws IOException {
262             this.user.markAsRead(lastread);
263         }
264 
265         @Override
266         public JsonObject json() throws IOException {
267             return this.user.json();
268         }
269 
270         @Override
271         public void patch(
272             final JsonObject json
273         ) throws IOException {
274             this.user.patch(json);
275         }
276 
277         /**
278          * Returns the value of html_url property of User's JSON.
279          * @return The 'html_url' property value.
280          * @throws IOException If any I/O error occurs.
281          */
282         public String htmlUrl() throws IOException {
283             return this.jsn.text("html_url");
284         }
285 
286         /**
287          * Returns the value of followers_url property of User's JSON.
288          * @return The 'followers_url' property value.
289          * @throws IOException If any I/O error occurs.
290          */
291         public String followersUrl() throws IOException {
292             return this.jsn.text("followers_url");
293         }
294 
295         /**
296          * Returns the value of following_url property of User's JSON.
297          * @return The 'following_url' property value.
298          * @throws IOException If any I/O error occurs.
299          */
300         public String followingUrl() throws IOException {
301             return this.jsn.text("following_url");
302         }
303 
304         /**
305          * Returns the value of gists_url property of User's JSON.
306          * @return The 'gists_url' property value.
307          * @throws IOException If any I/O error occurs.
308          */
309         public String gistsUrl() throws IOException {
310             return this.jsn.text("gists_url");
311         }
312 
313         /**
314          * Returns the value of starred_url property of User's JSON.
315          * @return The 'starred_url' property value.
316          * @throws IOException If any I/O error occurs.
317          */
318         public String starredUrl() throws IOException {
319             return this.jsn.text("starred_url");
320         }
321 
322         /**
323          * Returns the value of subscriptions_url property of User's JSON.
324          * @return The 'subscriptions_url' property value.
325          * @throws IOException If any I/O error occurs.
326          */
327         public String subscriptionsUrl() throws IOException {
328             return this.jsn.text("subscriptions_url");
329         }
330 
331         /**
332          * Returns the value of organizations_url property of User's JSON.
333          * @return The 'organizations_url' property value.
334          * @throws IOException If any I/O error occurs.
335          */
336         public String organizationsUrl() throws IOException {
337             return this.jsn.text("organizations_url");
338         }
339 
340         /**
341          * Returns the value of repos_url property of User's JSON.
342          * @return The 'repos_url' property value.
343          * @throws IOException If any I/O error occurs.
344          */
345         public String reposUrl() throws IOException {
346             return this.jsn.text("repos_url");
347         }
348 
349         /**
350          * Returns the value of events_url property of User's JSON.
351          * @return The 'events_url' property value.
352          * @throws IOException If any I/O error occurs.
353          */
354         public String eventsUrl() throws IOException {
355             return this.jsn.text("events_url");
356         }
357 
358         /**
359          * Returns the value of received_events_url property of User's JSON.
360          * @return The 'received_events_url' property value.
361          * @throws IOException If any I/O error occurs.
362          */
363         public String receivedEventsUrl() throws IOException {
364             return this.jsn.text("received_events_url");
365         }
366 
367         /**
368          * Returns the value of type property of User's JSON.
369          * @return The 'type' property value.
370          * @throws IOException If any I/O error occurs.
371          */
372         public String type() throws IOException {
373             return this.jsn.text("type");
374         }
375 
376         /**
377          * Returns the value of site_admin property of User's JSON.
378          * @return The 'site_admin' property value.
379          * @throws IOException If any I/O error occurs.
380          */
381         public boolean siteAdmin() throws IOException {
382             return "true".equals(this.jsn.text("site_admin"));
383         }
384 
385         /**
386          * Returns the value of blog property of User's JSON.
387          * @return The 'blog' property value.
388          * @throws IOException If any I/O error occurs.
389          */
390         public String blog() throws IOException {
391             return this.jsn.text("blog");
392         }
393 
394         /**
395          * Returns the value of hireable property of User's JSON.
396          * @return The 'hireable' property value.
397          * @throws IOException If any I/O error occurs.
398          */
399         public boolean hireable() throws IOException {
400             return "true".equals(this.jsn.text("hireable"));
401         }
402 
403         /**
404          * Returns the value of bio property of User's JSON.
405          * @return The 'bio' property value.
406          * @throws IOException If any I/O error occurs.
407          */
408         public String bio() throws IOException {
409             return this.jsn.text("bio");
410         }
411 
412         /**
413          * Returns the value of public_repos property of User's JSON.
414          * @return The 'public_repos' property value.
415          * @throws IOException If any I/O error occurs.
416          */
417         public int publicRepos() throws IOException {
418             return Integer.parseInt(this.jsn.text("public_repos"));
419         }
420 
421         /**
422          * Returns the value of public_gists property of User's JSON.
423          * @return The 'public_gists' property value.
424          * @throws IOException If any I/O error occurs.
425          */
426         public int publicGists() throws IOException {
427             return Integer.parseInt(this.jsn.text("public_gists"));
428         }
429 
430         /**
431          * Returns the value of followers property of User's JSON.
432          * @return The 'followers' property value.
433          * @throws IOException If any I/O error occurs.
434          */
435         public int followersCount() throws IOException {
436             return Integer.parseInt(this.jsn.text("followers"));
437         }
438 
439         /**
440          * Returns the value of following property of User's JSON.
441          * @return The 'following' property value.
442          * @throws IOException If any I/O error occurs.
443          */
444         public int followingCount() throws IOException {
445             return Integer.parseInt(this.jsn.text("following"));
446         }
447 
448         /**
449          * Returns the value of created_at property of User's JSON.
450          * @return The 'created_at' property value.
451          * @throws IOException If any I/O error occurs.
452          */
453         public Github.Time created() throws IOException {
454             try {
455                 return new Github.Time(this.jsn.text("created_at"));
456             } catch (final ParseException ex) {
457                 throw new IllegalArgumentException(
458                     "Cannot parse value of 'created_at' property",
459                     ex
460                 );
461             }
462         }
463 
464         /**
465          * Returns the value of updated_at property of User's JSON.
466          * @return The 'updated_at' property value.
467          * @throws IOException If any I/O error occurs.
468          */
469         public Github.Time updated() throws IOException {
470             try {
471                 return new Github.Time(this.jsn.text("updated_at"));
472             } catch (final ParseException ex) {
473                 throw new IllegalArgumentException(
474                     "Cannot parse value of 'updated_at' property",
475                     ex
476                 );
477             }
478         }
479     }
480 }