KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jdepend > textui > JDepend


1 package jdepend.textui;
2
3 import java.io.*;
4 import java.util.*;
5 import java.text.NumberFormat JavaDoc;
6
7 import jdepend.framework.JavaClass;
8 import jdepend.framework.JavaPackage;
9 import jdepend.framework.PackageComparator;
10 import jdepend.framework.PackageFilter;
11
12 /**
13  * The <code>JDepend</code> class analyzes directories of Java class files,
14  * generates metrics for each Java package, and reports the metrics in a textual
15  * format.
16  *
17  * @author <b>Mike Clark</b>
18  * @author Clarkware Consulting, Inc.
19  */

20
21 public class JDepend {
22
23     private jdepend.framework.JDepend analyzer;
24
25     private PrintWriter writer;
26
27     protected NumberFormat JavaDoc formatter;
28
29     /**
30      * Constructs a <code>JDepend</code> instance using standard output.
31      */

32     public JDepend() {
33         this(new PrintWriter(System.out));
34     }
35
36     /**
37      * Constructs a <code>JDepend</code> instance with the specified writer.
38      *
39      * @param writer Writer.
40      */

41     public JDepend(PrintWriter writer) {
42         analyzer = new jdepend.framework.JDepend();
43
44         formatter = NumberFormat.getInstance();
45         formatter.setMaximumFractionDigits(2);
46
47         setWriter(writer);
48     }
49
50     /**
51      * Sets the output writer.
52      *
53      * @param writer Output writer.
54      */

55     public void setWriter(PrintWriter writer) {
56         this.writer = writer;
57     }
58
59     protected PrintWriter getWriter() {
60         return writer;
61     }
62
63     /**
64      * Sets the package filter.
65      *
66      * @param filter Package filter.
67      */

68     public void setFilter(PackageFilter filter) {
69         analyzer.setFilter(filter);
70     }
71
72     /**
73      * Sets the comma-separated list of components.
74      */

75     public void setComponents(String JavaDoc components) {
76         analyzer.setComponents(components);
77     }
78     
79     /**
80      * Adds the specified directory name to the collection of directories to be
81      * analyzed.
82      *
83      * @param name Directory name.
84      * @throws IOException If the directory does not exist.
85      */

86     public void addDirectory(String JavaDoc name) throws IOException {
87         analyzer.addDirectory(name);
88     }
89
90     /**
91      * Determines whether inner classes are analyzed.
92      *
93      * @param b <code>true</code> to analyze inner classes; <code>false</code>
94      * otherwise.
95      */

96     public void analyzeInnerClasses(boolean b) {
97         analyzer.analyzeInnerClasses(b);
98     }
99
100     /**
101      * Analyzes the registered directories, generates metrics for each Java
102      * package, and reports the metrics.
103      */

104     public void analyze() {
105
106         printHeader();
107
108         Collection packages = analyzer.analyze();
109
110         ArrayList packageList = new ArrayList(packages);
111
112         Collections.sort(packageList, new PackageComparator(PackageComparator
113                 .byName()));
114
115         printPackages(packageList);
116
117         printCycles(packageList);
118
119         printSummary(packageList);
120
121         printFooter();
122
123         getWriter().flush();
124     }
125
126     protected void printPackages(Collection packages) {
127         printPackagesHeader();
128
129         Iterator i = packages.iterator();
130         while (i.hasNext()) {
131             printPackage((JavaPackage) i.next());
132         }
133
134         printPackagesFooter();
135     }
136
137     protected void printPackage(JavaPackage jPackage) {
138
139         printPackageHeader(jPackage);
140
141         if (jPackage.getClasses().size() == 0) {
142             printNoStats();
143             printPackageFooter(jPackage);
144             return;
145         }
146
147         printStatistics(jPackage);
148
149         printSectionBreak();
150
151         printAbstractClasses(jPackage);
152
153         printSectionBreak();
154
155         printConcreteClasses(jPackage);
156
157         printSectionBreak();
158
159         printEfferents(jPackage);
160
161         printSectionBreak();
162
163         printAfferents(jPackage);
164
165         printPackageFooter(jPackage);
166     }
167
168     protected void printAbstractClasses(JavaPackage jPackage) {
169         printAbstractClassesHeader();
170
171         ArrayList members = new ArrayList(jPackage.getClasses());
172         Collections.sort(members, new JavaClass.ClassComparator());
173         Iterator memberIter = members.iterator();
174         while (memberIter.hasNext()) {
175             JavaClass jClass = (JavaClass) memberIter.next();
176             if (jClass.isAbstract()) {
177                 printClassName(jClass);
178             }
179         }
180
181         printAbstractClassesFooter();
182     }
183
184     protected void printConcreteClasses(JavaPackage jPackage) {
185         printConcreteClassesHeader();
186
187         ArrayList members = new ArrayList(jPackage.getClasses());
188         Collections.sort(members, new JavaClass.ClassComparator());
189         Iterator memberIter = members.iterator();
190         while (memberIter.hasNext()) {
191             JavaClass concrete = (JavaClass) memberIter.next();
192             if (!concrete.isAbstract()) {
193                 printClassName(concrete);
194             }
195         }
196
197         printConcreteClassesFooter();
198     }
199
200     protected void printEfferents(JavaPackage jPackage) {
201         printEfferentsHeader();
202
203         ArrayList efferents = new ArrayList(jPackage.getEfferents());
204         Collections.sort(efferents, new PackageComparator(PackageComparator
205                 .byName()));
206         Iterator efferentIter = efferents.iterator();
207         while (efferentIter.hasNext()) {
208             JavaPackage efferent = (JavaPackage) efferentIter.next();
209             printPackageName(efferent);
210         }
211         if (efferents.size() == 0) {
212             printEfferentsError();
213         }
214
215         printEfferentsFooter();
216     }
217
218     protected void printAfferents(JavaPackage jPackage) {
219         printAfferentsHeader();
220
221         ArrayList afferents = new ArrayList(jPackage.getAfferents());
222         Collections.sort(afferents, new PackageComparator(PackageComparator
223                 .byName()));
224         Iterator afferentIter = afferents.iterator();
225         while (afferentIter.hasNext()) {
226             JavaPackage afferent = (JavaPackage) afferentIter.next();
227             printPackageName(afferent);
228         }
229         if (afferents.size() == 0) {
230             printAfferentsError();
231         }
232
233         printAfferentsFooter();
234     }
235
236     protected void printCycles(Collection packages) {
237         printCyclesHeader();
238
239         Iterator i = packages.iterator();
240         while (i.hasNext()) {
241             printCycle((JavaPackage) i.next());
242         }
243
244         printCyclesFooter();
245     }
246
247     protected void printCycle(JavaPackage jPackage) {
248
249         List list = new ArrayList();
250         jPackage.collectCycle(list);
251
252         if (!jPackage.containsCycle()) {
253             return;
254         }
255
256         JavaPackage cyclePackage = (JavaPackage) list.get(list.size() - 1);
257         String JavaDoc cyclePackageName = cyclePackage.getName();
258
259         int i = 0;
260         Iterator pkgIter = list.iterator();
261         while (pkgIter.hasNext()) {
262             i++;
263
264             JavaPackage pkg = (JavaPackage) pkgIter.next();
265
266             if (i == 1) {
267                 printCycleHeader(pkg);
268             } else {
269                 if (pkg.getName().equals(cyclePackageName)) {
270                     printCycleTarget(pkg);
271                 } else {
272                     printCycleContributor(pkg);
273                 }
274             }
275         }
276
277         printCycleFooter();
278     }
279
280     protected void printHeader() {
281         // do nothing
282
}
283
284     protected void printFooter() {
285         // do nothing
286
}
287
288     protected void printPackagesHeader() {
289         // do nothing
290
}
291
292     protected void printPackagesFooter() {
293         // do nothing
294
}
295
296     protected void printNoStats() {
297         getWriter().println(
298                 "No stats available: package referenced, but not analyzed.");
299     }
300
301     protected void printPackageHeader(JavaPackage jPackage) {
302         getWriter().println(
303                 "\n--------------------------------------------------");
304         getWriter().println("- Package: " + jPackage.getName());
305         getWriter().println(
306                 "--------------------------------------------------");
307     }
308
309     protected void printPackageFooter(JavaPackage jPackage) {
310         // do nothing
311
}
312
313     protected void printStatistics(JavaPackage jPackage) {
314         getWriter().println("\nStats:");
315         getWriter().println(
316                 tab() + "Total Classes: " + jPackage.getClassCount());
317         getWriter()
318                 .println(
319                         tab() + "Concrete Classes: "
320                                 + jPackage.getConcreteClassCount());
321         getWriter()
322                 .println(
323                         tab() + "Abstract Classes: "
324                                 + jPackage.getAbstractClassCount());
325         getWriter().println("");
326         getWriter().println(tab() + "Ca: " + jPackage.afferentCoupling());
327         getWriter().println(tab() + "Ce: " + jPackage.efferentCoupling());
328         getWriter().println("");
329         getWriter().println(
330                 tab() + "A: " + toFormattedString(jPackage.abstractness()));
331         getWriter().println(
332                 tab() + "I: " + toFormattedString(jPackage.instability()));
333         getWriter().println(
334                 tab() + "D: " + toFormattedString(jPackage.distance()));
335     }
336
337     protected void printClassName(JavaClass jClass) {
338         getWriter().println(tab() + jClass.getName());
339     }
340
341     protected void printPackageName(JavaPackage jPackage) {
342         getWriter().println(tab() + jPackage.getName());
343     }
344
345     protected void printAbstractClassesHeader() {
346         getWriter().println("Abstract Classes:");
347     }
348
349     protected void printAbstractClassesFooter() {
350         // do nothing
351
}
352
353     protected void printConcreteClassesHeader() {
354         getWriter().println("Concrete Classes:");
355     }
356
357     protected void printConcreteClassesFooter() {
358         // do nothing
359
}
360
361     protected void printEfferentsHeader() {
362         getWriter().println("Depends Upon:");
363     }
364
365     protected void printEfferentsFooter() {
366         // do nothing
367
}
368
369     protected void printEfferentsError() {
370         getWriter().println(tab() + "Not dependent on any packages.");
371     }
372
373     protected void printAfferentsHeader() {
374         getWriter().println("Used By:");
375     }
376
377     protected void printAfferentsFooter() {
378         // do nothing
379
}
380
381     protected void printAfferentsError() {
382         getWriter().println(tab() + "Not used by any packages.");
383     }
384
385     protected void printCyclesHeader() {
386         printSectionBreak();
387         getWriter().println(
388                 "\n--------------------------------------------------");
389         getWriter().println("- Package Dependency Cycles:");
390         getWriter().println(
391                 "--------------------------------------------------\n");
392     }
393
394     protected void printCyclesFooter() {
395         // do nothing
396
}
397
398     protected void printCycleHeader(JavaPackage jPackage) {
399         getWriter().println(jPackage.getName());
400         getWriter().println(tab() + "|");
401     }
402
403     protected void printCycleTarget(JavaPackage jPackage) {
404         getWriter().println(tab() + "|-> " + jPackage.getName());
405     }
406
407     protected void printCycleContributor(JavaPackage jPackage) {
408         getWriter().println(tab() + "| " + jPackage.getName());
409     }
410
411     protected void printCycleFooter() {
412         printSectionBreak();
413     }
414
415     protected void printSummary(Collection packages) {
416         getWriter().println(
417                 "\n--------------------------------------------------");
418         getWriter().println("- Summary:");
419         getWriter().println(
420                 "--------------------------------------------------\n");
421
422         getWriter()
423                 .println(
424                         "Name, Class Count, Abstract Class Count, Ca, Ce, A, I, D, V:\n");
425
426         Iterator i = packages.iterator();
427         while (i.hasNext()) {
428             JavaPackage jPackage = (JavaPackage) i.next();
429             getWriter().print(jPackage.getName() + ",");
430             getWriter().print(jPackage.getClassCount() + ",");
431             getWriter().print(jPackage.getAbstractClassCount() + ",");
432             getWriter().print(jPackage.afferentCoupling() + ",");
433             getWriter().print(jPackage.efferentCoupling() + ",");
434             getWriter().print(toFormattedString(jPackage.abstractness()) + ",");
435             getWriter().print(toFormattedString(jPackage.instability()) + ",");
436             getWriter().print(toFormattedString(jPackage.distance()) + ",");
437             getWriter().println(jPackage.getVolatility());
438         }
439     }
440
441     protected void printSectionBreak() {
442         getWriter().println("");
443     }
444
445     protected String JavaDoc toFormattedString(float f) {
446         return formatter.format(f);
447     }
448
449     protected String JavaDoc tab() {
450         return " ";
451     }
452
453     protected String JavaDoc tab(int n) {
454         StringBuffer JavaDoc s = new StringBuffer JavaDoc();
455         for (int i = 0; i < n; i++) {
456             s.append(tab());
457         }
458
459         return s.toString();
460     }
461
462     protected void usage(String JavaDoc message) {
463         if (message != null) {
464             System.err.println("\n" + message);
465         }
466         String JavaDoc baseUsage = "\nJDepend ";
467
468         System.err.println("");
469         System.err.println("usage: ");
470         System.err.println(baseUsage + "[-components <components>]" +
471             " [-file <output file>] <directory> " +
472             "[directory2 [directory 3] ...]");
473         System.exit(1);
474     }
475
476     protected void instanceMain(String JavaDoc[] args) {
477
478         if (args.length < 1) {
479             usage("Must specify at least one directory.");
480         }
481
482         int directoryCount = 0;
483
484         for (int i = 0; i < args.length; i++) {
485             if (args[i].startsWith("-")) {
486                 if (args[i].equalsIgnoreCase("-file")) {
487
488                     if (args.length <= i + 1) {
489                         usage("Output file name not specified.");
490                     }
491
492                     try {
493                         setWriter(new PrintWriter(new OutputStreamWriter(
494                                 new FileOutputStream(args[++i]), "UTF8")));
495                     } catch (IOException ioe) {
496                         usage(ioe.getMessage());
497                     }
498                     
499                 } else if (args[i].equalsIgnoreCase("-components")) {
500                     if (args.length <= i + 1) {
501                         usage("Components not specified.");
502                     }
503                     setComponents(args[++i]);
504                 } else {
505                     usage("Invalid argument: " + args[i]);
506                 }
507             } else {
508                 try {
509                     addDirectory(args[i]);
510                     directoryCount++;
511                 } catch (IOException ioe) {
512                     usage("Directory does not exist: " + args[i]);
513                 }
514             }
515         }
516
517         if (directoryCount == 0) {
518             usage("Must specify at least one directory.");
519         }
520
521         analyze();
522     }
523
524     public static void main(String JavaDoc args[]) {
525         new JDepend().instanceMain(args);
526     }
527 }
528
Popular Tags