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 lombok.EqualsAndHashCode;
34  import org.apache.commons.lang3.builder.CompareToBuilder;
35  
36  /**
37   * Repository coordinates.
38   *
39   * @author Yegor Bugayenko (yegor256@gmail.com)
40   * @version $Id: 3549595fd6b33ee8e8bff7bd5c598c0eb57632e5 $
41   * @since 0.1
42   */
43  @Immutable
44  public interface Coordinates extends Comparable<Coordinates> {
45  
46      /**
47       * Coordinate pats separator.
48       */
49      String SEPARATOR = "/";
50  
51      /**
52       * Get usr name.
53       * @return User name
54       */
55      String user();
56  
57      /**
58       * Get rpo name.
59       * @return Repo name
60       */
61      String repo();
62  
63      /**
64       * Jcabi.http implementation.
65       */
66      @Immutable
67      @EqualsAndHashCode(of = {"usr", "rpo"})
68      final class Simple implements Coordinates {
69          /**
70           * User name.
71           */
72          private final transient String usr;
73          /**
74           * Repository name.
75           */
76          private final transient String rpo;
77  
78          /**
79           * Public ctor.
80           * @param user User name
81           * @param repo Repository name
82           */
83          public Simple(final String user, final String repo) {
84              this.usr = user;
85              this.rpo = repo;
86          }
87  
88          /**
89           * Public ctor.
90           * @param mnemo Mnemo name
91           */
92          public Simple(final String mnemo) {
93              final String[] parts = mnemo.split(Coordinates.SEPARATOR, 2);
94              if (parts.length != 2) {
95                  throw new IllegalArgumentException(
96                      String.format("invalid coordinates '%s'", mnemo)
97                  );
98              }
99              this.usr = parts[0];
100             this.rpo = parts[1];
101         }
102 
103         @Override
104         public String toString() {
105             return String.format("%s/%s", this.usr, this.rpo);
106         }
107 
108         @Override
109         public String user() {
110             return this.usr;
111         }
112 
113         @Override
114         public String repo() {
115             return this.rpo;
116         }
117 
118         @Override
119         public int compareTo(final Coordinates other) {
120             return new CompareToBuilder()
121                 .append(this.usr, other.user())
122                 .append(this.rpo, other.repo())
123                 .build();
124         }
125     }
126 
127     /**
128      * Implementation of HTTPs coordinates.
129      * @author volodya-lombrozo
130      */
131     @Immutable
132     @EqualsAndHashCode
133     final class Https implements Coordinates {
134 
135         /**
136          * Github domain.
137          */
138         private static final String DOMAIN = "https://github.com/";
139 
140         /**
141          * URL.
142          */
143         private final String url;
144 
145         /**
146          * Public ctor.
147          * @param https URL
148          */
149         public Https(final String https) {
150             this.url = https;
151         }
152 
153         @Override
154         public String user() {
155             return this.split()[0];
156         }
157 
158         @Override
159         public String repo() {
160             final String repo = this.split()[1];
161             final String suffix = ".git";
162             if (repo.endsWith(suffix)) {
163                 return repo.substring(0, repo.length() - suffix.length());
164             } else {
165                 return repo;
166             }
167         }
168 
169         @Override
170         public int compareTo(final Coordinates other) {
171             return new CompareToBuilder()
172                 .append(this.user(), other.user())
173                 .append(this.repo(), other.repo())
174                 .build();
175         }
176 
177         /**
178          * Split URL.
179          * @return Array of repo coordinates.
180          */
181         private String[] split() {
182             if (!this.url.startsWith(Https.DOMAIN)) {
183                 throw new IllegalArgumentException(
184                     String.format(
185                         "Invalid URL, the '%s' should start with '%s'",
186                         this.url,
187                         Https.DOMAIN
188                     )
189                 );
190             }
191             return this.url.substring(Https.DOMAIN.length())
192                 .split(Coordinates.SEPARATOR, 2);
193         }
194     }
195 }