1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package net.sf.statcvs.model;
21
22 import java.util.Iterator;
23 import java.util.SortedSet;
24 import java.util.TreeSet;
25
26 /**
27 * Represents a directory in the {@link Repository Repository}, a
28 * container for {@link VersionedFile}s and sub<tt>Directory</tt>s.
29 * A new root directory is created by {@link #createRoot}.
30 * The {@link #createSubdirectory} method creates new subdirectories.
31 *
32 * TODO: Rename getCurrentLOC to getCurrentLines or getCurrentLineCount
33 *
34 * @author Richard Cyganiak <richard@cyganiak.de>
35 * @version $Id: Directory.java,v 1.11 2008/04/02 11:22:16 benoitx Exp $
36 */
37 public abstract class Directory implements Comparable {
38 private final SortedSet files = new TreeSet();
39 private final SortedSet directories = new TreeSet();
40
41 /**
42 * Factory method for creating a new root directory.
43 * @return a new root directory
44 */
45 public static Directory createRoot() {
46 return new DirectoryRoot();
47 }
48
49 /**
50 * Factory method for creating a new subdirectory.
51 * @param name the subdirectory's name
52 * @return the subdirectory instance
53 */
54 public Directory createSubdirectory(final String name) {
55 final Directory result = new DirectoryImpl(this, name);
56 directories.add(result);
57 return result;
58 }
59
60 /**
61 * Returns the directory's name without full path or any slashes,
62 * for example "src".
63 * @return the directory's name
64 */
65 public abstract String getName();
66
67 /**
68 * Returns the directory's full path with trailing slash,
69 * for example "src/net/sf/statcvs/".
70 * @return the directory's path
71 */
72 public abstract String getPath();
73
74 /**
75 * Returns the directory's parent directory or <tt>null</tt> if it is the root
76 * @return the directory's parent.
77 */
78 public abstract Directory getParent();
79
80 /**
81 * Returns <tt>true</tt> if this is the root of the directory tree.
82 * @return <tt>true</tt> if this is the root of the directory tree
83 */
84 public abstract boolean isRoot();
85
86 /**
87 * Returns the level of this directory in the direcotry tree.
88 * The root has level 0, its subdirectories have level 1, and so forth.
89 * @return the level of this directory in the directory tree
90 */
91 public abstract int getDepth();
92
93 /**
94 * Returns all {@link VersionedFile} objects in this directory, ordered
95 * by filename. Files in subdirectories are not included.
96 * @return the files in this directory
97 */
98 public SortedSet getFiles() {
99 return files;
100 }
101
102 /**
103 * Returns all {@link Revision}s to files in
104 * this directory, in order from oldest to most recent.
105 * @return list of <tt>Revision</tt>s for this directory
106 */
107 public SortedSet getRevisions() {
108 final SortedSet result = new TreeSet();
109 final Iterator iterator = files.iterator();
110 while (iterator.hasNext()) {
111 final VersionedFile file = (VersionedFile) iterator.next();
112 result.addAll(file.getRevisions());
113 }
114 return result;
115 }
116
117 /**
118 * Returns a <tt>SortedSet</tt> of all immediate subdirectories,
119 * ordered by name.
120 * @return <tt>SortedSet</tt> of {@link Directory} objects
121 */
122 public SortedSet getSubdirectories() {
123 return directories;
124 }
125
126 /**
127 * Returns a list of all subdirectories, including their subdirectories
128 * and this directory itself. The list is preordered, beginning with this
129 * directory itself.
130 * @return <tt>SortedSet</tt> of {@link Directory} objects
131 */
132 public SortedSet getSubdirectoriesRecursive() {
133 final SortedSet result = new TreeSet();
134 result.add(this);
135 final Iterator it = directories.iterator();
136 while (it.hasNext()) {
137 final Directory dir = (Directory) it.next();
138 result.addAll(dir.getSubdirectoriesRecursive());
139 }
140 return result;
141 }
142
143 /**
144 * Returns the number of lines in this directory. The returned number
145 * will be for the current revisions of all files.
146 * @return lines in this directory
147 */
148 public int getCurrentLOC() {
149 int result = 0;
150 final Iterator it = files.iterator();
151 while (it.hasNext()) {
152 final VersionedFile file = (VersionedFile) it.next();
153 result += file.getCurrentLinesOfCode();
154 }
155 return result;
156 }
157
158 /**
159 * Returns the number of files in this directory. Deleted files are not
160 * counted.
161 * @return number of files in this directory
162 */
163 public int getCurrentFileCount() {
164 int result = 0;
165 final Iterator it = files.iterator();
166 while (it.hasNext()) {
167 final VersionedFile file = (VersionedFile) it.next();
168 if (!file.isDead()) {
169 result++;
170 }
171 }
172 return result;
173 }
174
175 /**
176 * Returns <code>true</code> if all files in this directory and its
177 * subdirectories are deleted, or if it doesn't have any files and
178 * subdirectories at all.
179 * @return <code>true</code> if the directory is currently empty
180 */
181 public boolean isEmpty() {
182 Iterator it = files.iterator();
183 while (it.hasNext()) {
184 final VersionedFile file = (VersionedFile) it.next();
185 if (!file.isDead()) {
186 return false;
187 }
188 }
189 it = directories.iterator();
190 while (it.hasNext()) {
191 final Directory subdir = (Directory) it.next();
192 if (!subdir.isEmpty()) {
193 return false;
194 }
195 }
196 return true;
197 }
198
199 /**
200 * Compares this directory to another one, based on their full names.
201 * @see java.lang.Comparable#compareTo(java.lang.Object)
202 */
203 public int compareTo(final Object o) {
204 return getPath().compareTo(((Directory) o).getPath());
205 }
206
207 /**
208 * Adds a file to this directory.
209 * @param file a file in this directory
210 */
211 void addFile(final VersionedFile file) {
212 files.add(file);
213 }
214 }