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.google.common.base.Optional;
33  import com.jcabi.aspects.Immutable;
34  import com.jcabi.aspects.Loggable;
35  import java.io.IOException;
36  import java.util.HashMap;
37  import java.util.Map;
38  import javax.json.Json;
39  import javax.json.JsonObject;
40  import javax.json.JsonObjectBuilder;
41  import javax.json.JsonValue;
42  import lombok.EqualsAndHashCode;
43  import lombok.ToString;
44  
45  /**
46   * Github Repo API.
47   *
48   * @author Yegor Bugayenko (yegor256@gmail.com)
49   * @version $Id: 68f582e486584d6dd01444aeb8d5b0243430792c $
50   * @since 0.5
51   * @see <a href="https://developer.github.com/v3/repos/">Repos API</a>
52   */
53  @SuppressWarnings("PMD.TooManyMethods")
54  @Immutable
55  public interface Repos {
56  
57      /**
58       * Get its owner.
59       * @return Github
60       */
61      Github github();
62      //byte[]
63  
64      /**
65       * Create repository.
66       * @param settings Settings to use for creating the new repository
67       * @return Repository
68       * @throws IOException If there is any I/O problem
69       * @since 0.5
70       * @see <a href="https://developer.github.com/v3/repos/#create">Create Repository</a>
71       */
72      Repo create(RepoCreate settings)
73          throws IOException;
74  
75      /**
76       * Get repository by name.
77       * @param coords Repository name in "user/repo" format
78       * @return Repository
79       * @see <a href="https://developer.github.com/v3/repos/#get">Get Repository</a>
80       */
81      Repo get(Coordinates coords);
82  
83      /**
84       * Remove repository by name.
85       *
86       * <p>Note: Deleting a repository requires admin access.
87       * If OAuth is used, the delete_repo scope is required.
88       *
89       * @param coords Repository name in "user/repo" format
90       * @throws IOException If there is any I/O problem
91       * @see <a href="https://developer.github.com/v3/repos/#delete-a-repository">Delete a Repository</a>
92       */
93      void remove(Coordinates coords) throws IOException;
94  
95      /**
96       * Iterate all public repos, starting with the one you've seen already.
97       * @param identifier The integer ID of the last Repo that you’ve seen.
98       * @return Iterator of repo
99       * @see <a href="https://developer.github.com/v3/repos/#list-all-public-repositories">List all public repositories</a>
100      */
101     Iterable<Repo> iterate(
102         String identifier
103     );
104 
105     /**
106      * Check if a repository exists on Github.
107      * @param coords Coordinates of the repo.
108      * @return True if it exists, false otherwise.
109      * @throws IOException If something goes wrong.
110      */
111     boolean exists(final Coordinates coords) throws IOException;
112 
113     /**
114      * Settings to use when creating a new GitHub repository.
115      *
116      * @author Chris Rebert (github@rebertia.com)
117      * @version $Id: 68f582e486584d6dd01444aeb8d5b0243430792c $
118      * @since 0.24
119      * @see <a href="https://developer.github.com/v3/repos/#create">Create Repo API</a>
120      * @todo #1095:30m Add the ability to set the other parameters of
121      *  the repo creation API (has_issues, has_wiki, has_downloads,
122      *  team_id, gitignore_template, license_template).
123      */
124     @SuppressWarnings("PMD.TooManyMethods")
125     @ToString
126     @Loggable(Loggable.DEBUG)
127     @EqualsAndHashCode(of = {"nam", "priv", "descr", "home", "init"})
128     final class RepoCreate implements JsonReadable {
129         /**
130          * Name of the new repo.
131          */
132         private final transient String nam;
133         /**
134          * Privateness of the new repo.
135          */
136         private final transient boolean priv;
137         /**
138          * Description of the new repo.
139          */
140         private final transient String descr;
141         /**
142          * Homepage of the new repo.
143          */
144         private final transient String home;
145         /**
146          * Auto-init the new repo?
147          */
148         private final transient Optional<Boolean> init;
149         /**
150          * Organization where the created repo belongs.
151          */
152         private final transient String organization;
153 
154         /**
155          * Other parameters which repo might have.
156          */
157         private final transient Map<String, JsonValue> other;
158 
159         /**
160          * Public ctor.
161          * @param nme Name of the new repository. Cannot be empty.
162          * @param prvt Will the new repo be private?
163          *  If not, then it will be public.
164          */
165         public RepoCreate(final String nme, final boolean prvt) {
166             this(nme, prvt, "", "", Optional.<Boolean>absent(), "");
167         }
168 
169         /**
170          * Private ctor.
171          * @param nme Name of the new repo. Cannot be empty.
172          * @param prvt Will the new repo be private?
173          *  If not, then it will be public.
174          * @param desc Description of the new repo
175          * @param page Homepage of the new repo
176          * @param auto Auto-init the new repo?
177          * @param org Organization to which this repo belongs.
178          *  When empty or null, the repo is created under the
179          *  authenticated user.
180          * @checkstyle ParameterNumberCheck (7 lines)
181          */
182         private RepoCreate(
183             final String nme,
184             final boolean prvt,
185             final String desc,
186             final String page,
187             final Optional<Boolean> auto,
188             final String org
189         ) {
190             if (nme.isEmpty()) {
191                 throw new IllegalArgumentException("Name cannot be empty!");
192             }
193             this.nam = nme;
194             this.priv = prvt;
195             this.descr = desc;
196             this.home = page;
197             this.init = auto;
198             this.organization = org;
199             this.other = new HashMap<>(0);
200         }
201 
202         /**
203          * Name of the new repo.
204          * @return Name
205          */
206         public String name() {
207             return this.nam;
208         }
209 
210         /**
211          * Will the new repo be private? If not, then it will be public.
212          * @return Is this repo private?
213          */
214         public boolean isPrivate() {
215             return this.priv;
216         }
217 
218         /**
219          * Description of the new repo.
220          * If it has no description, this is an empty string.
221          * @return Description
222          */
223         public String description() {
224             return this.descr;
225         }
226 
227         /**
228          * Homepage of the new repo.
229          * If it has no homepage, this is an empty string.
230          * @return Homepage
231          */
232         public String homepage() {
233             return this.home;
234         }
235 
236         /**
237          * Auto-init the new repo?
238          * If absent, the GitHub default will be used.
239          * @return Optional boolean
240          */
241         public Optional<Boolean> autoInit() {
242             return this.init;
243         }
244 
245         /**
246          * Name of the organization to which this repo belongs.
247          * @return String org name
248          */
249         public String organization() {
250             return this.organization;
251         }
252 
253         /**
254          * Returns a RepoCreate with the given name.
255          * The name cannot be empty.
256          * @param nme Name of the new repo
257          * @return RepoCreate
258          */
259         public RepoCreate withName(
260             final String nme
261         ) {
262             return new RepoCreate(
263                 nme,
264                 this.priv,
265                 this.descr,
266                 this.home,
267                 this.init,
268                 this.organization
269             );
270         }
271 
272         /**
273          * Returns a RepoCreate with the given privacy.
274          * @param privacy Privateness of the new repo
275          * @return RepoCreate
276          */
277         public RepoCreate withPrivacy(final boolean privacy) {
278             return new RepoCreate(
279                 this.nam,
280                 privacy,
281                 this.descr,
282                 this.home,
283                 this.init,
284                 this.organization
285             );
286         }
287 
288         /**
289          * Returns a RepoCreate with the given description.
290          * @param desc Description
291          * @return RepoCreate
292          */
293         public RepoCreate withDescription(
294             final String desc
295         ) {
296             return new RepoCreate(
297                 this.nam,
298                 this.priv,
299                 desc,
300                 this.home,
301                 this.init,
302                 this.organization
303             );
304         }
305 
306         /**
307          * Returns a RepoCreate with the given homepage.
308          * @param page Homepage URL
309          * @return RepoCreate
310          */
311         public RepoCreate withHomepage(
312             final String page
313         ) {
314             return new RepoCreate(
315                 this.nam,
316                 this.priv,
317                 this.descr,
318                 page,
319                 this.init,
320                 this.organization
321             );
322         }
323 
324         /**
325          * Returns a RepoCreate with the given auto-init enabledness.
326          * @param auto Auto-init the new repo?
327          * @return RepoCreate
328          */
329         public RepoCreate withAutoInit(final Optional<Boolean> auto) {
330             return new RepoCreate(
331                 this.nam,
332                 this.priv,
333                 this.descr,
334                 this.home,
335                 auto,
336                 this.organization
337             );
338         }
339 
340         /**
341          * Returns a RepoCreate with the given auto-init enabledness.
342          * @param auto Auto-init the new repo?
343          * @return RepoCreate
344          */
345         public RepoCreate withAutoInit(final boolean auto) {
346             return new RepoCreate(
347                 this.nam,
348                 this.priv,
349                 this.descr,
350                 this.home,
351                 Optional.of(auto),
352                 this.organization
353             );
354         }
355 
356         /**
357          * Returns a RepoCreate with the given organization.
358          * @param org Organization to which this repo belongs.
359          * @return RepoCreate
360          */
361         public RepoCreate withOrganization(final String org) {
362             return new RepoCreate(
363                 this.nam,
364                 this.priv,
365                 this.descr,
366                 this.home,
367                 this.init,
368                 org
369             );
370         }
371 
372         /**
373          * Returns a RepoCreate with the given json fields.
374          * @param key Json key
375          * @param value Json value
376          * @return The same RepoCreate.
377          * @todo #1660:30min Make 'with' method immutable.
378          *  Currently, the 'with' method mutates the 'other' field.
379          *  This is not ideal, as it makes the class mutable.
380          *  Make the 'with' method immutable and return a new
381          *  RepoCreate object with the new field.
382          */
383         public RepoCreate with(final String key, final JsonValue value) {
384             this.other.put(key, value);
385             return this;
386         }
387 
388         @Override
389         public JsonObject json() {
390             JsonObjectBuilder builder = Json.createObjectBuilder()
391                 .add("name", this.nam)
392                 .add("description", this.descr)
393                 .add("homepage", this.home)
394                 .add("private", this.priv);
395             if (this.init.isPresent()) {
396                 builder = builder.add("auto_init", this.init.get());
397             }
398             for (final Map.Entry<String, JsonValue> entry
399                 : this.other.entrySet()) {
400                 builder.add(entry.getKey(), entry.getValue());
401             }
402             return builder.build();
403         }
404     }
405 }