View Javadoc

1   /*
2       StatCvs - CVS statistics generation 
3       Copyright (C) 2002  Lukasz Pekacki <lukasz@pekacki.de>
4       http://statcvs.sf.net/
5       
6       This library is free software; you can redistribute it and/or
7       modify it under the terms of the GNU Lesser General Public
8       License as published by the Free Software Foundation; either
9       version 2.1 of the License, or (at your option) any later version.
10  
11      This library is distributed in the hope that it will be useful,
12      but WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14      Lesser General Public License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public
17      License along with this library; if not, write to the Free Software
18      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19      
20  	$Name:  $ 
21  	Created on $Date: 2008/04/02 11:22:15 $ 
22  */
23  package net.sf.statcvs.input;
24  
25  import java.util.Date;
26  import java.util.HashMap;
27  import java.util.Iterator;
28  import java.util.LinkedList;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.SortedSet;
32  
33  import net.sf.statcvs.model.Commit;
34  import net.sf.statcvs.model.Revision;
35  
36  /**
37   * Takes a set of revisions, and builds a <code>List</code> of 
38   * {@link Commit}s from it. The result list is sorted by date.
39   * 
40   * The implementation allows for a tolerance of several minutes
41   * between individual file commits, but author and message must be identical.
42   * 
43   * @author Richard Cyganiak
44   * @version $Id: CommitListBuilder.java,v 1.5 2008/04/02 11:22:15 benoitx Exp $
45   */
46  public class CommitListBuilder {
47      private static final int MAX_TIME_BETWEEN_CHANGES_MILLISECONDS = 300000;
48  
49      private final Iterator revisions;
50      private final Map currentCommits = new HashMap();
51      private List commits;
52  
53      /**
54       * Creates a new instance using the given set of {@link Revision}s.
55       * The set must be sorted by date, oldest first.
56       * 
57       * @param revisions a set of {@link Revision}s
58       */
59      public CommitListBuilder(final SortedSet revisions) {
60          this(revisions.iterator());
61      }
62  
63      public CommitListBuilder(final Iterator revisions) {
64          this.revisions = revisions;
65      }
66  
67      /**
68       * Creates a <code>List</code> of {@link Commit}s from the source iterator.
69       * The result list will be sorted by date.
70       * 
71       * @return a new list of {@link Commit} objects
72       */
73      public List createCommitList() {
74          if (commits != null) {
75              return commits;
76          }
77  
78          commits = new LinkedList();
79          while (revisions.hasNext()) {
80              processRevision((Revision) revisions.next());
81          }
82          return commits;
83      }
84  
85      protected void processRevision(final Revision rev) {
86          if (rev.getAuthor() == null) {
87              return;
88          }
89          final Commit commit = (Commit) currentCommits.get(rev.getAuthor());
90          if (commit == null || !isSameCommit(commit, rev)) {
91              addNewCommit(rev);
92          } else {
93              addRevToCommit(commit, rev);
94          }
95      }
96  
97      protected void addNewCommit(final Revision rev) {
98          final Commit newCommit = new Commit(rev);
99          currentCommits.put(rev.getAuthor(), newCommit);
100         commits.add(newCommit);
101     }
102 
103     protected void addRevToCommit(final Commit commit, final Revision rev) {
104         commit.addRevision(rev);
105     }
106 
107     /**
108      * Returns <code>true</code> if change is part of the commit, that is if
109      * they have the same author, the same message, and are within the same
110      * timeframe.
111      * 
112      * @param commit the commit
113      * @param rev the revision to check against this commit
114      * @return <code>true</code> if change is part of this commit
115      */
116     public static boolean isSameCommit(final Commit commit, final Revision rev) {
117         return commit.getAuthor().equals(rev.getAuthor()) && commit.getComment().equals(rev.getComment()) && isInTimeFrame(commit, rev.getDate());
118     }
119 
120     /**
121      * Returns <code>true</code> if the date lies within the timespan of
122      * the commit, plus/minus a tolerance.
123      * 
124      * @param date the date to check against this commit
125      * @return <code>true</code> if the date lies within the timespan of the commit
126      */
127     public static boolean isInTimeFrame(final Commit commit, final Date date) {
128         return date.getTime() > (commit.getDate().getTime() - MAX_TIME_BETWEEN_CHANGES_MILLISECONDS)
129                 && (date.getTime() < commit.getDate().getTime() + MAX_TIME_BETWEEN_CHANGES_MILLISECONDS);
130     }
131 }