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 package net.sf.statcvs.model;
21
22 import java.util.Date;
23 import java.util.HashSet;
24 import java.util.Set;
25 import java.util.SortedSet;
26 import java.util.TreeSet;
27
28 /**
29 * Represents one versioned file in the {@link Repository Repository},
30 * including its name, {@link Directory} and {@link Revision} list.
31 * Revisions can be created using the <tt>addXXXRevision</tt> factory
32 * methods. Revisions can be created in any order.
33 *
34 * TODO: Rename class to something like VersionedFile, getCurrentLinesOfCode() to getCurrentLines(), maybe getFilenameXXX, isDead() to isDeleted()
35 *
36 * @author Manuel Schulze
37 * @author Richard Cyganiak <richard@cyganiak.de>
38 * @version $Id: VersionedFile.java,v 1.2 2008/04/02 11:22:16 benoitx Exp $
39 */
40 public class VersionedFile implements Comparable {
41 private final String filename;
42 private final SortedSet revisions = new TreeSet();
43 private final Directory directory;
44 private final Set authors = new HashSet();
45
46 /**
47 * Creates a VersionedFile object.
48 *
49 * @param name The full name of the file
50 * @param directory the directory where the file resides
51 */
52 public VersionedFile(final String name, final Directory directory) {
53 this.filename = name;
54 this.directory = directory;
55 if (directory != null) {
56 directory.addFile(this);
57 }
58 }
59
60 /**
61 * Returns a list of authors that have commited at least one revision of the file.
62 * @return a list of authors
63 */
64 public Set getAuthors() {
65 return authors;
66 }
67
68 /**
69 * Returns the full filename.
70 * @return the full filename
71 */
72 public String getFilenameWithPath() {
73 return filename;
74 }
75
76 /**
77 * Returns the filename without path.
78 * @return the filename without path
79 */
80 public String getFilename() {
81 final int lastDelim = this.filename.lastIndexOf("/");
82 return this.filename.substring(lastDelim + 1, this.filename.length());
83 }
84
85 /**
86 * Returns the file's <tt>Directory</tt>.
87 * @return the file's <tt>Directory</tt>
88 */
89 public Directory getDirectory() {
90 return directory;
91 }
92
93 /**
94 * Gets the latest revision of this file.
95 * @return the latest revision of this file
96 */
97 public Revision getLatestRevision() {
98 return (Revision) this.revisions.last();
99 }
100
101 /**
102 * Gets the earliest revision of this file.
103 * @return the earliest revision of this file
104 */
105 public Revision getInitialRevision() {
106 return (Revision) this.revisions.first();
107 }
108
109 /**
110 * Returns the list of {@link Revision}s of this file,
111 * sorted from earliest to most recent.
112 * @return a <tt>SortedSet</tt> of {@link Revision}s
113 */
114 public SortedSet getRevisions() {
115 return this.revisions;
116 }
117
118 /**
119 * Returns the current number of lines for this file. Binary files
120 * and deleted files are assumed to have 0 lines.
121 * @return the current number of lines for this file
122 */
123 public int getCurrentLinesOfCode() {
124 return getLatestRevision().getLines();
125 }
126
127 /**
128 * Returns <code>true</code> if the latest revision of this file was
129 * a deletion.
130 * @return <code>true</code> if this file is deleted
131 */
132 public boolean isDead() {
133 return getLatestRevision().isDead();
134 }
135
136 /**
137 * Returns true, if <code>author</code> worked on this file.
138 * @param author The <code>Author</code> to search for
139 * @return <code>true</code>, if the author is listed in one of
140 * this file's revisions
141 */
142 public boolean hasAuthor(final Author author) {
143 return authors.contains(author);
144 }
145
146 /**
147 * Returns the revision which was replaced by the revision given as
148 * argument. Returns <tt>null</tt> if the given revision is the initial
149 * revision of this file.
150 * @param revision a revision of this file
151 * @return this revision's predecessor
152 */
153 public Revision getPreviousRevision(final Revision revision) {
154 if (!revisions.contains(revision)) {
155 throw new IllegalArgumentException("revision not containted in file");
156 }
157 final SortedSet headSet = revisions.headSet(revision);
158 if (headSet.isEmpty()) {
159 return null;
160 }
161 return (Revision) headSet.last();
162 }
163
164 /**
165 * {@inheritDoc}
166 */
167 public String toString() {
168 return getFilenameWithPath() + " (" + revisions.size() + " revisions)";
169 }
170
171 /**
172 * Compares this file to another one, based on filename.
173 * @see java.lang.Comparable#compareTo(java.lang.Object)
174 */
175 public int compareTo(final Object other) {
176 return filename.compareTo(((VersionedFile) other).filename);
177 }
178
179 /**
180 * Adds an initial revision to the file. An initial revision is either
181 * the first revision of the file, or a re-add after the file was
182 * deleted.
183 * @param revisionNumber the revision number, for example "1.1"
184 * @param author the login from which the change was committed
185 * @param date the time when the change was committed
186 * @param comment the commit message
187 * @param lines the number of lines of the new file
188 */
189 public Revision addInitialRevision(final String revisionNumber, final Author author, final Date date, final String comment, final int lines,
190 final SortedSet symbolicNames) {
191 final Revision result = new Revision(this, revisionNumber, Revision.TYPE_CREATION, author, date, comment, lines, lines, 0, symbolicNames);
192 addRevision(result);
193 return result;
194 }
195
196 /**
197 * Adds a change revision to the file.
198 * @param revisionNumber the revision number, for example "1.1"
199 * @param author the login from which the change was committed
200 * @param date the time when the change was committed
201 * @param comment the commit message
202 * @param lines the number of lines in the file after the change
203 * @param linesDelta the change in the number of lines
204 * @param replacedLines number of lines that were removed and replaced by others
205 */
206 public Revision addChangeRevision(final String revisionNumber, final Author author, final Date date, final String comment, final int lines,
207 final int linesDelta, final int replacedLines, final SortedSet symbolicNames) {
208 final Revision result = new Revision(this, revisionNumber, Revision.TYPE_CHANGE, author, date, comment, lines, linesDelta, replacedLines, symbolicNames);
209 addRevision(result);
210 return result;
211 }
212
213 /**
214 * Adds a deletion revision to the file.
215 * @param revisionNumber the revision number, for example "1.1"
216 * @param author the login from which the change was committed
217 * @param date the time when the change was committed
218 * @param comment the commit message
219 * @param lines the number of lines in the file before it was deleted
220 */
221 public Revision addDeletionRevision(final String revisionNumber, final Author author, final Date date, final String comment, int lines,
222 final SortedSet symbolicNames) {
223 final Revision result = new Revision(this, revisionNumber, Revision.TYPE_DELETION, author, date, comment, 0, -lines, 0, symbolicNames);
224 addRevision(result);
225 return result;
226 }
227
228 /**
229 * Adds a "begin of log" revision to the file. This kind of revision
230 * only marks the beginning of the log timespan if the file was
231 * already present in the repository at this time. It is not an actual
232 * revision committed by an author.
233 * @param date the begin of the log
234 * @param lines the number of lines in the file at that time
235 */
236 public Revision addBeginOfLogRevision(final Date date, final int lines, final SortedSet symbolicNames) {
237 final Revision result = new Revision(this, "0.0", Revision.TYPE_BEGIN_OF_LOG, null, date, null, lines, 0, 0, symbolicNames);
238 addRevision(result);
239 return result;
240 }
241
242 private void addRevision(final Revision revision) {
243 revisions.add(revision);
244 if (revision.getAuthor() != null) {
245 authors.add(revision.getAuthor());
246 }
247 }
248 }