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.Locale;
37  import javax.json.JsonObject;
38  import lombok.EqualsAndHashCode;
39  import lombok.ToString;
40  
41  /**
42   * File change.
43   * @author Chris Rebert (github@chrisrebert.com)
44   * @version $Id: 204a28f556e5211372eab281671ab30c3fbbaabb $
45   * @since 0.24
46   * @see <a href="https://developer.github.com/v3/repos/commits/#compare-two-commits">Compare two commits</a>
47   */
48  @Immutable
49  @SuppressWarnings("PMD.TooManyMethods")
50  public interface FileChange extends JsonReadable {
51      enum Status implements StringEnum {
52          /**
53           * File was added.
54           */
55          ADDED("added"),
56          /**
57           * File's content was modified.
58           */
59          MODIFIED("modified"),
60          /**
61           * File was removed.
62           */
63          REMOVED("removed"),
64          /**
65           * File was renamed.
66           */
67          RENAMED("renamed");
68  
69          /**
70           * File status string.
71           */
72          private final transient String status;
73  
74          /**
75           * Ctor.
76           * @param stat File status string.
77           */
78          Status(final String stat) {
79              this.status = stat;
80          }
81  
82          @Override
83          public String identifier() {
84              return this.status;
85          }
86  
87          /**
88           * Get file change status corresponding to the given status string.
89           * @param name Status string
90           * @return Status enum value
91           */
92          public static FileChange.Status forValue(final String name) {
93              return Status.valueOf(name.toUpperCase(Locale.ENGLISH));
94          }
95      }
96  
97      /**
98       * Smart file change with extra features.
99       */
100     @Immutable
101     @ToString
102     @Loggable(Loggable.DEBUG)
103     @EqualsAndHashCode(of = { "change", "jsn" })
104     @SuppressWarnings("PMD.TooManyMethods")
105     final class Smart implements FileChange {
106         /**
107          * Encapsulated file change.
108          */
109         private final transient FileChange change;
110         /**
111          * SmartJson object for convenient JSON parsing.
112          */
113         private final transient SmartJson jsn;
114 
115         /**
116          * Public ctor.
117          * @param chng File change
118          */
119         public Smart(final FileChange chng) {
120             this.change = chng;
121             this.jsn = new SmartJson(chng);
122         }
123 
124         /**
125          * File's commit SHA.
126          * @return SHA
127          * @throws IOException If there is any I/O problem
128          */
129         public String sha() throws IOException {
130             return this.jsn.text("sha");
131         }
132 
133         /**
134          * File's name. Includes the path to the file from the
135          * root directory of the repository. Does not start with a
136          * forward slash. Example: "foo/bar/baz.txt"
137          * @return Filename
138          * @throws IOException If there is any I/O problem
139          */
140         public String filename() throws IOException {
141             return this.jsn.text("filename");
142         }
143 
144         /**
145          * Status of the file in this change.
146          * @return File status
147          * @throws IOException If there is any I/O problem
148          */
149         public FileChange.Status status() throws IOException {
150             return FileChange.Status.forValue(this.jsn.text("status"));
151         }
152 
153         /**
154          * Number of lines added, or 0 if the file is binary.
155          * @return Number of lines added
156          * @throws IOException If there is any I/O problem
157          */
158         public int additions() throws IOException {
159             return this.jsn.number("additions");
160         }
161 
162         /**
163          * Number of lines deleted, or 0 if the file is binary.
164          * @return Number of lines deleted
165          * @throws IOException If there is any I/O problem
166          */
167         public int deletions() throws IOException {
168             return this.jsn.number("deletions");
169         }
170 
171         /**
172          * Number of lines modified, which is equal to the sum of
173          * {@link Smart#additions()} and {@link Smart#deletions()}.
174          * @return Number of lines modified
175          * @throws IOException If there is any I/O problem
176          */
177         public int changes() throws IOException {
178             return this.jsn.number("changes");
179         }
180 
181         /**
182          * Diff string of the changes to the file. Only available if
183          * the file is text (as opposed to binary).
184          * @return Diff string
185          * @throws IOException If there is any I/O problem
186          */
187         public Optional<String> patch() throws IOException {
188             return Optional.fromNullable(this.json().getString("patch", null));
189         }
190 
191         /**
192          * URL for the raw contents of the file.
193          * @return URL
194          * @throws IOException If there is any I/O problem
195          */
196         public String rawUrl() throws IOException {
197             return this.jsn.text("raw_url");
198         }
199 
200         /**
201          * URL for the file's git blob.
202          * @return URL
203          * @throws IOException If there is any I/O problem
204          */
205         public String blobUrl() throws IOException {
206             return this.jsn.text("blob_url");
207         }
208 
209         /**
210          * Repo contents URL for the file.
211          * @return URL
212          * @throws IOException If there is any I/O problem
213          */
214         public String contentsUrl() throws IOException {
215             return this.jsn.text("contents_url");
216         }
217 
218         @Override
219         public JsonObject json() throws IOException {
220             return this.change.json();
221         }
222     }
223 }