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.Json;
39  import javax.json.JsonObject;
40  import javax.json.JsonValue;
41  import lombok.EqualsAndHashCode;
42  import lombok.ToString;
43  
44  /**
45   * Github release.
46   *
47   * @author Paul Polishchuk (ppol@ua.fm)
48   * @version $Id: 20dc89771f410b739f27711507360b1f0e031b15 $
49   * @since 0.8
50   * @see <a href="https://developer.github.com/v3/repos/releases/">Releases API</a>
51   * @checkstyle MultipleStringLiterals (500 lines)
52   */
53  @Immutable
54  @SuppressWarnings("PMD.TooManyMethods")
55  public interface Release extends JsonReadable, JsonPatchable {
56  
57      /**
58       * Owner of them.
59       * @return Repo
60       */
61      Repo repo();
62  
63      /**
64       * Release id.
65       * @return Id
66       */
67      int number();
68  
69      /**
70       * Deletes a release.
71       * @throws IOException If any I/O problems occur.
72       */
73      void delete() throws IOException;
74  
75      /**
76       * Get all release assets of this release.
77       * @return Release assets.
78       * @see <a href="https://developer.github.com/v3/repos/releases/">Releases API</a>
79       */
80      ReleaseAssets assets();
81  
82      /**
83       * Smart release.
84       */
85      @Immutable
86      @ToString
87      @Loggable(Loggable.DEBUG)
88      @EqualsAndHashCode(of = { "release", "jsn" })
89      final class Smart implements Release {
90  
91          /**
92           * Encapsulated release.
93           */
94          private final transient Release release;
95          /**
96           * SmartJson object for convenient JSON parsing.
97           */
98          private final transient SmartJson jsn;
99  
100         /**
101          * Public CTOR.
102          * @param original Original release
103          */
104         public Smart(
105             final Release original
106         ) {
107             this.release = original;
108             this.jsn = new SmartJson(original);
109         }
110 
111         @Override
112         public JsonObject json() throws IOException {
113             return this.release.json();
114         }
115 
116         @Override
117         public void patch(
118             final JsonObject json
119         ) throws IOException {
120             this.release.patch(json);
121         }
122 
123         @Override
124         public Repo repo() {
125             return this.release.repo();
126         }
127 
128         @Override
129         public int number() {
130             return this.release.number();
131         }
132 
133         @Override
134         public ReleaseAssets assets() {
135             return this.release.assets();
136         }
137 
138         /**
139          * Get release url.
140          * @return Release url
141          * @throws IOException If there is any I/O problem
142          */
143         public URL url() throws IOException {
144             return new URL(this.jsn.text("url"));
145         }
146 
147         /**
148          * Get release html url.
149          * @return Release html url
150          * @throws IOException If there is any I/O problem
151          */
152         public URL htmlUrl() throws IOException {
153             return new URL(this.jsn.text("html_url"));
154         }
155 
156         /**
157          * Get release assets url.
158          * @return Release assets url
159          * @throws IOException If there is any I/O problem
160          */
161         public URL assetsUrl() throws IOException {
162             return new URL(this.jsn.text("assets_url"));
163         }
164 
165         /**
166          * Get release upload url.
167          * @return Release upload url
168          * @throws IOException If there is any I/O problem
169          */
170         public URL uploadUrl() throws IOException {
171             return new URL(this.jsn.text("upload_url"));
172         }
173 
174         /**
175          * Get release tag name.
176          * @return The release tag name
177          * @throws IOException If there is any I/O problem
178          */
179         public String tag() throws IOException {
180             return this.jsn.text("tag_name");
181         }
182 
183         /**
184          * Has release tag?
185          * @return TRUE if tag exists
186          * @throws IOException If there is any I/O problem
187          * @since 0.21
188          */
189         public boolean hasTag() throws IOException {
190             return this.jsn.hasNotNull("tag_name");
191         }
192 
193         /**
194          * Change its tag name.
195          * @param text Tag name
196          * @throws IOException If there is any I/O problem
197          */
198         public void tag(
199             final String text
200         ) throws IOException {
201             this.release.patch(
202                 Json.createObjectBuilder().add("tag_name", text).build()
203             );
204         }
205 
206         /**
207          * Get release target commitish.
208          * @return Release target commitish value
209          * @throws IOException If there is any I/O problem
210          */
211         public String commitish() throws IOException {
212             return this.jsn.text("target_commitish");
213         }
214 
215         /**
216          * Change its target commitish.
217          * @param text Target commitish.
218          * @throws IOException If there is any I/O problem
219          */
220         public void commitish(
221             final String text
222         ) throws IOException {
223             this.release.patch(
224                 Json.createObjectBuilder()
225                     .add("target_commitish", text)
226                     .build()
227             );
228         }
229 
230         /**
231          * Does this release have a name?
232          * @return Whether this release has a name
233          * @throws IOException If there is any I/O problem
234          */
235         public boolean hasName() throws IOException {
236             return this.jsn.hasNotNull("name");
237         }
238 
239         /**
240          * Get release name. Note that there may not be one, so make sure to
241          * check with {@link Release.Smart#hasName()} first.
242          * @return Release name
243          * @throws IOException If there is any I/O problem
244          */
245         public String name() throws IOException {
246             return this.jsn.text("name");
247         }
248 
249         /**
250          * Change its name.
251          * @param text Name of release.
252          * @throws IOException If there is any I/O problem
253          */
254         public void name(
255             final String text
256         ) throws IOException {
257             this.release.patch(
258                 Json.createObjectBuilder().add("name", text).build()
259             );
260         }
261 
262         /**
263          * Has release body.
264          * @return TRUE if release body exists
265          * @throws IOException If there is any I/O problem
266          */
267         public boolean hasBody() throws IOException {
268             return this.jsn.hasNotNull("body");
269         }
270 
271         /**
272          * Get release body.
273          * @return Release body
274          * @throws IOException If there is any I/O problem
275          */
276         public String body() throws IOException {
277             final String body;
278             if (this.hasBody()) {
279                 body = this.jsn.text("body");
280             } else {
281                 body = "";
282             }
283             return body;
284         }
285 
286         /**
287          * Change its body.
288          * @param text Text describing the contents of the tag
289          * @throws IOException If there is any I/O problem
290          */
291         public void body(
292             final String text
293         ) throws IOException {
294             this.release.patch(
295                 Json.createObjectBuilder().add("body", text).build()
296             );
297         }
298 
299         /**
300          * Get release creation date.
301          * @return Release creation date
302          * @throws IOException If there is any I/O problem
303          */
304         public Date createdAt() throws IOException {
305             try {
306                 return new Github.Time(this.jsn.text("created_at"))
307                     .date();
308             } catch (final ParseException ex) {
309                 throw new IOException(ex);
310             }
311         }
312 
313         /**
314          * Get release publication date.
315          * @return Release publication date
316          * @throws IOException If there is any I/O problem
317          */
318         public Date publishedAt() throws IOException {
319             try {
320                 return new Github.Time(this.jsn.text("published_at"))
321                     .date();
322             } catch (final ParseException ex) {
323                 throw new IOException(ex);
324             }
325         }
326 
327         /**
328          * Is release draft.
329          * @return Returns true if it's draft
330          * @throws IOException If there is any I/O problem
331          */
332         public boolean draft() throws IOException {
333             return this.json().getBoolean("draft", Boolean.FALSE);
334         }
335 
336         /**
337          * Change its status.
338          * @param draft True makes the release a draft.
339          * @throws IOException If there is any I/O problem
340          */
341         public void draft(final boolean draft) throws IOException {
342             this.release.patch(
343                 Json.createObjectBuilder().add("draft", draft).build()
344             );
345         }
346 
347         /**
348          * Is it prerelease.
349          * @return Returns true if it's prerelease
350          * @throws IOException If there is any I/O problem
351          */
352         public boolean prerelease() throws IOException {
353             return Boolean.parseBoolean(
354                 this.json()
355                     .getOrDefault("prerelease", JsonValue.FALSE)
356                     .toString().replace("\"", "")
357             );
358         }
359 
360         /**
361          * Change its prerelease.
362          * @param pre True to identify the release as a prerelease.
363          * @throws IOException If there is any I/O problem
364          */
365         public void prerelease(final boolean pre) throws IOException {
366             this.release.patch(
367                 Json.createObjectBuilder().add("prerelease", pre).build()
368             );
369         }
370 
371         @Override
372         public void delete() throws IOException {
373             this.release.delete();
374         }
375 
376     }
377 
378 }