View Javadoc

1   /*
2    * LICENSE
3    *
4    * "THE BEER-WARE LICENSE" (Revision 42):
5    * "Sven Strittmatter" <ich@weltraumschaf.de> wrote this file.
6    * As long as you retain this notice you can do whatever you want with
7    * this stuff. If we meet some day, and you think this stuff is worth it,
8    * you can buy me a beer in return.
9    */
10  package org.jenkinsci.plugins.darcs;
11  
12  import hudson.model.User;
13  import hudson.scm.ChangeLogSet;
14  import hudson.scm.EditType;
15  
16  import java.util.ArrayList;
17  import java.util.Arrays;
18  import java.util.List;
19  
20  import org.kohsuke.stapler.export.Exported;
21  
22  /**
23   * Represents a change set (aka. a patch in Darcs).
24   *
25   * <p>
26   * The object should be treated like an immutable object.
27   *
28   * @author Sven Strittmatter <ich@weltraumschaf.de>
29   */
30  public class DarcsChangeSet extends ChangeLogSet.Entry {
31  
32      /**
33       * The patch author.
34       */
35      private String author;
36      /**
37       * The patch date in UTC.
38       */
39      private String date;
40      /**
41       * Localized patch date.
42       */
43      private String localDate;
44      /**
45       * Whether it is an inversion of an other patch.
46       */
47      private boolean inverted;
48      /**
49       * The patches unique has.
50       */
51      private String hash;
52      /**
53       * The patch name.
54       */
55      private String name;
56      /**
57       * The patch long comment.
58       */
59      private String comment;
60      /**
61       * Filles added by this patch.
62       */
63      private List<String> added = new ArrayList<String>();
64      /**
65       * Filles deleted by this patch.
66       */
67      private List<String> deleted = new ArrayList<String>();
68      /**
69       * Filles modified by this patch.
70       */
71      private List<String> modified = new ArrayList<String>();
72  
73      /**
74       * Returns the author as User object.
75       *
76       * If you want the parsed author string from Darcs call getPlainAuthor().
77       *
78       * @return a Jenkins user object
79       */
80      @Exported
81      public User getAuthor() {
82          return User.get(getPlainAuthor());
83      }
84  
85      /**
86       * Returns the plain author string used in the Darcs repository.
87       *
88       * @return author name
89       */
90      public String getPlainAuthor() {
91          return author;
92      }
93  
94      /**
95       * Returns the patch comment.
96       *
97       * @return comment message
98       */
99      @Exported
100     public String getComment() {
101         return comment;
102     }
103 
104     /**
105      * Returns the patch date as string.
106      *
107      * @return date string in UTC
108      */
109     @Exported
110     public String getDate() {
111         return date;
112     }
113 
114     /**
115      * Returns the unique hash string of the patch.
116      *
117      * @return hash string
118      */
119     @Exported
120     public String getHash() {
121         return hash;
122     }
123 
124     /**
125      * Returns whether the patch is inverted or not.
126      *
127      * @return {@code true} if it is an inverse patch, else {@code false}
128      */
129     @Exported
130     public boolean isInverted() {
131         return inverted;
132     }
133 
134     /**
135      * Returns the localized date string.
136      *
137      * @return local date string in UTC
138      */
139     @Exported
140     public String getLocalDate() {
141         return localDate;
142     }
143 
144     /**
145      * Returns the patch name.
146      *
147      * @return the patch name
148      */
149     @Exported
150     public String getName() {
151         return name;
152     }
153 
154     /**
155      * Method for fulfill the interface.
156      *
157      * Delegates to {@link #getComment()}.
158      *
159      * @return same as {@link #getComment()}
160      */
161     @Override
162     public String getMsg() {
163         return getComment();
164     }
165 
166     /**
167      * Sets the author string from Darcs.
168      *
169      * Thus this object should be treated as immutable, this setter should only be called from the DarcsChangeLogParser.
170      *
171      * @param anAuthor author name string
172      */
173     public void setAuthor(final String anAuthor) {
174         author = anAuthor;
175     }
176 
177     /**
178      * Sets the comment string.
179      *
180      * Thus this object should be treated as immutable, this setter should only be called from the DarcsChangeLogParser.
181      *
182      * @param aComment patch comment message
183      */
184     public void setComment(final String aComment) {
185         comment = aComment;
186     }
187 
188     /**
189      * Sets the date string.
190      *
191      * Thus this object should be treated as immutable, this setter should only be called from the DarcsChangeLogParser.
192      *
193      * @param aDate date in UTC
194      */
195     public void setDate(final String aDate) {
196         date = aDate;
197     }
198 
199     /**
200      * Sets the hash string.
201      *
202      * Thus this object should be treated as immutable, this setter should only be called from the DarcsChangeLogParser.
203      *
204      * @param aHash hash string
205      */
206     public void setHash(final String aHash) {
207         hash = aHash;
208     }
209 
210     /**
211      * Sets the inverted flag.
212      *
213      * Thus this object should be treated as immutable, this setter should only be called from the DarcsChangeLogParser.
214      *
215      * @param isInverted {@code true} if it is an inverse patch, else {@code false}
216      */
217     public void setInverted(final boolean isInverted) {
218         inverted = isInverted;
219     }
220 
221     /**
222      * Sets the localized date string.
223      *
224      * Thus this object should be treated as immutable, this setter should only be called from the DarcsChangeLogParser.
225      *
226      * @param aLocalDate date in UTC
227      */
228     public void setLocalDate(final String aLocalDate) {
229         localDate = aLocalDate;
230     }
231 
232     /**
233      * Sets the patch name.
234      *
235      * Thus this object should be treated as immutable, this setter should only be called from the DarcsChangeLogParser.
236      *
237      * @param aName patch name
238      */
239     public void setName(final String aName) {
240         name = aName;
241     }
242 
243     /**
244      * Returns a lazy computed list of all files affected by this patch.
245      *
246      * @return the list is recalculated on each call
247      */
248     @Override
249     public List<String> getAffectedPaths() {
250         return new ArrayList<String>() {
251             {
252                 addAll(added);
253                 addAll(deleted);
254                 addAll(modified);
255             }
256         };
257     }
258 
259     /**
260      * Gets all the files that were added.
261      *
262      * @return modifiable list
263      */
264     @Exported
265     public List<String> getAddedPaths() {
266         return added;
267     }
268 
269     /**
270      * Gets all the files that were deleted.
271      *
272      * @return modifiable list
273      */
274     @Exported
275     public List<String> getDeletedPaths() {
276         return deleted;
277     }
278 
279     /**
280      * Gets all the files that were modified.
281      *
282      * @return modifiable list
283      */
284     @Exported
285     public List<String> getModifiedPaths() {
286         return modified;
287     }
288 
289     /**
290      * Convenience method for getting affected paths by type.
291      *
292      * @param kind one of {@link EditType#ADD}, {@link EditType#EDIT}, {@link EditType#DELETE}
293      * @return list associated to the edit type
294      */
295     public List<String> getPaths(final EditType kind) {
296         if (kind == EditType.ADD) {
297             return getAddedPaths();
298         }
299 
300         if (kind == EditType.EDIT) {
301             return getModifiedPaths();
302         }
303 
304         if (kind == EditType.DELETE) {
305             return getDeletedPaths();
306         }
307 
308         return null;
309     }
310 
311     @Override
312     protected void setParent(final ChangeLogSet parent) {
313         super.setParent(parent);
314     }
315 
316     /**
317      * Returns all three variations of {@link EditType}. Placed here to simplify access from views.
318      *
319      * @return available edit types
320      */
321     public List<EditType> getEditTypes() {
322         return Arrays.asList(EditType.ADD, EditType.EDIT, EditType.DELETE);
323     }
324 
325     @Override
326     public String toString() {
327         return "DarcsChangeSet{"
328                 + "hash=" + hash
329                 + ", name=" + name
330                 + ", author=" + author
331                 + ", date=" + date
332                 + ", localDate=" + localDate
333                 + ", inverted=" + inverted
334                 + ", added=" + added
335                 + ", modified=" + modified
336                 + ", deleted=" + deleted
337                 + '}';
338     }
339 
340     @Override
341     public int hashCode() {
342         return Arrays.hashCode(new Object[]{
343             added,
344             author,
345             comment,
346             date,
347             deleted,
348             hash,
349             inverted,
350             localDate,
351             modified,
352             name,
353         });
354     }
355 
356     @Override
357     public boolean equals(final Object obj) {
358         if (!(obj instanceof DarcsChangeSet)) {
359             return false;
360         }
361 
362         final DarcsChangeSet other = (DarcsChangeSet) obj;
363 
364         if (!equal(added, other.added)) {
365             return false;
366         }
367 
368         if (!equal(author, other.author)) {
369             return false;
370         }
371 
372         if (!equal(comment, other.comment)) {
373             return false;
374         }
375 
376         if (!equal(date, other.date)) {
377             return false;
378         }
379 
380         if (!equal(deleted, other.deleted)) {
381             return false;
382         }
383 
384         if (!equal(hash, other.hash)) {
385             return false;
386         }
387 
388         if (!equal(localDate, other.localDate)) {
389             return false;
390         }
391 
392         if (!equal(modified, other.modified)) {
393             return false;
394         }
395 
396         if (!equal(inverted, other.inverted)) {
397             return false;
398         }
399 
400         if (!equal(name, other.name)) {
401             return false;
402         }
403 
404         return true;
405     }
406 
407     /**
408      * Helper which respects {@code null} values.
409      *
410      * @param a first object to compare
411      * @param b second object to compare
412      * @return {@code true} if a and b are equal, else {@code false}
413      */
414     private static boolean equal(final Object a, final Object b) {
415         return a == b || (a != null && a.equals(b));
416     }
417 
418 }