1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package net.sf.statcvs.input;
24
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Date;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Properties;
34 import java.util.Set;
35 import java.util.SortedSet;
36 import java.util.TreeSet;
37 import java.util.logging.Logger;
38 import java.util.regex.Pattern;
39
40 import net.sf.statcvs.model.Author;
41 import net.sf.statcvs.model.Directory;
42 import net.sf.statcvs.model.Repository;
43 import net.sf.statcvs.model.SymbolicName;
44 import net.sf.statcvs.model.VersionedFile;
45 import net.sf.statcvs.output.ConfigurationOptions;
46 import net.sf.statcvs.util.FilePatternMatcher;
47 import net.sf.statcvs.util.FileUtils;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class Builder implements CvsLogBuilder {
63 private static Logger logger = Logger.getLogger(Builder.class.getName());
64
65 private final RepositoryFileManager repositoryFileManager;
66 private final FilePatternMatcher includePattern;
67 private final FilePatternMatcher excludePattern;
68 private final Pattern tagsPattern;
69
70 private final Map authors = new HashMap();
71 private final Map directories = new HashMap();
72 private final Map symbolicNames = new HashMap();
73
74 private final List fileBuilders = new ArrayList();
75 private final Set atticFileNames = new HashSet();
76
77 private FileBuilder currentFileBuilder = null;
78 private Date startDate = null;
79 private String projectName = null;
80
81 private int countRejectedByExclude = 0;
82 private int countAcceptedByExclude = 0;
83 private int countRejectedByInclude = 0;
84 private int countAcceptedByInclude = 0;
85 private boolean flagOutOfSync = false;
86 private boolean flagHasLocalCVSMetadata = false;
87 private int countFoundLocalFiles = 0;
88 private int countNotFoundLocalFiles = 0;
89
90
91
92
93
94
95
96
97
98
99
100
101 public Builder(final RepositoryFileManager repositoryFileManager, final FilePatternMatcher includePattern, final FilePatternMatcher excludePattern,
102 final Pattern tagsPattern) {
103 this.repositoryFileManager = repositoryFileManager;
104 this.includePattern = includePattern;
105 this.excludePattern = excludePattern;
106 this.tagsPattern = tagsPattern;
107 directories.put("", Directory.createRoot());
108 }
109
110
111
112
113
114
115 public void buildModule(final String moduleName) {
116 this.projectName = moduleName;
117 }
118
119
120
121
122
123
124
125
126
127 public void buildFile(final String filename, final boolean isBinary, final boolean isInAttic, final Map revBySymnames) {
128 if (currentFileBuilder != null) {
129 fileBuilders.add(currentFileBuilder);
130 }
131 currentFileBuilder = new FileBuilder(this, filename, isBinary, revBySymnames);
132 if (isInAttic) {
133 atticFileNames.add(filename);
134 }
135 }
136
137
138
139
140
141
142
143 public void buildRevision(final RevisionData data) {
144 currentFileBuilder.addRevisionData(data);
145 if (startDate == null || startDate.compareTo(data.getDate()) > 0) {
146 startDate = data.getDate();
147 }
148 }
149
150
151
152
153
154
155 public Repository createCvsContent() {
156 if (currentFileBuilder != null) {
157 fileBuilders.add(currentFileBuilder);
158 currentFileBuilder = null;
159 }
160
161 final Repository result = new Repository();
162 final Iterator it = fileBuilders.iterator();
163 while (it.hasNext()) {
164 final FileBuilder fileBuilder = (FileBuilder) it.next();
165 final VersionedFile file = fileBuilder.createFile(startDate);
166 if (file == null) {
167 continue;
168 }
169 if (fileBuilder.hasUnexpectedLocalRevision()) {
170 this.flagOutOfSync = true;
171 }
172 if (fileBuilder.hasLocalCVSMetadata()) {
173 this.flagHasLocalCVSMetadata = true;
174 }
175 if (fileBuilder.hasLocalFileNotFound()) {
176 this.countNotFoundLocalFiles++;
177 this.flagOutOfSync = true;
178 } else if (file.getCurrentLinesOfCode() > 0) {
179 this.countFoundLocalFiles++;
180 }
181 result.addFile(file);
182 logger.finer("adding " + file.getFilenameWithPath() + " (" + file.getRevisions().size() + " revisions)");
183 }
184
185
186 final SortedSet revisions = result.getRevisions();
187 final List commits = new CommitListBuilder(revisions).createCommitList();
188 result.setCommits(commits);
189 result.setSymbolicNames(getMatchingSymbolicNames());
190 return result;
191 }
192
193 public String getProjectName() {
194 return projectName;
195 }
196
197
198
199
200
201 public Set getAtticFileNames() {
202 return atticFileNames;
203 }
204
205
206
207
208 public boolean allRejectedByExcludePattern() {
209 return this.countRejectedByExclude > 0 && this.countAcceptedByExclude == 0;
210 }
211
212
213
214
215 public boolean allRejectedByIncludePattern() {
216 return this.countRejectedByInclude > 0 && this.countAcceptedByInclude == 0;
217 }
218
219
220
221
222
223
224
225 public boolean isLogAndLocalFilesOutOfSync() {
226 return this.flagHasLocalCVSMetadata && this.flagOutOfSync;
227 }
228
229
230
231
232
233
234 public boolean isLocalFilesNotFound() {
235 return this.countNotFoundLocalFiles > this.countFoundLocalFiles;
236 }
237
238
239
240
241
242
243
244 public boolean hasLocalCVSMetadata() {
245 return this.flagHasLocalCVSMetadata;
246 }
247
248
249
250
251
252
253
254 public Author getAuthor(final String name) {
255 if (this.authors.containsKey(name.toLowerCase())) {
256 return (Author) this.authors.get(name.toLowerCase());
257 }
258 final Properties p = ConfigurationOptions.getConfigProperties();
259 final Author newAuthor = new Author(name);
260 this.authors.put(name.toLowerCase(), newAuthor);
261 if (p != null) {
262 newAuthor.setRealName(p.getProperty("user." + name.toLowerCase() + ".realName"));
263 newAuthor.setHomePageUrl(p.getProperty("user." + name.toLowerCase() + ".url"));
264 newAuthor.setImageUrl(p.getProperty("user." + name.toLowerCase() + ".image"));
265 newAuthor.setEmail(p.getProperty("user." + name.toLowerCase() + ".email"));
266 }
267 return newAuthor;
268 }
269
270
271
272
273
274
275
276 public Directory getDirectory(final String filename) {
277 final int lastSlash = filename.lastIndexOf('/');
278 if (lastSlash == -1) {
279 return getDirectoryForPath("");
280 }
281 return getDirectoryForPath(filename.substring(0, lastSlash + 1));
282 }
283
284
285
286
287
288
289
290
291 public SymbolicName getSymbolicName(final String name) {
292 SymbolicName sym = (SymbolicName) symbolicNames.get(name);
293
294 if (sym != null) {
295 return sym;
296 } else {
297 sym = new SymbolicName(name);
298 symbolicNames.put(name, sym);
299
300 return sym;
301 }
302 }
303
304 public int getLOC(final String filename) throws NoLineCountException {
305 if (repositoryFileManager == null) {
306 throw new NoLineCountException("no RepositoryFileManager");
307 }
308 return repositoryFileManager.getLinesOfCode(filename);
309 }
310
311
312
313
314 public String getRevision(final String filename) throws IOException {
315 if (repositoryFileManager == null) {
316 throw new IOException("no RepositoryFileManager");
317 }
318 return repositoryFileManager.getRevision(filename);
319 }
320
321
322
323
324
325
326
327
328
329
330
331 public boolean matchesPatterns(final String filename) {
332 if (excludePattern != null) {
333 if (excludePattern.matches(filename)) {
334 this.countRejectedByExclude++;
335 return false;
336 } else {
337 this.countAcceptedByExclude++;
338 }
339 }
340 if (includePattern != null) {
341 if (includePattern.matches(filename)) {
342 this.countAcceptedByInclude++;
343 } else {
344 this.countRejectedByInclude++;
345 return false;
346 }
347 }
348 return true;
349 }
350
351
352
353
354
355 private Directory getDirectoryForPath(final String path) {
356 if (directories.containsKey(path)) {
357 return (Directory) directories.get(path);
358 }
359 final Directory parent = getDirectoryForPath(FileUtils.getParentDirectoryPath(path));
360 final Directory newDirectory = parent.createSubdirectory(FileUtils.getDirectoryName(path));
361 directories.put(path, newDirectory);
362 return newDirectory;
363 }
364
365 private SortedSet getMatchingSymbolicNames() {
366 final TreeSet result = new TreeSet();
367 if (this.tagsPattern == null) {
368 return result;
369 }
370 for (final Iterator it = this.symbolicNames.values().iterator(); it.hasNext();) {
371 final SymbolicName sn = (SymbolicName) it.next();
372 if (sn.getDate() != null && this.tagsPattern.matcher(sn.getName()).matches()) {
373 result.add(sn);
374 }
375 }
376 return result;
377 }
378 }