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.Collection;
38 import java.util.Date;
39 import javax.json.Json;
40 import javax.json.JsonObject;
41 import lombok.EqualsAndHashCode;
42 import lombok.ToString;
43
44 /**
45 * Github issue comment.
46 *
47 * <p>Comment implements {@link JsonReadable}, that's how you can get its full
48 * details in JSON format. For example, to get its author's Github login
49 * you get the entire JSON and then gets its element:
50 *
51 * <pre>String login = comment.json()
52 * .getJsonObject("user")
53 * .getString("login");</pre>
54 *
55 * <p>However, it's better to use a supplementary "smart" decorator, which
56 * automates most of these operations:
57 *
58 * <pre>String login = new Comment.Smart(comment).author().login();</pre>
59 *
60 * @author Yegor Bugayenko (yegor256@gmail.com)
61 * @author Paulo Lobo (pauloeduardolobo@gmail.com)
62 * @version $Id: 9e492078f5c26ef887ad0c8b07cfbc5e573f06e1 $
63 * @since 0.1
64 * @see <a href="https://developer.github.com/v3/issues/comments/">Issue Comments API</a>
65 * @checkstyle MultipleStringLiterals (500 lines)
66 */
67 @Immutable
68 @SuppressWarnings("PMD.TooManyMethods")
69 public interface Comment
70 extends Comparable<Comment>, JsonReadable, JsonPatchable {
71
72 /**
73 * The issue it's in.
74 * @return Owner of the comment
75 */
76 Issue issue();
77
78 /**
79 * Number.
80 * @return Comment number
81 */
82 int number();
83
84 /**
85 * Delete the comment.
86 * @throws IOException If there is any I/O problem
87 * @see <a href="https://developer.github.com/v3/issues/comments/#delete-a-comment">Delete a Comment</a>
88 */
89 void remove() throws IOException;
90
91 /**
92 * Adds the reaction to the comment.
93 * @param reaction Reaction to be added.
94 * @throws IOException In case something goes wrong.
95 */
96 void react(Reaction reaction) throws IOException;
97
98 /**
99 * List the reactions of the comment.
100 * @return Comment reactions.
101 */
102 Iterable<Reaction> reactions();
103
104 /**
105 * Smart comment with additional features.
106 */
107 @Immutable
108 @ToString
109 @Loggable(Loggable.DEBUG)
110 @EqualsAndHashCode(of = { "comment", "jsn" })
111 final class Smart implements Comment {
112 /**
113 * Encapsulated comment.
114 */
115 private final transient Comment comment;
116
117 /**
118 * SmartJson object for convenient JSON parsing.
119 */
120 private final transient SmartJson jsn;
121
122 /**
123 * Public ctor.
124 * @param cmt Comment
125 */
126 public Smart(final Comment cmt) {
127 this.comment = cmt;
128 this.jsn = new SmartJson(cmt);
129 }
130 /**
131 * Get its author.
132 * @return Author of comment
133 * @throws IOException If there is any I/O problem
134 */
135 public User author() throws IOException {
136 return this.comment.issue().repo().github().users().get(
137 this.comment.json().getJsonObject("user").getString("login")
138 );
139 }
140 /**
141 * Get its body.
142 * @return Body of comment
143 * @throws IOException If there is any I/O problem
144 */
145 public String body() throws IOException {
146 return this.jsn.text("body");
147 }
148 /**
149 * Change comment body.
150 * @param text Body of comment
151 * @throws IOException If there is any I/O problem
152 */
153 public void body(final String text) throws IOException {
154 this.comment.patch(
155 Json.createObjectBuilder().add("body", text).build()
156 );
157 }
158 /**
159 * Get its URL.
160 * @return URL of comment
161 * @throws IOException If there is any I/O problem
162 */
163 public URL url() throws IOException {
164 return new URL(this.jsn.text("url"));
165 }
166 /**
167 * When this comment was created.
168 * @return Date of creation
169 * @throws IOException If there is any I/O problem
170 */
171 public Date createdAt() throws IOException {
172 try {
173 return new Github.Time(
174 this.jsn.text("created_at")
175 ).date();
176 } catch (final ParseException ex) {
177 throw new IOException(ex);
178 }
179 }
180 /**
181 * When this comment was updated last time.
182 * @return Date of update
183 * @throws IOException If there is any I/O problem
184 */
185 public Date updatedAt() throws IOException {
186 try {
187 return new Github.Time(
188 this.jsn.text("updated_at")
189 ).date();
190 } catch (final ParseException ex) {
191 throw new IOException(ex);
192 }
193 }
194 @Override
195 public Issue issue() {
196 return this.comment.issue();
197 }
198 @Override
199 public int number() {
200 return this.comment.number();
201 }
202 @Override
203 public void remove() throws IOException {
204 this.comment.remove();
205 }
206
207 @Override
208 public void react(final Reaction reaction) {
209 throw new UnsupportedOperationException("react() not implemented");
210 }
211
212 @Override
213 public Collection<Reaction> reactions() {
214 throw new UnsupportedOperationException(
215 "reactions() not implemented"
216 );
217 }
218
219 @Override
220 public JsonObject json() throws IOException {
221 return this.comment.json();
222 }
223 @Override
224 public void patch(final JsonObject json) throws IOException {
225 this.comment.patch(json);
226 }
227 @Override
228 public int compareTo(final Comment obj) {
229 return this.comment.compareTo(obj);
230 }
231 }
232
233 }