001: /*
002: * Create a graphviz graph based on the classes in the specified java
003: * source files.
004: *
005: * (C) Copyright 2002-2005 Diomidis Spinellis
006: *
007: * Permission to use, copy, and distribute this software and its
008: * documentation for any purpose and without fee is hereby granted,
009: * provided that the above copyright notice appear in all copies and that
010: * both that copyright notice and this permission notice appear in
011: * supporting documentation.
012: *
013: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
014: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
015: * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * $Id: UmlGraph.java,v 1.82 2007/11/29 12:00:48 dds Exp $
018: *
019: */
020:
021: package org.umlgraph.doclet;
022:
023: import java.io.IOException;
024: import java.io.PrintWriter;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: import com.sun.javadoc.ClassDoc;
029: import com.sun.javadoc.Doc;
030: import com.sun.javadoc.LanguageVersion;
031: import com.sun.javadoc.RootDoc;
032:
033: /**
034: * Doclet API implementation
035: * @depend - - - OptionProvider
036: * @depend - - - Options
037: * @depend - - - View
038: * @depend - - - ClassGraph
039: * @depend - - - Version
040: *
041: * @version $Revision: 1.82 $
042: * @author <a href="http://www.spinellis.gr">Diomidis Spinellis</a>
043: */
044: public class UmlGraph {
045:
046: private static final String programName = "UmlGraph";
047: private static final String docletName = "org.umlgraph.doclet.UmlGraph";
048:
049: /** Options used for commenting nodes */
050: private static Options commentOptions;
051:
052: /** Entry point through javadoc */
053: public static boolean start(RootDoc root) throws IOException {
054: Options opt = buildOptions(root);
055: root.printNotice("UMLGraph doclet version " + Version.VERSION
056: + " started");
057:
058: View[] views = buildViews(opt, root, root);
059: if (views == null)
060: return false;
061: if (views.length == 0)
062: buildGraph(root, opt, null);
063: else
064: for (int i = 0; i < views.length; i++)
065: buildGraph(root, views[i], null);
066: return true;
067: }
068:
069: public static void main(String args[]) {
070: PrintWriter err = new PrintWriter(System.err);
071: com.sun.tools.javadoc.Main.execute(programName, err, err, err,
072: docletName, args);
073: }
074:
075: public static Options getCommentOptions() {
076: return commentOptions;
077: }
078:
079: /**
080: * Creates the base Options object.
081: * This contains both the options specified on the command
082: * line and the ones specified in the UMLOptions class, if available.
083: * Also create the globally accessible commentOptions object.
084: */
085: public static Options buildOptions(RootDoc root) {
086: commentOptions = new Options();
087: commentOptions.setOptions(root.options());
088: commentOptions.setOptions(findClass(root, "UMLNoteOptions"));
089: commentOptions.shape = new Shape("note");
090:
091: Options opt = new Options();
092: opt.setOptions(root.options());
093: opt.setOptions(findClass(root, "UMLOptions"));
094: return opt;
095: }
096:
097: /** Return the ClassDoc for the specified class; null if not found. */
098: private static ClassDoc findClass(RootDoc root, String name) {
099: ClassDoc[] classes = root.classes();
100: for (ClassDoc cd : classes)
101: if (cd.name().equals(name))
102: return cd;
103: return null;
104: }
105:
106: /**
107: * Builds and outputs a single graph according to the view overrides
108: */
109: public static void buildGraph(RootDoc root, OptionProvider op,
110: Doc contextDoc) throws IOException {
111: Options opt = op.getGlobalOptions();
112: root.printNotice("Building " + op.getDisplayName());
113: ClassDoc[] classes = root.classes();
114:
115: ClassGraph c = new ClassGraph(root, op, contextDoc);
116: c.prologue();
117: for (int i = 0; i < classes.length; i++)
118: c.printClass(classes[i], true);
119: for (int i = 0; i < classes.length; i++)
120: c.printRelations(classes[i]);
121: if (opt.inferRelationships)
122: c.printInferredRelations(classes);
123: if (opt.inferDependencies)
124: c.printInferredDependencies(classes);
125:
126: c.printExtraClasses(root);
127: c.epilogue();
128: }
129:
130: /**
131: * Builds the views according to the parameters on the command line
132: * @param opt The options
133: * @param srcRootDoc The RootDoc for the source classes
134: * @param viewRootDoc The RootDoc for the view classes (may be
135: * different, or may be the same as the srcRootDoc)
136: */
137: public static View[] buildViews(Options opt, RootDoc srcRootDoc,
138: RootDoc viewRootDoc) {
139: if (opt.viewName != null) {
140: ClassDoc viewClass = viewRootDoc.classNamed(opt.viewName);
141: if (viewClass == null) {
142: System.out
143: .println("View "
144: + opt.viewName
145: + " not found! Exiting without generating any output.");
146: return null;
147: }
148: if (viewClass.tags("view").length == 0) {
149: System.out.println(viewClass + " is not a view!");
150: return null;
151: }
152: if (viewClass.isAbstract()) {
153: System.out
154: .println(viewClass
155: + " is an abstract view, no output will be generated!");
156: return null;
157: }
158: return new View[] { buildView(srcRootDoc, viewClass, opt) };
159: } else if (opt.findViews) {
160: List<View> views = new ArrayList<View>();
161: ClassDoc[] classes = viewRootDoc.classes();
162:
163: // find view classes
164: for (int i = 0; i < classes.length; i++)
165: if (classes[i].tags("view").length > 0
166: && !classes[i].isAbstract())
167: views.add(buildView(srcRootDoc, classes[i], opt));
168:
169: return views.toArray(new View[views.size()]);
170: } else
171: return new View[0];
172: }
173:
174: /**
175: * Builds a view along with its parent views, recursively
176: */
177: private static View buildView(RootDoc root, ClassDoc viewClass,
178: OptionProvider provider) {
179: ClassDoc super Class = viewClass.super class();
180: if (super Class == null || super Class.tags("view").length == 0)
181: return new View(root, viewClass, provider);
182:
183: return new View(root, viewClass, buildView(root, super Class,
184: provider));
185: }
186:
187: /** Option checking */
188: public static int optionLength(String option) {
189: return Options.optionLength(option);
190: }
191:
192: /** Indicate the language version we support */
193: public static LanguageVersion languageVersion() {
194: return LanguageVersion.JAVA_1_5;
195: }
196: }
|