mirror of https://github.com/dspinellis/UMLGraph
Files repocopied to org/umlgraph
This commit is contained in:
parent
6e5dabef48
commit
15b5b303bf
|
|
@ -1 +0,0 @@
|
|||
Version.java
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Create a graphviz graph based on the classes in the specified java
|
||||
* source files.
|
||||
*
|
||||
* (C) Copyright 2002-2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class's dot-comaptible alias name (for fully qualified class names)
|
||||
* and printed information
|
||||
* @version $Revision$
|
||||
* @author <a href="http://www.spinellis.gr">Diomidis Spinellis</a>
|
||||
*/
|
||||
class ClassInfo {
|
||||
private static int classNumber;
|
||||
/** Alias name for the class */
|
||||
String name;
|
||||
/** True if the class class node has been printed */
|
||||
boolean nodePrinted;
|
||||
/** True if the class class node is hidden */
|
||||
boolean hidden;
|
||||
/**
|
||||
* The list of classes that share a relation with this one. Contains
|
||||
* all the classes linked with a bi-directional relation , and the ones
|
||||
* referred by a directed relation
|
||||
*/
|
||||
Map<String, RelationPattern> relatedClasses = new HashMap<String, RelationPattern>();
|
||||
|
||||
ClassInfo(boolean p, boolean h) {
|
||||
nodePrinted = p;
|
||||
hidden = h;
|
||||
name = "c" + (new Integer(classNumber)).toString();
|
||||
classNumber++;
|
||||
}
|
||||
|
||||
public void addRelation(String dest, RelationType rt, RelationDirection d) {
|
||||
RelationPattern ri = relatedClasses.get(dest);
|
||||
if(ri == null) {
|
||||
ri = new RelationPattern(RelationDirection.NONE);
|
||||
relatedClasses.put(dest, ri);
|
||||
}
|
||||
ri.addRelation(rt, d);
|
||||
}
|
||||
|
||||
public RelationPattern getRelation(String dest) {
|
||||
return relatedClasses.get(dest);
|
||||
}
|
||||
|
||||
/** Start numbering from zero. */
|
||||
public static void reset() {
|
||||
classNumber = 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
|
||||
/**
|
||||
* A ClassMatcher is used to check if a class definition matches a
|
||||
* specific condition. The nature of the condition is dependent on
|
||||
* the kind of matcher
|
||||
* @author wolf
|
||||
*/
|
||||
public interface ClassMatcher {
|
||||
/**
|
||||
* Returns the options for the specified class.
|
||||
*/
|
||||
public boolean matches(ClassDoc cd);
|
||||
|
||||
/**
|
||||
* Returns the options for the specified class.
|
||||
*/
|
||||
public boolean matches(String name);
|
||||
}
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
/*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
|
||||
/**
|
||||
* Matches classes that are directly connected to one of the classes matched by
|
||||
* the regual expression specified. The context center is computed by regex
|
||||
* lookup. Depending on the specified Options, inferred relations and
|
||||
* dependencies will be used as well.
|
||||
* <p>
|
||||
* This class needs to perform quite a bit of computations in order to gather
|
||||
* the network of class releationships, so you are allowed to reuse it should
|
||||
* you
|
||||
* @author wolf
|
||||
*
|
||||
* @depend - - - DevNullWriter
|
||||
*/
|
||||
public class ContextMatcher implements ClassMatcher {
|
||||
ClassGraphHack cg;
|
||||
Pattern pattern;
|
||||
List<ClassDoc> matched;
|
||||
Set<String> visited = new HashSet<String>();
|
||||
Options opt;
|
||||
RootDoc root;
|
||||
boolean keepParentHide;
|
||||
|
||||
/**
|
||||
* Builds the context matcher
|
||||
* @param root The root doc returned by JavaDoc
|
||||
* @param pattern The pattern that will match the "center" of this
|
||||
* context
|
||||
* @param opt The options will be used to decide on inference
|
||||
* @param keepParentHide If true, parent option hide patterns will be
|
||||
* preserved, so that classes hidden by the options won't
|
||||
* be shown in the context
|
||||
* @param fullContext If true, all the classes related to the context
|
||||
* center will be included, otherwise it will match only
|
||||
* the classes referred with an outgoing relation from
|
||||
* the context center
|
||||
* @throws IOException
|
||||
*/
|
||||
public ContextMatcher(RootDoc root, Pattern pattern, Options options, boolean keepParentHide) throws IOException {
|
||||
this.pattern = pattern;
|
||||
this.root = root;
|
||||
this.keepParentHide = keepParentHide;
|
||||
opt = (Options) options.clone();
|
||||
opt.setOption(new String[] { "-!hide" });
|
||||
opt.setOption(new String[] { "-!attributes" });
|
||||
opt.setOption(new String[] { "-!operations" });
|
||||
this.cg = new ClassGraphHack(root, opt);
|
||||
|
||||
setContextCenter(pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to setup a different pattern for this context matcher.
|
||||
* <p>
|
||||
* This can be used to speed up subsequent matching with the same global
|
||||
* options, since the class network informations will be reused.
|
||||
* @param pattern
|
||||
*/
|
||||
public void setContextCenter(Pattern pattern) {
|
||||
// build up the classgraph printing the relations for all of the
|
||||
// classes that make up the "center" of this context
|
||||
this.pattern = pattern;
|
||||
matched = new ArrayList<ClassDoc>();
|
||||
for (ClassDoc cd : root.classes()) {
|
||||
if (pattern.matcher(cd.toString()).matches()) {
|
||||
matched.add(cd);
|
||||
addToGraph(cd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified class to the internal class graph along with its
|
||||
* relations and depencies, eventually inferring them, according to the
|
||||
* Options specified for this matcher
|
||||
* @param cd
|
||||
*/
|
||||
private void addToGraph(ClassDoc cd) {
|
||||
// avoid adding twice the same class, but don't rely on cg.getClassInfo
|
||||
// since there
|
||||
// are other ways to add a classInfor than printing the class
|
||||
if (visited.contains(cd.toString()))
|
||||
return;
|
||||
|
||||
visited.add(cd.toString());
|
||||
cg.printClass(cd, false);
|
||||
cg.printRelations(cd);
|
||||
if (opt.inferRelationships) {
|
||||
cg.printInferredRelations(cd);
|
||||
}
|
||||
if (opt.inferDependencies) {
|
||||
cg.printInferredDependencies(cd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see gr.spinellis.umlgraph.doclet.ClassMatcher#matches(com.sun.javadoc.ClassDoc)
|
||||
*/
|
||||
public boolean matches(ClassDoc cd) {
|
||||
if (keepParentHide && opt.matchesHideExpression(cd.toString()))
|
||||
return false;
|
||||
|
||||
// if the class is matched, it's in by default.
|
||||
if (matched.contains(cd))
|
||||
return true;
|
||||
|
||||
// otherwise, add the class to the graph and see if it's associated
|
||||
// with any of the matched classes using the classgraph hack
|
||||
addToGraph(cd);
|
||||
return matches(cd.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see gr.spinellis.umlgraph.doclet.ClassMatcher#matches(java.lang.String)
|
||||
*/
|
||||
public boolean matches(String name) {
|
||||
if (pattern.matcher(name).matches())
|
||||
return true;
|
||||
|
||||
for (ClassDoc mcd : matched) {
|
||||
String mcName = mcd.toString();
|
||||
ClassInfo ciMatched = cg.getClassInfo(mcName);
|
||||
RelationPattern rp = ciMatched.getRelation(name);
|
||||
if (ciMatched != null && rp != null && opt.contextRelationPattern.matchesOne(rp))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A quick hack to compute class dependencies reusing ClassGraph but
|
||||
* without generating output. Will be removed once the ClassGraph class
|
||||
* will be split into two classes for graph computation and output
|
||||
* generation.
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
private static class ClassGraphHack extends ClassGraph {
|
||||
|
||||
public ClassGraphHack(RootDoc root, OptionProvider optionProvider) throws IOException {
|
||||
super(root, optionProvider, null);
|
||||
prologue();
|
||||
}
|
||||
|
||||
public void prologue() throws IOException {
|
||||
w = new PrintWriter(new DevNullWriter());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple dev/null imitation
|
||||
* @author wolf
|
||||
*/
|
||||
private static class DevNullWriter extends Writer {
|
||||
|
||||
public void write(char[] cbuf, int off, int len) throws IOException {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
|
||||
/**
|
||||
* A view designed for UMLDoc, filters out everything that it's not directly
|
||||
* connected to the center class of the context.
|
||||
* <p>
|
||||
* As such, can be viewed as a simplified version of a {@linkplain View} using a
|
||||
* single {@linkplain ContextMatcher}, but provides some extra configuration
|
||||
* such as context highlighting and output path configuration (and it is
|
||||
* specified in code rather than in javadoc comments).
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public class ContextView implements OptionProvider {
|
||||
|
||||
private ClassDoc cd;
|
||||
private ContextMatcher matcher;
|
||||
private Options globalOptions;
|
||||
private Options myGlobalOptions;
|
||||
private Options hideOptions;
|
||||
private Options centerOptions;
|
||||
private Options packageOptions;
|
||||
private static final String[] HIDE_OPTIONS = new String[] { "-hide" };
|
||||
|
||||
public ContextView(String outputFolder, ClassDoc cd, RootDoc root, Options parent)
|
||||
throws IOException {
|
||||
this.cd = cd;
|
||||
String outputPath = cd.containingPackage().name().replace('.', '/') + "/" + cd.name()
|
||||
+ ".dot";
|
||||
|
||||
// setup options statically, so that we won't need to change them so
|
||||
// often
|
||||
this.globalOptions = parent.getGlobalOptions();
|
||||
|
||||
this.packageOptions = parent.getGlobalOptions();
|
||||
this.packageOptions.showQualified = false;
|
||||
|
||||
this.myGlobalOptions = parent.getGlobalOptions();
|
||||
this.myGlobalOptions.setOption(new String[] { "-output", outputPath });
|
||||
this.myGlobalOptions.setOption(HIDE_OPTIONS);
|
||||
|
||||
this.hideOptions = parent.getGlobalOptions();
|
||||
this.hideOptions.setOption(HIDE_OPTIONS);
|
||||
|
||||
this.centerOptions = parent.getGlobalOptions();
|
||||
this.centerOptions.nodeFillColor = "lemonChiffon";
|
||||
this.centerOptions.showQualified = false;
|
||||
|
||||
this.matcher = new ContextMatcher(root, Pattern.compile(cd.qualifiedName()),
|
||||
myGlobalOptions, true);
|
||||
|
||||
}
|
||||
|
||||
public void setContextCenter(ClassDoc contextCenter) {
|
||||
this.cd = contextCenter;
|
||||
String outputPath = cd.containingPackage().name().replace('.', '/') + "/" + cd.name()
|
||||
+ ".dot";
|
||||
this.myGlobalOptions.setOption(new String[] { "-output", outputPath });
|
||||
matcher.setContextCenter(Pattern.compile(cd.toString()));
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Context view for class " + cd;
|
||||
}
|
||||
|
||||
public Options getGlobalOptions() {
|
||||
return myGlobalOptions;
|
||||
}
|
||||
|
||||
public Options getOptionsFor(ClassDoc cd) {
|
||||
if (globalOptions.matchesHideExpression(cd.toString()) || !matcher.matches(cd)) {
|
||||
return hideOptions;
|
||||
} else if (cd.equals(this.cd)) {
|
||||
return centerOptions;
|
||||
} else if(cd.containingPackage().equals(this.cd.containingPackage())){
|
||||
return packageOptions;
|
||||
} else {
|
||||
return globalOptions;
|
||||
}
|
||||
}
|
||||
|
||||
public Options getOptionsFor(String name) {
|
||||
if (!matcher.matches(name))
|
||||
return hideOptions;
|
||||
else if (name.equals(cd.name()))
|
||||
return centerOptions;
|
||||
else
|
||||
return globalOptions;
|
||||
}
|
||||
|
||||
public void overrideForClass(Options opt, ClassDoc cd) {
|
||||
if (opt.matchesHideExpression(cd.toString()) || !matcher.matches(cd))
|
||||
opt.setOption(HIDE_OPTIONS);
|
||||
if (cd.equals(this.cd))
|
||||
opt.nodeFillColor = "lemonChiffon";
|
||||
}
|
||||
|
||||
public void overrideForClass(Options opt, String className) {
|
||||
if (!matcher.matches(className))
|
||||
opt.setOption(HIDE_OPTIONS);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
|
||||
/**
|
||||
* Matches every class that implements (directly or indirectly) an
|
||||
* interfaces matched by regular expression provided.
|
||||
*/
|
||||
public class InterfaceMatcher implements ClassMatcher {
|
||||
|
||||
protected RootDoc root;
|
||||
protected Pattern pattern;
|
||||
|
||||
public InterfaceMatcher(RootDoc root, Pattern pattern) {
|
||||
this.root = root;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public boolean matches(ClassDoc cd) {
|
||||
// if it's the interface we're looking for, match
|
||||
if(cd.isInterface() && pattern.matcher(cd.toString()).matches())
|
||||
return true;
|
||||
|
||||
// for each interface, recurse, since classes and interfaces
|
||||
// are treated the same in the doclet API
|
||||
for (ClassDoc iface : cd.interfaces()) {
|
||||
if(matches(iface))
|
||||
return true;
|
||||
}
|
||||
|
||||
// recurse on supeclass, if available
|
||||
if(cd.superclass() != null)
|
||||
return matches(cd.superclass());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean matches(String name) {
|
||||
ClassDoc cd = root.classNamed(name);
|
||||
if(cd == null)
|
||||
return false;
|
||||
return matches(cd);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2002-2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
|
||||
/**
|
||||
* A factory class that builds Options object for general use or for a
|
||||
* specific class
|
||||
*/
|
||||
public interface OptionProvider {
|
||||
/**
|
||||
* Returns the options for the specified class.
|
||||
*/
|
||||
public Options getOptionsFor(ClassDoc cd);
|
||||
|
||||
/**
|
||||
* Returns the options for the specified class.
|
||||
*/
|
||||
public Options getOptionsFor(String name);
|
||||
|
||||
/**
|
||||
* Returns the global options (the class independent definition)
|
||||
*/
|
||||
public Options getGlobalOptions();
|
||||
|
||||
/**
|
||||
* Gets a base Options and applies the overrides for the specified class
|
||||
*/
|
||||
public void overrideForClass(Options opt, ClassDoc cd);
|
||||
|
||||
/**
|
||||
* Gets a base Options and applies the overrides for the specified class
|
||||
*/
|
||||
public void overrideForClass(Options opt, String className);
|
||||
|
||||
/**
|
||||
* Returns user displayable name for this option provider.
|
||||
* <p>Will be used to provide progress feedback on the console
|
||||
*/
|
||||
public String getDisplayName();
|
||||
}
|
||||
|
|
@ -1,699 +0,0 @@
|
|||
/*
|
||||
* Create a graphviz graph based on the classes in the specified java
|
||||
* source files.
|
||||
*
|
||||
* (C) Copyright 2002-2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Vector;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.Tag;
|
||||
|
||||
/**
|
||||
* Represent the program options
|
||||
* @version $Revision$
|
||||
* @author <a href="http://www.spinellis.gr">Diomidis Spinellis</a>
|
||||
*/
|
||||
public class Options implements Cloneable, OptionProvider {
|
||||
// dot's font platform dependence workaround
|
||||
private static String defaultFont;
|
||||
private static String defaultItalicFont;
|
||||
// reused often, especially in UmlGraphDoc, worth creating just once and reusing
|
||||
private static final Pattern allPattern = Pattern.compile(".*");
|
||||
protected static final String DEFAULT_EXTERNAL_APIDOC = "http://java.sun.com/j2se/1.4.2/docs/api/";
|
||||
|
||||
static {
|
||||
// use an appropriate font depending on the current operating system
|
||||
// (on windows graphviz is unable to locate "Helvetica-Oblique"
|
||||
if(System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||
defaultFont = "arial";
|
||||
defaultItalicFont = "ariali";
|
||||
} else {
|
||||
defaultFont = "Helvetica";
|
||||
defaultItalicFont = "Helvetica-Oblique";
|
||||
}
|
||||
}
|
||||
|
||||
// instance fields
|
||||
Vector<Pattern> hidePatterns;
|
||||
boolean showQualified;
|
||||
boolean showAttributes;
|
||||
boolean showEnumerations;
|
||||
boolean showEnumConstants;
|
||||
boolean showOperations;
|
||||
boolean showConstructors;
|
||||
boolean showVisibility;
|
||||
boolean horizontal;
|
||||
boolean showType;
|
||||
String edgeFontName;
|
||||
String edgeFontColor;
|
||||
String edgeColor;
|
||||
double edgeFontSize;
|
||||
String nodeFontName;
|
||||
String nodeFontAbstractName;
|
||||
String nodeFontColor;
|
||||
double nodeFontSize;
|
||||
String nodeFillColor;
|
||||
double nodeFontClassSize;
|
||||
String nodeFontClassName;
|
||||
String nodeFontClassAbstractName;
|
||||
double nodeFontTagSize;
|
||||
String nodeFontTagName;
|
||||
double nodeFontPackageSize;
|
||||
String nodeFontPackageName;
|
||||
String bgColor;
|
||||
public String outputFileName;
|
||||
String outputEncoding;
|
||||
Map<Pattern, String> apiDocMap;
|
||||
String apiDocRoot;
|
||||
boolean postfixPackage;
|
||||
boolean useGuillemot;
|
||||
boolean findViews;
|
||||
String viewName;
|
||||
public String outputDirectory;
|
||||
/** Guillemot left (open) */
|
||||
String guilOpen = "«"; // "\u00ab";
|
||||
/** Guillemot right (close) */
|
||||
String guilClose = "»"; // "\u00bb";
|
||||
boolean inferRelationships;
|
||||
boolean inferDependencies;
|
||||
RelationPattern contextRelationPattern;
|
||||
boolean useImports;
|
||||
Visibility inferDependencyVisibility;
|
||||
boolean inferDepInPackage;
|
||||
RelationType inferRelationshipType;
|
||||
private Vector<Pattern> collPackages;
|
||||
boolean compact;
|
||||
// internal option, used by UMLDoc to generate relative links between classes
|
||||
boolean relativeLinksForSourcePackages;
|
||||
// internal option, used by UMLDoc to force strict matching on the class names
|
||||
// and avoid problems with packages in the template declaration making UmlGraph hide
|
||||
// classes outside of them (for example, class gr.spinellis.Foo<T extends java.io.Serializable>
|
||||
// would have been hidden by the hide pattern "java.*"
|
||||
// TODO: consider making this standard behaviour
|
||||
boolean strictMatching;
|
||||
|
||||
Options() {
|
||||
showQualified = false;
|
||||
showAttributes = false;
|
||||
showEnumConstants = false;
|
||||
showOperations = false;
|
||||
showVisibility = false;
|
||||
showEnumerations = false;
|
||||
showConstructors = false;
|
||||
showType = false;
|
||||
edgeFontName = defaultFont;
|
||||
edgeFontColor = "black";
|
||||
edgeColor = "black";
|
||||
edgeFontSize = 10;
|
||||
nodeFontColor = "black";
|
||||
nodeFontName = defaultFont;
|
||||
nodeFontAbstractName = defaultItalicFont;
|
||||
nodeFontSize = 10;
|
||||
nodeFontClassSize = -1;
|
||||
nodeFontClassName = null;
|
||||
nodeFontClassAbstractName = null;
|
||||
nodeFontTagSize = -1;
|
||||
nodeFontTagName = null;
|
||||
nodeFontPackageSize = -1;
|
||||
nodeFontPackageName = null;
|
||||
nodeFillColor = null;
|
||||
bgColor = null;
|
||||
outputFileName = "graph.dot";
|
||||
outputDirectory= null;
|
||||
outputEncoding = "ISO-8859-1";
|
||||
hidePatterns = new Vector<Pattern>();
|
||||
apiDocMap = new HashMap<Pattern, String>();
|
||||
apiDocRoot = null;
|
||||
postfixPackage = false;
|
||||
useGuillemot = true;
|
||||
findViews = false;
|
||||
viewName = null;
|
||||
contextRelationPattern = new RelationPattern(RelationDirection.BOTH);
|
||||
inferRelationships = false;
|
||||
inferDependencies = false;
|
||||
inferDependencyVisibility = Visibility.PRIVATE;
|
||||
inferDepInPackage = false;
|
||||
useImports = false;
|
||||
inferRelationshipType = RelationType.NAVASSOC;
|
||||
collPackages = new Vector<Pattern>();
|
||||
compact = false;
|
||||
relativeLinksForSourcePackages = false;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
Options clone = null;
|
||||
try {
|
||||
clone = (Options) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// Should not happen
|
||||
}
|
||||
// deep clone the hide and collection patterns
|
||||
clone.hidePatterns = new Vector<Pattern>(hidePatterns);
|
||||
clone.collPackages= new Vector<Pattern>(collPackages);
|
||||
clone.apiDocMap = new HashMap<Pattern, String>(apiDocMap);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/** Most complete output */
|
||||
public void setAll() {
|
||||
showAttributes = true;
|
||||
showEnumerations = true;
|
||||
showEnumConstants = true;
|
||||
showOperations = true;
|
||||
showConstructors = true;
|
||||
showVisibility = true;
|
||||
showType = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of arguments associated with the specified option.
|
||||
* The return value includes the actual option.
|
||||
* Will return 0 if the option is not supported.
|
||||
*/
|
||||
public static int optionLength(String option) {
|
||||
if(option.equals("-qualify") ||
|
||||
option.equals("-horizontal") ||
|
||||
option.equals("-attributes") ||
|
||||
option.equals("-operations") ||
|
||||
option.equals("-constructors") ||
|
||||
option.equals("-visibility") ||
|
||||
option.equals("-types") ||
|
||||
option.equals("-all") ||
|
||||
option.equals("-postfixpackage") ||
|
||||
option.equals("-noguillemot") ||
|
||||
option.equals("-enumconstants") ||
|
||||
option.equals("-enumerations") ||
|
||||
option.equals("-views") ||
|
||||
option.equals("-inferrel") ||
|
||||
option.equals("-useimports") ||
|
||||
option.equals("-inferdep") ||
|
||||
option.equals("-inferdepinpackage") ||
|
||||
option.equals("-compact"))
|
||||
|
||||
return 1;
|
||||
else if(option.equals("-nodefillcolor") ||
|
||||
option.equals("-nodefontcolor") ||
|
||||
option.equals("-nodefontsize") ||
|
||||
option.equals("-nodefontname") ||
|
||||
option.equals("-nodefontabstractname") ||
|
||||
option.equals("-nodefontclasssize") ||
|
||||
option.equals("-nodefontclassname") ||
|
||||
option.equals("-nodefontclassabstractname") ||
|
||||
option.equals("-nodefonttagsize") ||
|
||||
option.equals("-nodefonttagname") ||
|
||||
option.equals("-nodefontpackagesize") ||
|
||||
option.equals("-nodefontpackagename") ||
|
||||
option.equals("-edgefontcolor") ||
|
||||
option.equals("-edgecolor") ||
|
||||
option.equals("-edgefontsize") ||
|
||||
option.equals("-edgefontname") ||
|
||||
option.equals("-output") ||
|
||||
option.equals("-outputencoding") ||
|
||||
option.equals("-bgcolor") ||
|
||||
option.equals("-hide") ||
|
||||
option.equals("-apidocroot") ||
|
||||
option.equals("-apidocmap") ||
|
||||
option.equals("-d") ||
|
||||
option.equals("-view") ||
|
||||
option.equals("-inferreltype") ||
|
||||
option.equals("-inferdepvis") ||
|
||||
option.equals("-collpackages") ||
|
||||
option.equals("-link"))
|
||||
return 2;
|
||||
else if(option.equals("-contextPattern"))
|
||||
return 3;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Set the options based on a single option and its arguments */
|
||||
void setOption(String[] opt) {
|
||||
if(!opt[0].equals("-hide") && optionLength(opt[0]) > opt.length) {
|
||||
System.err.println("Skipping option '" + opt[0] + "', missing argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if(opt[0].equals("-qualify")) {
|
||||
showQualified = true;
|
||||
} else if (opt[0].equals("-!qualify")) {
|
||||
showQualified = false;
|
||||
} else if(opt[0].equals("-horizontal")) {
|
||||
horizontal = true;
|
||||
} else if (opt[0].equals("-!horizontal")) {
|
||||
horizontal = false;
|
||||
} else if(opt[0].equals("-attributes")) {
|
||||
showAttributes = true;
|
||||
} else if (opt[0].equals("-!attributes")) {
|
||||
showAttributes = false;
|
||||
} else if(opt[0].equals("-enumconstants")) {
|
||||
showEnumConstants = true;
|
||||
} else if (opt[0].equals("-!enumconstants")) {
|
||||
showEnumConstants = false;
|
||||
} else if(opt[0].equals("-operations")) {
|
||||
showOperations = true;
|
||||
} else if (opt[0].equals("-!operations")) {
|
||||
showOperations = false;
|
||||
} else if(opt[0].equals("-enumerations")) {
|
||||
showEnumerations = true;
|
||||
} else if (opt[0].equals("-!enumerations")) {
|
||||
showEnumerations = false;
|
||||
} else if(opt[0].equals("-constructors")) {
|
||||
showConstructors = true;
|
||||
} else if (opt[0].equals("-!constructors")) {
|
||||
showConstructors = false;
|
||||
} else if(opt[0].equals("-visibility")) {
|
||||
showVisibility = true;
|
||||
} else if (opt[0].equals("-!visibility")) {
|
||||
showVisibility = false;
|
||||
} else if(opt[0].equals("-types")) {
|
||||
showType = true;
|
||||
} else if (opt[0].equals("-!types")) {
|
||||
showType = false;
|
||||
} else if(opt[0].equals("-all")) {
|
||||
setAll();
|
||||
} else if(opt[0].equals("-bgcolor")) {
|
||||
bgColor = opt[1];
|
||||
} else if (opt[0].equals("-!bgcolor")) {
|
||||
bgColor = null;
|
||||
} else if(opt[0].equals("-edgecolor")) {
|
||||
edgeColor = opt[1];
|
||||
} else if (opt[0].equals("-!edgecolor")) {
|
||||
edgeColor = "black";
|
||||
} else if(opt[0].equals("-edgefontcolor")) {
|
||||
edgeFontColor = opt[1];
|
||||
} else if (opt[0].equals("-!edgefontcolor")) {
|
||||
edgeFontColor = "black";
|
||||
} else if(opt[0].equals("-edgefontname")) {
|
||||
edgeFontName = opt[1];
|
||||
} else if (opt[0].equals("-!edgefontname")) {
|
||||
edgeFontName = defaultFont;
|
||||
} else if(opt[0].equals("-edgefontsize")) {
|
||||
edgeFontSize = Integer.parseInt(opt[1]);
|
||||
} else if (opt[0].equals("-!edgefontsize")) {
|
||||
edgeFontSize = 10;
|
||||
} else if(opt[0].equals("-nodefontcolor")) {
|
||||
nodeFontColor = opt[1];
|
||||
} else if (opt[0].equals("-!nodefontcolor")) {
|
||||
nodeFontColor = "black";
|
||||
} else if(opt[0].equals("-nodefontname")) {
|
||||
nodeFontName = opt[1];
|
||||
} else if (opt[0].equals("-!nodefontname")) {
|
||||
nodeFontName = defaultFont;
|
||||
} else if(opt[0].equals("-nodefontabstractname")) {
|
||||
nodeFontAbstractName = opt[1];
|
||||
} else if (opt[0].equals("-!nodefontabstractname")) {
|
||||
nodeFontAbstractName = defaultItalicFont;
|
||||
} else if(opt[0].equals("-nodefontsize")) {
|
||||
nodeFontSize = Integer.parseInt(opt[1]);
|
||||
} else if (opt[0].equals("-!nodefontsize")) {
|
||||
nodeFontSize = 10;
|
||||
} else if(opt[0].equals("-nodefontclassname")) {
|
||||
nodeFontClassName = opt[1];
|
||||
} else if (opt[0].equals("-!nodefontclassname")) {
|
||||
nodeFontClassName = null;
|
||||
} else if(opt[0].equals("-nodefontclassabstractname")) {
|
||||
nodeFontClassAbstractName = opt[1];
|
||||
} else if (opt[0].equals("-!nodefontclassabstractname")) {
|
||||
nodeFontClassAbstractName = null;
|
||||
} else if(opt[0].equals("-nodefontclasssize")) {
|
||||
nodeFontClassSize = Integer.parseInt(opt[1]);
|
||||
} else if (opt[0].equals("-!nodefontclasssize")) {
|
||||
nodeFontClassSize = -1;
|
||||
} else if(opt[0].equals("-nodefonttagname")) {
|
||||
nodeFontTagName = opt[1];
|
||||
} else if (opt[0].equals("-!nodefonttagname")) {
|
||||
nodeFontTagName = null;
|
||||
} else if(opt[0].equals("-nodefonttagsize")) {
|
||||
nodeFontTagSize = Integer.parseInt(opt[1]);
|
||||
} else if (opt[0].equals("-!nodefonttagsize")) {
|
||||
nodeFontTagSize = -1;
|
||||
} else if(opt[0].equals("-nodefontpackagename")) {
|
||||
nodeFontPackageName = opt[1];
|
||||
} else if (opt[0].equals("-!nodefontpackagename")) {
|
||||
nodeFontPackageName = null;
|
||||
} else if(opt[0].equals("-nodefontpackagesize")) {
|
||||
nodeFontPackageSize = Integer.parseInt(opt[1]);
|
||||
} else if (opt[0].equals("-!nodefontpackagesize")) {
|
||||
nodeFontPackageSize = -1;
|
||||
} else if(opt[0].equals("-nodefillcolor")) {
|
||||
nodeFillColor = opt[1];
|
||||
} else if (opt[0].equals("-!nodefillcolor")) {
|
||||
nodeFillColor = null;
|
||||
} else if(opt[0].equals("-output")) {
|
||||
outputFileName = opt[1];
|
||||
} else if (opt[0].equals("-!output")) {
|
||||
outputFileName = "graph.dot";
|
||||
} else if(opt[0].equals("-outputencoding")) {
|
||||
outputEncoding = opt[1];
|
||||
} else if (opt[0].equals("-!outputencoding")) {
|
||||
outputEncoding = "ISO-8859-1";
|
||||
} else if(opt[0].equals("-hide")) {
|
||||
if(opt.length == 1) {
|
||||
hidePatterns.clear();
|
||||
hidePatterns.add(allPattern);
|
||||
} else {
|
||||
try {
|
||||
hidePatterns.add(Pattern.compile(opt[1]));
|
||||
} catch (PatternSyntaxException e) {
|
||||
System.err.println("Skipping invalid pattern " + opt[1]);
|
||||
}
|
||||
}
|
||||
} else if (opt[0].equals("-!hide")) {
|
||||
hidePatterns.clear();
|
||||
} else if(opt[0].equals("-apidocroot")) {
|
||||
apiDocRoot = fixApiDocRoot(opt[1]);
|
||||
} else if (opt[0].equals("-!apidocroot")) {
|
||||
apiDocRoot = null;
|
||||
} else if(opt[0].equals("-apidocmap")) {
|
||||
setApiDocMapFile(opt[1]);
|
||||
} else if (opt[0].equals("-!apidocmap")) {
|
||||
apiDocMap.clear();
|
||||
} else if(opt[0].equals("-noguillemot")) {
|
||||
guilOpen = "<<";
|
||||
guilClose = ">>";
|
||||
} else if (opt[0].equals("-!noguillemot")) {
|
||||
guilOpen = "\u00ab";
|
||||
guilClose = "\u00bb";
|
||||
} else if (opt[0].equals("-view")) {
|
||||
viewName = opt[1];
|
||||
} else if (opt[0].equals("-!view")) {
|
||||
viewName = null;
|
||||
} else if (opt[0].equals("-views")) {
|
||||
findViews = true;
|
||||
} else if (opt[0].equals("-!views")) {
|
||||
findViews = false;
|
||||
} else if (opt[0].equals("-d")) {
|
||||
outputDirectory = opt[1];
|
||||
} else if (opt[0].equals("-!d")) {
|
||||
outputDirectory = null;
|
||||
} else if(opt[0].equals("-inferrel")) {
|
||||
inferRelationships = true;
|
||||
} else if(opt[0].equals("-!inferrel")) {
|
||||
inferRelationships = false;
|
||||
} else if(opt[0].equals("-inferreltype")) {
|
||||
try {
|
||||
inferRelationshipType = RelationType.valueOf(opt[1].toUpperCase());
|
||||
} catch(IllegalArgumentException e) {
|
||||
System.err.println("Unknown association type " + opt[1]);
|
||||
}
|
||||
} else if(opt[0].equals("-!inferreltype")) {
|
||||
inferRelationshipType = RelationType.NAVASSOC;
|
||||
} else if(opt[0].equals("-inferdepvis")) {
|
||||
try {
|
||||
Visibility vis = Visibility.valueOf(opt[1].toUpperCase());
|
||||
inferDependencyVisibility = vis;
|
||||
} catch(IllegalArgumentException e) {
|
||||
System.err.println("Ignoring invalid visibility specification for " +
|
||||
"dependency inference: " + opt[1]);
|
||||
}
|
||||
} else if(opt[0].equals("-!inferdepvis")) {
|
||||
inferDependencyVisibility = Visibility.PRIVATE;
|
||||
} else if(opt[0].equals("-inferdep")) {
|
||||
inferDependencies = true;
|
||||
} else if(opt[0].equals("-!inferdep")) {
|
||||
inferDependencies = false;
|
||||
} else if(opt[0].equals("-inferdepinpackage")) {
|
||||
inferDepInPackage = true;
|
||||
} else if(opt[0].equals("-!inferdepinpackage")) {
|
||||
inferDepInPackage = false;
|
||||
} else if(opt[0].equals("-useimports")) {
|
||||
useImports = true;
|
||||
} else if(opt[0].equals("-!useimports")) {
|
||||
useImports = false;
|
||||
} else if (opt[0].equals("-collpackages")) {
|
||||
try {
|
||||
collPackages.add(Pattern.compile(opt[1]));
|
||||
} catch (PatternSyntaxException e) {
|
||||
System.err.println("Skipping invalid pattern " + opt[1]);
|
||||
}
|
||||
} else if (opt[0].equals("-!collpackages")) {
|
||||
collPackages.clear();
|
||||
} else if (opt[0].equals("-compact")) {
|
||||
compact = true;
|
||||
} else if (opt[0].equals("-!compact")) {
|
||||
compact = false;
|
||||
} else if (opt[0].equals("-postfixpackage")) {
|
||||
postfixPackage = true;
|
||||
} else if (opt[0].equals("-!postfixpackage")) {
|
||||
postfixPackage = false;
|
||||
} else if (opt[0].equals("-link")) {
|
||||
addApiDocRoots(opt[1]);
|
||||
} else if(opt[0].equals("-contextPattern")) {
|
||||
RelationDirection d; RelationType rt;
|
||||
try {
|
||||
d = RelationDirection.valueOf(opt[2].toUpperCase());
|
||||
if(opt[1].equalsIgnoreCase("all")) {
|
||||
contextRelationPattern = new RelationPattern(d);
|
||||
} else {
|
||||
rt = RelationType.valueOf(opt[1].toUpperCase());
|
||||
contextRelationPattern.addRelation(rt, d);
|
||||
}
|
||||
} catch(IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
; // Do nothing, javadoc will handle the option or complain, if
|
||||
// needed.
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds api doc roots from a link. The folder reffered by the link should contain a package-list
|
||||
* file that will be parsed in order to add api doc roots to this configuration
|
||||
* @param packageListUrl
|
||||
*/
|
||||
private void addApiDocRoots(String packageListUrl) {
|
||||
BufferedReader br = null;
|
||||
packageListUrl = fixApiDocRoot(packageListUrl);
|
||||
try {
|
||||
URL url = new URL(packageListUrl + "/package-list");
|
||||
br = new BufferedReader(new InputStreamReader(url.openStream()));
|
||||
String line = null;
|
||||
while((line = br.readLine()) != null) {
|
||||
line = line + ".";
|
||||
Pattern pattern = Pattern.compile(line.replace(".", "\\.") + "[^\\.]*");
|
||||
apiDocMap.put(pattern, packageListUrl);
|
||||
}
|
||||
} catch(IOException e) {
|
||||
System.err.println("Errors happened while accessing the package-list file at "
|
||||
+ packageListUrl);
|
||||
} finally {
|
||||
if(br != null)
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the property file referred by <code>apiDocMapFileName</code> and fills the apiDocMap
|
||||
* accordingly
|
||||
* @param apiDocMapFileName
|
||||
*/
|
||||
void setApiDocMapFile(String apiDocMapFileName) {
|
||||
try {
|
||||
InputStream is = new FileInputStream(apiDocMapFileName);
|
||||
Properties userMap = new Properties();
|
||||
userMap.load(is);
|
||||
for (Map.Entry mapEntry : userMap.entrySet()) {
|
||||
try {
|
||||
Pattern regex = Pattern.compile((String) mapEntry.getKey());
|
||||
String thisRoot = (String) mapEntry.getValue();
|
||||
if (thisRoot != null) {
|
||||
thisRoot = fixApiDocRoot(thisRoot);
|
||||
apiDocMap.put(regex, thisRoot);
|
||||
} else {
|
||||
System.err.println("No URL for pattern " + mapEntry.getKey());
|
||||
}
|
||||
} catch (PatternSyntaxException e) {
|
||||
System.err.println("Skipping bad pattern " + mapEntry.getKey());
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.println("File " + apiDocMapFileName + " was not found: " + e);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error reading the property api map file " + apiDocMapFileName
|
||||
+ ": " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate URL "root" for an external class name. It will
|
||||
* match the class name against the regular expressions specified in the
|
||||
* <code>apiDocMap</code>; if a match is found, the associated URL
|
||||
* will be returned.
|
||||
*
|
||||
* <b>NOTE:</b> The match order of the match attempts is the one specified by the
|
||||
* constructor of the api doc root, so it depends on the order of "-link" and "-apiDocMap"
|
||||
* parameters.
|
||||
*/
|
||||
public String getApiDocRoot(String className) {
|
||||
if(apiDocMap.isEmpty())
|
||||
apiDocMap.put(Pattern.compile(".*"), DEFAULT_EXTERNAL_APIDOC);
|
||||
|
||||
for (Map.Entry<Pattern, String> mapEntry : apiDocMap.entrySet()) {
|
||||
Pattern regex = mapEntry.getKey();
|
||||
Matcher matcher = regex.matcher(className);
|
||||
if (matcher.matches())
|
||||
return mapEntry.getValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Trim and append a file separator to the string */
|
||||
private String fixApiDocRoot(String str) {
|
||||
String fixed = null;
|
||||
if (str != null) {
|
||||
fixed = str.trim();
|
||||
if (fixed.length() > 0) {
|
||||
if (!File.separator.equals("/"))
|
||||
fixed = fixed.replace(File.separator.charAt(0), '/');
|
||||
if (!fixed.endsWith("/"))
|
||||
fixed = fixed + "/";
|
||||
}
|
||||
}
|
||||
return fixed;
|
||||
}
|
||||
|
||||
/** Set the options based on the command line parameters */
|
||||
public void setOptions(String[][] options) {
|
||||
for (String s[] : options)
|
||||
setOption(s);
|
||||
}
|
||||
|
||||
|
||||
/** Set the options based on the tag elements of the ClassDoc parameter */
|
||||
public void setOptions(ClassDoc p) {
|
||||
if (p == null)
|
||||
return;
|
||||
|
||||
for (Tag tag : p.tags("opt")) {
|
||||
String[] opt = StringUtil.tokenize(tag.text());
|
||||
opt[0] = "-" + opt[0];
|
||||
setOption(opt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the supplied string matches an entity specified
|
||||
* with the -hide parameter.
|
||||
* @return true if the string matches.
|
||||
*/
|
||||
public boolean matchesHideExpression(String s) {
|
||||
for (Pattern hidePattern : hidePatterns) {
|
||||
// micro-optimization because the "all pattern" is heavily used in UmlGraphDoc
|
||||
if(hidePattern == allPattern)
|
||||
return true;
|
||||
|
||||
Matcher m = hidePattern.matcher(s);
|
||||
if (strictMatching) {
|
||||
if (m.matches()) {
|
||||
return true;
|
||||
}
|
||||
} else if (m.find()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the supplied string matches an entity specified
|
||||
* with the -hide parameter.
|
||||
* @return true if the string matches.
|
||||
*/
|
||||
public boolean matchesCollPackageExpression(String s) {
|
||||
for (Pattern collPattern : collPackages) {
|
||||
Matcher m = collPattern.matcher(s);
|
||||
if (strictMatching) {
|
||||
if (m.matches()) {
|
||||
return true;
|
||||
}
|
||||
} else if (m.find()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// OptionProvider methods
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
public Options getOptionsFor(ClassDoc cd) {
|
||||
Options localOpt = getGlobalOptions();
|
||||
localOpt.setOptions(cd);
|
||||
return localOpt;
|
||||
}
|
||||
|
||||
public Options getOptionsFor(String name) {
|
||||
return getGlobalOptions();
|
||||
}
|
||||
|
||||
public Options getGlobalOptions() {
|
||||
return (Options) clone();
|
||||
}
|
||||
|
||||
public void overrideForClass(Options opt, ClassDoc cd) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public void overrideForClass(Options opt, String className) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "general class diagram";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("UMLGRAPH OPTIONS\n");
|
||||
for(Field f : this.getClass().getDeclaredFields()) {
|
||||
if(!Modifier.isStatic(f.getModifiers())) {
|
||||
f.setAccessible(true);
|
||||
try {
|
||||
sb.append(f.getName() + ":" + f.get(this) + "\n");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.PackageDoc;
|
||||
|
||||
public class PackageMatcher implements ClassMatcher {
|
||||
protected PackageDoc packageDoc;
|
||||
|
||||
public PackageMatcher(PackageDoc packageDoc) {
|
||||
super();
|
||||
this.packageDoc = packageDoc;
|
||||
}
|
||||
|
||||
public boolean matches(ClassDoc cd) {
|
||||
return cd.containingPackage().equals(packageDoc);
|
||||
}
|
||||
|
||||
public boolean matches(String name) {
|
||||
for (ClassDoc cd : packageDoc.allClasses()) {
|
||||
if (cd.qualifiedName().equals(name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.PackageDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
|
||||
/**
|
||||
* A view designed for UMLDoc, filters out everything that it's not contained in
|
||||
* the specified package.
|
||||
* <p>
|
||||
* As such, can be viewed as a simplified version of a {@linkplain View} using a
|
||||
* single {@linkplain ClassMatcher}, and provides some extra configuration such
|
||||
* as output path configuration (and it is specified in code rather than in
|
||||
* javadoc comments).
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public class PackageView implements OptionProvider {
|
||||
|
||||
private PackageDoc pd;
|
||||
private OptionProvider parent;
|
||||
private ClassMatcher matcher;
|
||||
private String outputPath;
|
||||
|
||||
public PackageView(String outputFolder, PackageDoc pd, RootDoc root, OptionProvider parent) {
|
||||
this.parent = parent;
|
||||
this.pd = pd;
|
||||
this.matcher = new PackageMatcher(pd);
|
||||
this.outputPath = pd.name().replace('.', '/') + "/" + pd.name() + ".dot";
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Package view for package " + pd;
|
||||
}
|
||||
|
||||
public Options getGlobalOptions() {
|
||||
Options go = parent.getGlobalOptions();
|
||||
|
||||
go.setOption(new String[] { "-output", outputPath });
|
||||
go.setOption(new String[] { "-hide" });
|
||||
|
||||
return go;
|
||||
}
|
||||
|
||||
public Options getOptionsFor(ClassDoc cd) {
|
||||
Options go = parent.getGlobalOptions();
|
||||
overrideForClass(go, cd);
|
||||
return go;
|
||||
}
|
||||
|
||||
public Options getOptionsFor(String name) {
|
||||
Options go = parent.getGlobalOptions();
|
||||
overrideForClass(go, name);
|
||||
return go;
|
||||
}
|
||||
|
||||
public void overrideForClass(Options opt, ClassDoc cd) {
|
||||
opt.showQualified = false;
|
||||
if (!matcher.matches(cd) || parent.getGlobalOptions().matchesHideExpression(cd.name()))
|
||||
opt.setOption(new String[] { "-hide" });
|
||||
}
|
||||
|
||||
public void overrideForClass(Options opt, String className) {
|
||||
opt.showQualified = false;
|
||||
if (!matcher.matches(className))
|
||||
opt.setOption(new String[] { "-hide" });
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
|
||||
/**
|
||||
* Matches classes performing a regular expression match on the qualified class
|
||||
* name
|
||||
* @author wolf
|
||||
*/
|
||||
public class PatternMatcher implements ClassMatcher {
|
||||
Pattern pattern;
|
||||
|
||||
public PatternMatcher(Pattern pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public boolean matches(ClassDoc cd) {
|
||||
return matches(cd.toString());
|
||||
}
|
||||
|
||||
public boolean matches(String name) {
|
||||
Matcher matcher = pattern.matcher(name);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* The possibile directions of a relation given a reference class (used in
|
||||
* context diagrams)
|
||||
*/
|
||||
public enum RelationDirection {
|
||||
NONE, IN, OUT, BOTH;
|
||||
|
||||
/**
|
||||
* Adds the current direction
|
||||
* @param d
|
||||
* @return
|
||||
*/
|
||||
public RelationDirection sum(RelationDirection d) {
|
||||
if (this == NONE)
|
||||
return d;
|
||||
|
||||
if ((this == IN && d == OUT) || (this == OUT && d == IN) || this == BOTH || d == BOTH)
|
||||
return BOTH;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this direction "contains" the specified one, that is,
|
||||
* either it's equal to it, or this direction is {@link #BOTH}
|
||||
* @param d
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(RelationDirection d) {
|
||||
if (this == BOTH)
|
||||
return true;
|
||||
else
|
||||
return d == this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts the direction of the relation. Turns IN into OUT and vice-versa, NONE and BOTH
|
||||
* are not changed
|
||||
* @return
|
||||
*/
|
||||
public RelationDirection inverse() {
|
||||
if (this == IN)
|
||||
return OUT;
|
||||
else if (this == OUT)
|
||||
return IN;
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* A map from relation types to directions
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public class RelationPattern {
|
||||
/**
|
||||
* A map from RelationType (indexes) to Direction objects
|
||||
*/
|
||||
RelationDirection[] directions;
|
||||
|
||||
/**
|
||||
* Creates a new pattern using the same direction for every relation kind
|
||||
* @param defaultDirection The direction used to initialize this pattern
|
||||
*/
|
||||
public RelationPattern(RelationDirection defaultDirection) {
|
||||
directions = new RelationDirection[RelationType.values().length];
|
||||
for (int i = 0; i < directions.length; i++) {
|
||||
directions[i] = defaultDirection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds, eventually merging, a direction for the specified relation type
|
||||
* @param relationType
|
||||
* @param direction
|
||||
*/
|
||||
public void addRelation(RelationType relationType, RelationDirection direction) {
|
||||
int idx = relationType.ordinal();
|
||||
directions[idx] = directions[idx].sum(direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this patterns matches at least the direction of one
|
||||
* of the relations in the other relation patterns. Matching is defined
|
||||
* by {@linkplain RelationDirection#contains(RelationDirection)}
|
||||
* @param relationPattern
|
||||
* @return
|
||||
*/
|
||||
public boolean matchesOne(RelationPattern relationPattern) {
|
||||
for (int i = 0; i < directions.length; i++) {
|
||||
if (directions[i].contains(relationPattern.directions[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* The type of relation that links two entities
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public enum RelationType {
|
||||
ASSOC, NAVASSOC, HAS, COMPOSED, DEPEND, EXTENDS, IMPLEMENTS;
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Create a graphviz graph based on the classes in the specified java
|
||||
* source files.
|
||||
*
|
||||
* (C) Copyright 2002-2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* String utility functions
|
||||
* @version $Revision$
|
||||
* @author <a href="http://www.spinellis.gr">Diomidis Spinellis</a>
|
||||
*/
|
||||
class StringUtil {
|
||||
/** Tokenize string s into an array */
|
||||
public static String[] tokenize(String s) {
|
||||
ArrayList<String> r = new ArrayList<String>();
|
||||
String remain = s;
|
||||
int n = 0, pos;
|
||||
|
||||
remain = remain.trim();
|
||||
while (remain.length() > 0) {
|
||||
if (remain.startsWith("\"")) {
|
||||
// Field in quotes
|
||||
pos = remain.indexOf('"', 1);
|
||||
if (pos == -1)
|
||||
break;
|
||||
r.add(remain.substring(1, pos));
|
||||
if (pos + 1 < remain.length())
|
||||
pos++;
|
||||
} else {
|
||||
// Space-separated field
|
||||
pos = remain.indexOf(' ', 0);
|
||||
if (pos == -1) {
|
||||
r.add(remain);
|
||||
remain = "";
|
||||
} else
|
||||
r.add(remain.substring(0, pos));
|
||||
}
|
||||
remain = remain.substring(pos + 1);
|
||||
remain = remain.trim();
|
||||
// - is used as a placeholder for empy fields
|
||||
if (r.get(n).equals("-"))
|
||||
r.set(n, "");
|
||||
n++;
|
||||
}
|
||||
return r.toArray(new String[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
|
||||
/**
|
||||
* Matches every class that extends (directly or indirectly) a class
|
||||
* matched by the regular expression provided.
|
||||
*/
|
||||
public class SubclassMatcher implements ClassMatcher {
|
||||
|
||||
protected RootDoc root;
|
||||
protected Pattern pattern;
|
||||
|
||||
public SubclassMatcher(RootDoc root, Pattern pattern) {
|
||||
this.root = root;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public boolean matches(ClassDoc cd) {
|
||||
// if it's the class we're looking for return
|
||||
if(pattern.matcher(cd.toString()).matches())
|
||||
return true;
|
||||
|
||||
// recurse on supeclass, if available
|
||||
if(cd.superclass() != null)
|
||||
return matches(cd.superclass());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean matches(String name) {
|
||||
ClassDoc cd = root.classNamed(name);
|
||||
if(cd == null)
|
||||
return false;
|
||||
return matches(cd);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* Options for UMLGraph class diagram generation
|
||||
* @opt operations
|
||||
* @opt visibility
|
||||
* @hidden
|
||||
*/
|
||||
public class UMLOptions {}
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
/*
|
||||
* Create a graphviz graph based on the classes in the specified java
|
||||
* source files.
|
||||
*
|
||||
* (C) Copyright 2002-2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.Doc;
|
||||
import com.sun.javadoc.LanguageVersion;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
|
||||
/**
|
||||
* Doclet API implementation
|
||||
* @depend - - - OptionProvider
|
||||
* @depend - - - Options
|
||||
* @depend - - - View
|
||||
* @depend - - - ClassGraph
|
||||
* @depend - - - Version
|
||||
*
|
||||
* @version $Revision$
|
||||
* @author <a href="http://www.spinellis.gr">Diomidis Spinellis</a>
|
||||
*/
|
||||
public class UmlGraph {
|
||||
|
||||
private static final String programName = "UmlGraph";
|
||||
private static final String docletName = "gr.spinellis.umlgraph.doclet.UmlGraph";
|
||||
|
||||
/** Entry point through javadoc */
|
||||
public static boolean start(RootDoc root) throws IOException {
|
||||
Options opt = buildOptions(root);
|
||||
root.printNotice("UMLGraph doclet version " + Version.VERSION + " started");
|
||||
|
||||
View[] views = buildViews(opt, root, root);
|
||||
if(views == null)
|
||||
return false;
|
||||
if (views.length == 0)
|
||||
buildGraph(root, opt, null);
|
||||
else
|
||||
for (int i = 0; i < views.length; i++)
|
||||
buildGraph(root, views[i], null);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
PrintWriter err = new PrintWriter(System.err);
|
||||
com.sun.tools.javadoc.Main.execute(programName,
|
||||
err, err, err, docletName, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the base Options object, that contains both the options specified on the command
|
||||
* line and the ones specified in the UMLOptions class, if available.
|
||||
*/
|
||||
public static Options buildOptions(RootDoc root) {
|
||||
Options opt = new Options();
|
||||
opt.setOptions(root.options());
|
||||
opt.setOptions(findUMLOptions(root));
|
||||
return opt;
|
||||
}
|
||||
|
||||
private static ClassDoc findUMLOptions(RootDoc root) {
|
||||
ClassDoc[] classes = root.classes();
|
||||
for (ClassDoc cd : classes)
|
||||
if(cd.name().equals("UMLOptions"))
|
||||
return cd;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and outputs a single graph according to the view overrides
|
||||
*/
|
||||
public static void buildGraph(RootDoc root, OptionProvider op, Doc contextDoc) throws IOException {
|
||||
Options opt = op.getGlobalOptions();
|
||||
root.printNotice("Building " + op.getDisplayName());
|
||||
ClassDoc[] classes = root.classes();
|
||||
|
||||
ClassGraph c = new ClassGraph(root, op, contextDoc);
|
||||
c.prologue();
|
||||
for (int i = 0; i < classes.length; i++)
|
||||
c.printClass(classes[i], true);
|
||||
for (int i = 0; i < classes.length; i++)
|
||||
c.printRelations(classes[i]);
|
||||
if(opt.inferRelationships)
|
||||
c.printInferredRelations(classes);
|
||||
if(opt.inferDependencies)
|
||||
c.printInferredDependencies(classes);
|
||||
|
||||
c.printExtraClasses(root);
|
||||
c.epilogue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the views according to the parameters on the command line
|
||||
* @param opt The options
|
||||
* @param srcRootDoc The RootDoc for the source classes
|
||||
* @param viewRootDoc The RootDoc for the view classes (may be
|
||||
* different, or may be the same as the srcRootDoc)
|
||||
*/
|
||||
public static View[] buildViews(Options opt, RootDoc srcRootDoc, RootDoc viewRootDoc) {
|
||||
if (opt.viewName != null) {
|
||||
ClassDoc viewClass = viewRootDoc.classNamed(opt.viewName);
|
||||
if(viewClass == null) {
|
||||
System.out.println("View " + opt.viewName + " not found! Exiting without generating any output.");
|
||||
return null;
|
||||
}
|
||||
if(viewClass.tags("view").length == 0) {
|
||||
System.out.println(viewClass + " is not a view!");
|
||||
return null;
|
||||
}
|
||||
if(viewClass.isAbstract()) {
|
||||
System.out.println(viewClass + " is an abstract view, no output will be generated!");
|
||||
return null;
|
||||
}
|
||||
return new View[] { buildView(srcRootDoc, viewClass, opt) };
|
||||
} else if (opt.findViews) {
|
||||
List<View> views = new ArrayList<View>();
|
||||
ClassDoc[] classes = viewRootDoc.classes();
|
||||
|
||||
// find view classes
|
||||
for (int i = 0; i < classes.length; i++)
|
||||
if (classes[i].tags("view").length > 0 && !classes[i].isAbstract())
|
||||
views.add(buildView(srcRootDoc, classes[i], opt));
|
||||
|
||||
return views.toArray(new View[views.size()]);
|
||||
} else
|
||||
return new View[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a view along with its parent views, recursively
|
||||
*/
|
||||
private static View buildView(RootDoc root, ClassDoc viewClass, OptionProvider provider) {
|
||||
ClassDoc superClass = viewClass.superclass();
|
||||
if(superClass == null || superClass.tags("view").length == 0)
|
||||
return new View(root, viewClass, provider);
|
||||
|
||||
return new View(root, viewClass, buildView(root, superClass, provider));
|
||||
}
|
||||
|
||||
/** Option checking */
|
||||
public static int optionLength(String option) {
|
||||
return Options.optionLength(option);
|
||||
}
|
||||
|
||||
/** Indicate the language version we support */
|
||||
public static LanguageVersion languageVersion() {
|
||||
return LanguageVersion.JAVA_1_5;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,242 +0,0 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.LanguageVersion;
|
||||
import com.sun.javadoc.PackageDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
import com.sun.tools.doclets.standard.Standard;
|
||||
|
||||
/**
|
||||
* Chaining doclet that runs the standart Javadoc doclet first, and on success,
|
||||
* runs the generation of dot files by UMLGraph
|
||||
* @author wolf
|
||||
*
|
||||
* @depend - - - WrappedClassDoc
|
||||
* @depend - - - WrappedRootDoc
|
||||
*/
|
||||
public class UmlGraphDoc {
|
||||
/**
|
||||
* Option check, forwards options to the standard doclet, if that one refuses them,
|
||||
* they are sent to UmlGraph
|
||||
*/
|
||||
public static int optionLength(String option) {
|
||||
int result = Standard.optionLength(option);
|
||||
if (result != 0)
|
||||
return result;
|
||||
else
|
||||
return UmlGraph.optionLength(option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard doclet entry point
|
||||
* @param root
|
||||
* @return
|
||||
*/
|
||||
public static boolean start(RootDoc root) {
|
||||
root.printNotice("UmlGraphDoc version " + Version.VERSION + ", running the standard doclet");
|
||||
Standard.start(root);
|
||||
root.printNotice("UmlGraphDoc version " + Version.VERSION + ", altering javadocs");
|
||||
try {
|
||||
String outputFolder = findOutputPath(root.options());
|
||||
|
||||
Options opt = new Options();
|
||||
opt.setOptions(root.options());
|
||||
// in javadoc enumerations are always printed
|
||||
opt.showEnumerations = true;
|
||||
opt.relativeLinksForSourcePackages = true;
|
||||
// enable strict matching for hide expressions
|
||||
opt.strictMatching = true;
|
||||
// root.printNotice(opt.toString());
|
||||
|
||||
root = new WrappedRootDoc(root);
|
||||
generatePackageDiagrams(root, opt, outputFolder);
|
||||
generateContextDiagrams(root, opt, outputFolder);
|
||||
} catch(Throwable t) {
|
||||
root.printWarning("Error!");
|
||||
root.printWarning(t.toString());
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standand doclet entry
|
||||
* @return
|
||||
*/
|
||||
public static LanguageVersion languageVersion() {
|
||||
return Standard.languageVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the package diagrams for all of the packages that contain classes among those
|
||||
* returned by RootDoc.class()
|
||||
*/
|
||||
private static void generatePackageDiagrams(RootDoc root, Options opt, String outputFolder)
|
||||
throws IOException {
|
||||
Set<String> packages = new HashSet<String>();
|
||||
for (ClassDoc classDoc : root.classes()) {
|
||||
PackageDoc packageDoc = classDoc.containingPackage();
|
||||
if(!packages.contains(packageDoc.name())) {
|
||||
packages.add(packageDoc.name());
|
||||
OptionProvider view = new PackageView(outputFolder, packageDoc, root, opt);
|
||||
UmlGraph.buildGraph(root, view, packageDoc);
|
||||
runGraphviz(outputFolder, packageDoc.name(), packageDoc.name(), root);
|
||||
alterHtmlDocs(outputFolder, packageDoc.name(), packageDoc.name(),
|
||||
"package-summary.html", Pattern.compile("</H2>"), root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the context diagram for a single class
|
||||
*/
|
||||
private static void generateContextDiagrams(RootDoc root, Options opt, String outputFolder)
|
||||
throws IOException {
|
||||
ContextView view = null;
|
||||
for (ClassDoc classDoc : root.classes()) {
|
||||
if(view == null)
|
||||
view = new ContextView(outputFolder, classDoc, root, opt);
|
||||
else
|
||||
view.setContextCenter(classDoc);
|
||||
UmlGraph.buildGraph(root, view, classDoc);
|
||||
runGraphviz(outputFolder, classDoc.containingPackage().name(), classDoc.name(), root);
|
||||
alterHtmlDocs(outputFolder, classDoc.containingPackage().name(), classDoc.name(),
|
||||
classDoc.name() + ".html", Pattern.compile("(Class|Interface|Enum) " + classDoc.name() + ".*") , root);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs Graphviz dot building both a diagram (in png format) and a client side map for it.
|
||||
* <p>
|
||||
* At the moment, it assumes dot.exe is in the classpahth
|
||||
*/
|
||||
private static void runGraphviz(String outputFolder, String packageName, String name, RootDoc root) {
|
||||
File dotFile = new File(outputFolder, packageName.replace(".", "/") + "/" + name + ".dot");
|
||||
File pngFile = new File(outputFolder, packageName.replace(".", "/") + "/" + name + ".png");
|
||||
File mapFile = new File(outputFolder, packageName.replace(".", "/") + "/" + name + ".map");
|
||||
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(new String [] {
|
||||
"dot",
|
||||
"-Tcmapx",
|
||||
"-o",
|
||||
mapFile.getAbsolutePath(),
|
||||
"-Tpng",
|
||||
"-o",
|
||||
pngFile.getAbsolutePath(),
|
||||
dotFile.getAbsolutePath()
|
||||
});
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||
String line = null;
|
||||
while((line = reader.readLine()) != null)
|
||||
root.printWarning(line);
|
||||
int result = p.waitFor();
|
||||
if (result != 0)
|
||||
root.printWarning("Errors running Graphviz on " + dotFile);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an HTML file, looks for the first instance of the specified insertion point, and
|
||||
* inserts the diagram image reference and a client side map in that point.
|
||||
*/
|
||||
private static void alterHtmlDocs(String outputFolder, String packageName, String className,
|
||||
String htmlFileName, Pattern insertPointPattern, RootDoc root) throws IOException {
|
||||
// setup files
|
||||
File output = new File(outputFolder, packageName.replace(".", "/"));
|
||||
File htmlFile = new File(output, htmlFileName);
|
||||
File alteredFile = new File(htmlFile.getAbsolutePath() + ".uml");
|
||||
File mapFile = new File(output, className + ".map");
|
||||
if (!htmlFile.exists()) {
|
||||
System.err.println("Expected file not found: " + htmlFile.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
|
||||
// parse & rewrite
|
||||
BufferedWriter writer = null;
|
||||
BufferedReader reader = null;
|
||||
boolean matched = false;
|
||||
try {
|
||||
int BUFSIZE = (int) Math.pow(2, 20); // more or less one megabyte
|
||||
writer = new BufferedWriter(new FileWriter(alteredFile), BUFSIZE);
|
||||
reader = new BufferedReader(new FileReader(htmlFile));
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
writer.write(line);
|
||||
writer.newLine();
|
||||
if (!matched && insertPointPattern.matcher(line).matches()) {
|
||||
matched = true;
|
||||
if (mapFile.exists())
|
||||
insertClientSideMap(mapFile, writer);
|
||||
else
|
||||
root.printWarning("Could not find map file " + mapFile);
|
||||
writer.write("<div align=\"center\"><img src=\"" + className
|
||||
+ ".png\" alt=\"Package class diagram package " + className
|
||||
+ "\" usemap=\"#G\" border=0/></a></div>");
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (writer != null)
|
||||
writer.close();
|
||||
if (reader != null)
|
||||
reader.close();
|
||||
}
|
||||
|
||||
// if altered, delete old file and rename new one to the old file name
|
||||
if (matched) {
|
||||
htmlFile.delete();
|
||||
alteredFile.renameTo(htmlFile);
|
||||
} else {
|
||||
root.printNotice("Warning, could not find a line that matches the pattern '" + insertPointPattern.pattern()
|
||||
+ "'.\n Class diagram reference not inserted");
|
||||
alteredFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the map file and outputs in to the specified writer
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void insertClientSideMap(File mapFile, BufferedWriter writer) throws IOException {
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(mapFile));
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
writer.write(line);
|
||||
writer.newLine();
|
||||
}
|
||||
} finally {
|
||||
if (reader != null)
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output path specified on the javadoc options
|
||||
*/
|
||||
private static String findOutputPath(String[][] options) {
|
||||
for (int i = 0; i < options.length; i++) {
|
||||
if (options[i][0].equals("-d"))
|
||||
return options[i][1];
|
||||
}
|
||||
return ".";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
/*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
import com.sun.javadoc.Tag;
|
||||
|
||||
/**
|
||||
* Contains the definition of a View. A View is a set of option overrides that
|
||||
* will lead to the creation of a UML class diagram. Multiple views can be
|
||||
* defined on the same source tree, effectively allowing to create multiple
|
||||
* class diagram out of it.
|
||||
* @author wolf
|
||||
*
|
||||
* @depend - - - Options
|
||||
* @depend - - - ClassMatcher
|
||||
* @depend - - - InterfaceMatcher
|
||||
* @depend - - - PatternMatcher
|
||||
* @depend - - - SubclassMatcher
|
||||
* @depend - - - ContextMatcher
|
||||
*
|
||||
*/
|
||||
public class View implements OptionProvider {
|
||||
Map<ClassMatcher, List<String[]>> optionOverrides = new LinkedHashMap<ClassMatcher, List<String[]>>();
|
||||
ClassDoc viewDoc;
|
||||
OptionProvider provider;
|
||||
List<String[]> globalOptions;
|
||||
RootDoc root;
|
||||
|
||||
/**
|
||||
* Builds a view given the class that contains its definition
|
||||
*/
|
||||
public View(RootDoc root, ClassDoc c, OptionProvider provider) {
|
||||
this.viewDoc = c;
|
||||
this.provider = provider;
|
||||
this.root = root;
|
||||
Tag[] tags = c.tags();
|
||||
ClassMatcher currMatcher = null;
|
||||
// parse options, get the global ones, and build a map of the
|
||||
// pattern matched overrides
|
||||
globalOptions = new ArrayList<String[]>();
|
||||
for (int i = 0; i < tags.length; i++) {
|
||||
if (tags[i].name().equals("@match")) {
|
||||
currMatcher = buildMatcher(tags[i].text());
|
||||
if(currMatcher != null) {
|
||||
optionOverrides.put(currMatcher, new ArrayList<String[]>());
|
||||
}
|
||||
} else if (tags[i].name().equals("@opt")) {
|
||||
String[] opts = StringUtil.tokenize(tags[i].text());
|
||||
opts[0] = "-" + opts[0];
|
||||
if (currMatcher == null) {
|
||||
globalOptions.add(opts);
|
||||
} else {
|
||||
optionOverrides.get(currMatcher).add(opts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that builds the appropriate matcher for @match tags
|
||||
*/
|
||||
private ClassMatcher buildMatcher(String tagText) {
|
||||
// check there are at least @match <type> and a parameter
|
||||
String[] strings = StringUtil.tokenize(tagText);
|
||||
if (strings.length < 2) {
|
||||
System.err.println("Skipping uncomplete @match tag, type missing: " + tagText + " in view " + viewDoc);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (strings[0].equals("class")) {
|
||||
return new PatternMatcher(Pattern.compile(strings[1]));
|
||||
} else if (strings[0].equals("context")) {
|
||||
return new ContextMatcher(root, Pattern.compile(strings[1]), getGlobalOptions(),
|
||||
false);
|
||||
} else if (strings[0].equals("outgoingContext")) {
|
||||
return new ContextMatcher(root, Pattern.compile(strings[1]), getGlobalOptions(),
|
||||
false);
|
||||
} else if (strings[0].equals("interface")) {
|
||||
return new InterfaceMatcher(root, Pattern.compile(strings[1]));
|
||||
} else if (strings[0].equals("subclass")) {
|
||||
return new SubclassMatcher(root, Pattern.compile(strings[1]));
|
||||
} else {
|
||||
System.err.println("Skipping @match tag, unknown match type, in view " + viewDoc);
|
||||
}
|
||||
} catch (PatternSyntaxException pse) {
|
||||
System.err.println("Skipping @match tag due to invalid regular expression '" + tagText
|
||||
+ "'" + " in view " + viewDoc);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Skipping @match tag due to an internal error '" + tagText
|
||||
+ "'" + " in view " + viewDoc);
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// OptionProvider methods
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
public Options getOptionsFor(ClassDoc cd) {
|
||||
Options localOpt = getGlobalOptions();
|
||||
overrideForClass(localOpt, cd);
|
||||
localOpt.setOptions(cd);
|
||||
return localOpt;
|
||||
}
|
||||
|
||||
public Options getOptionsFor(String name) {
|
||||
Options localOpt = getGlobalOptions();
|
||||
overrideForClass(localOpt, name);
|
||||
return localOpt;
|
||||
}
|
||||
|
||||
public Options getGlobalOptions() {
|
||||
Options go = provider.getGlobalOptions();
|
||||
|
||||
boolean outputSet = false;
|
||||
for (String[] opts : globalOptions) {
|
||||
if (opts[0].equals("-output"))
|
||||
outputSet = true;
|
||||
go.setOption(opts);
|
||||
}
|
||||
if (!outputSet)
|
||||
go.setOption(new String[] { "-output", viewDoc.name() + ".dot" });
|
||||
|
||||
return go;
|
||||
}
|
||||
|
||||
public void overrideForClass(Options opt, ClassDoc cd) {
|
||||
provider.overrideForClass(opt, cd);
|
||||
for (ClassMatcher cm : optionOverrides.keySet()) {
|
||||
if(cm.matches(cd)) {
|
||||
for (String[] override : optionOverrides.get(cm)) {
|
||||
opt.setOption(override);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void overrideForClass(Options opt, String className) {
|
||||
provider.overrideForClass(opt, className);
|
||||
for (ClassMatcher cm : optionOverrides.keySet()) {
|
||||
if(cm.matches(className)) {
|
||||
for (String[] override : optionOverrides.get(cm)) {
|
||||
opt.setOption(override);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "view " + viewDoc.name();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Create a graphviz graph based on the classes in the specified java
|
||||
* source files.
|
||||
*
|
||||
* (C) Copyright 2002-2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import com.sun.javadoc.ProgramElementDoc;
|
||||
|
||||
/**
|
||||
* Enumerates the possible visibilities in a Java program. For brevity, package
|
||||
* private visibility is referred as PACKAGE.
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public enum Visibility {
|
||||
PRIVATE, PACKAGE, PROTECTED, PUBLIC;
|
||||
|
||||
public static Visibility get(ProgramElementDoc doc) {
|
||||
if (doc.isPrivate())
|
||||
return PRIVATE;
|
||||
else if (doc.isPackagePrivate())
|
||||
return PACKAGE;
|
||||
else if (doc.isProtected())
|
||||
return PROTECTED;
|
||||
else
|
||||
return PUBLIC;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,362 +0,0 @@
|
|||
/*
|
||||
* Create a graphviz graph based on the classes in the specified java
|
||||
* source files.
|
||||
*
|
||||
* (C) Copyright 2002-2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import com.sun.javadoc.AnnotationDesc;
|
||||
import com.sun.javadoc.AnnotationTypeDoc;
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.ConstructorDoc;
|
||||
import com.sun.javadoc.FieldDoc;
|
||||
import com.sun.javadoc.MethodDoc;
|
||||
import com.sun.javadoc.PackageDoc;
|
||||
import com.sun.javadoc.ParamTag;
|
||||
import com.sun.javadoc.ParameterizedType;
|
||||
import com.sun.javadoc.SeeTag;
|
||||
import com.sun.javadoc.SourcePosition;
|
||||
import com.sun.javadoc.Tag;
|
||||
import com.sun.javadoc.Type;
|
||||
import com.sun.javadoc.TypeVariable;
|
||||
import com.sun.javadoc.WildcardType;
|
||||
|
||||
/**
|
||||
* A ClassDoc wrapper that caches answer to the most common requests performed
|
||||
* by UMLGraph, considerably improving the overall UMLDoc performance (ClassDoc
|
||||
* computes most of the results for more fine grained information at each call).
|
||||
* <p>
|
||||
* Unfortunately this has a side effect, since it breaks the equals() call between
|
||||
* plain ClassDoc instances and WrappedClassDoc ones, so use it with due care.
|
||||
* <p>
|
||||
* In particular, don't provide WrappedClassDoc instances to the standard doclet.
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public class WrappedClassDoc implements ClassDoc {
|
||||
ClassDoc wrapped;
|
||||
String toString;
|
||||
String name;
|
||||
Tag[] tags;
|
||||
|
||||
public WrappedClassDoc(ClassDoc wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
public AnnotationDesc[] annotations() {
|
||||
return wrapped.annotations();
|
||||
}
|
||||
|
||||
public AnnotationTypeDoc asAnnotationTypeDoc() {
|
||||
return wrapped.asAnnotationTypeDoc();
|
||||
}
|
||||
|
||||
public ClassDoc asClassDoc() {
|
||||
return wrapped.asClassDoc();
|
||||
}
|
||||
|
||||
public ParameterizedType asParameterizedType() {
|
||||
return wrapped.asParameterizedType();
|
||||
}
|
||||
|
||||
public TypeVariable asTypeVariable() {
|
||||
return wrapped.asTypeVariable();
|
||||
}
|
||||
|
||||
public WildcardType asWildcardType() {
|
||||
return wrapped.asWildcardType();
|
||||
}
|
||||
|
||||
public String commentText() {
|
||||
return wrapped.commentText();
|
||||
}
|
||||
|
||||
public int compareTo(Object arg0) {
|
||||
if (arg0 instanceof WrappedClassDoc) {
|
||||
WrappedClassDoc other = (WrappedClassDoc) arg0;
|
||||
return wrapped.compareTo(other.wrapped);
|
||||
}
|
||||
return wrapped.compareTo(arg0);
|
||||
}
|
||||
|
||||
public ConstructorDoc[] constructors() {
|
||||
return wrapped.constructors();
|
||||
}
|
||||
|
||||
public ConstructorDoc[] constructors(boolean arg0) {
|
||||
return wrapped.constructors(arg0);
|
||||
}
|
||||
|
||||
public ClassDoc containingClass() {
|
||||
return wrapped.containingClass();
|
||||
}
|
||||
|
||||
public PackageDoc containingPackage() {
|
||||
return wrapped.containingPackage();
|
||||
}
|
||||
|
||||
public boolean definesSerializableFields() {
|
||||
return wrapped.definesSerializableFields();
|
||||
}
|
||||
|
||||
public String dimension() {
|
||||
return wrapped.dimension();
|
||||
}
|
||||
|
||||
public FieldDoc[] enumConstants() {
|
||||
return wrapped.enumConstants();
|
||||
}
|
||||
|
||||
public FieldDoc[] fields() {
|
||||
return wrapped.fields();
|
||||
}
|
||||
|
||||
public FieldDoc[] fields(boolean arg0) {
|
||||
return wrapped.fields(arg0);
|
||||
}
|
||||
|
||||
public ClassDoc findClass(String arg0) {
|
||||
return wrapped.findClass(arg0);
|
||||
}
|
||||
|
||||
public Tag[] firstSentenceTags() {
|
||||
return wrapped.firstSentenceTags();
|
||||
}
|
||||
|
||||
public String getRawCommentText() {
|
||||
return wrapped.getRawCommentText();
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
public @Deprecated ClassDoc[] importedClasses() {
|
||||
return wrapped.importedClasses();
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
public @Deprecated PackageDoc[] importedPackages() {
|
||||
return wrapped.importedPackages();
|
||||
}
|
||||
|
||||
public Tag[] inlineTags() {
|
||||
return wrapped.inlineTags();
|
||||
}
|
||||
|
||||
public ClassDoc[] innerClasses() {
|
||||
return wrapped.innerClasses();
|
||||
}
|
||||
|
||||
public ClassDoc[] innerClasses(boolean arg0) {
|
||||
return wrapped.innerClasses(arg0);
|
||||
}
|
||||
|
||||
public ClassDoc[] interfaces() {
|
||||
return wrapped.interfaces();
|
||||
}
|
||||
|
||||
public Type[] interfaceTypes() {
|
||||
return wrapped.interfaceTypes();
|
||||
}
|
||||
|
||||
public boolean isAbstract() {
|
||||
return wrapped.isAbstract();
|
||||
}
|
||||
|
||||
public boolean isAnnotationType() {
|
||||
return wrapped.isAnnotationType();
|
||||
}
|
||||
|
||||
public boolean isAnnotationTypeElement() {
|
||||
return wrapped.isAnnotationTypeElement();
|
||||
}
|
||||
|
||||
public boolean isClass() {
|
||||
return wrapped.isClass();
|
||||
}
|
||||
|
||||
public boolean isConstructor() {
|
||||
return wrapped.isConstructor();
|
||||
}
|
||||
|
||||
public boolean isEnum() {
|
||||
return wrapped.isEnum();
|
||||
}
|
||||
|
||||
public boolean isEnumConstant() {
|
||||
return wrapped.isEnumConstant();
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return wrapped.isError();
|
||||
}
|
||||
|
||||
public boolean isException() {
|
||||
return wrapped.isException();
|
||||
}
|
||||
|
||||
public boolean isExternalizable() {
|
||||
return wrapped.isExternalizable();
|
||||
}
|
||||
|
||||
public boolean isField() {
|
||||
return wrapped.isField();
|
||||
}
|
||||
|
||||
public boolean isFinal() {
|
||||
return wrapped.isFinal();
|
||||
}
|
||||
|
||||
public boolean isIncluded() {
|
||||
return wrapped.isIncluded();
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return wrapped.isInterface();
|
||||
}
|
||||
|
||||
public boolean isMethod() {
|
||||
return wrapped.isMethod();
|
||||
}
|
||||
|
||||
public boolean isOrdinaryClass() {
|
||||
return wrapped.isOrdinaryClass();
|
||||
}
|
||||
|
||||
public boolean isPackagePrivate() {
|
||||
return wrapped.isPackagePrivate();
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
return wrapped.isPrimitive();
|
||||
}
|
||||
|
||||
public boolean isPrivate() {
|
||||
return wrapped.isPrivate();
|
||||
}
|
||||
|
||||
public boolean isProtected() {
|
||||
return wrapped.isProtected();
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
return wrapped.isPublic();
|
||||
}
|
||||
|
||||
public boolean isSerializable() {
|
||||
return wrapped.isSerializable();
|
||||
}
|
||||
|
||||
public boolean isStatic() {
|
||||
return wrapped.isStatic();
|
||||
}
|
||||
|
||||
public MethodDoc[] methods() {
|
||||
return wrapped.methods();
|
||||
}
|
||||
|
||||
public MethodDoc[] methods(boolean arg0) {
|
||||
return wrapped.methods(arg0);
|
||||
}
|
||||
|
||||
public String modifiers() {
|
||||
return wrapped.modifiers();
|
||||
}
|
||||
|
||||
public int modifierSpecifier() {
|
||||
return wrapped.modifierSpecifier();
|
||||
}
|
||||
|
||||
public String name() {
|
||||
if (name == null)
|
||||
name = wrapped.name();
|
||||
return name;
|
||||
}
|
||||
|
||||
public SourcePosition position() {
|
||||
return wrapped.position();
|
||||
}
|
||||
|
||||
public String qualifiedName() {
|
||||
return wrapped.qualifiedName();
|
||||
}
|
||||
|
||||
public String qualifiedTypeName() {
|
||||
return wrapped.qualifiedTypeName();
|
||||
}
|
||||
|
||||
public SeeTag[] seeTags() {
|
||||
return wrapped.seeTags();
|
||||
}
|
||||
|
||||
public FieldDoc[] serializableFields() {
|
||||
return wrapped.serializableFields();
|
||||
}
|
||||
|
||||
public MethodDoc[] serializationMethods() {
|
||||
return wrapped.serializationMethods();
|
||||
}
|
||||
|
||||
public void setRawCommentText(String arg0) {
|
||||
wrapped.setRawCommentText(arg0);
|
||||
}
|
||||
|
||||
public String simpleTypeName() {
|
||||
return wrapped.simpleTypeName();
|
||||
}
|
||||
|
||||
public boolean subclassOf(ClassDoc arg0) {
|
||||
return wrapped.subclassOf(arg0);
|
||||
}
|
||||
|
||||
public ClassDoc superclass() {
|
||||
return wrapped.superclass();
|
||||
}
|
||||
|
||||
public Type superclassType() {
|
||||
return wrapped.superclassType();
|
||||
}
|
||||
|
||||
public Tag[] tags() {
|
||||
if (tags == null)
|
||||
tags = wrapped.tags();
|
||||
return tags;
|
||||
}
|
||||
|
||||
public Tag[] tags(String arg0) {
|
||||
return wrapped.tags(arg0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (toString == null) {
|
||||
toString = wrapped.toString();
|
||||
}
|
||||
return toString;
|
||||
}
|
||||
|
||||
public String typeName() {
|
||||
return wrapped.typeName();
|
||||
}
|
||||
|
||||
public TypeVariable[] typeParameters() {
|
||||
return wrapped.typeParameters();
|
||||
}
|
||||
|
||||
public ParamTag[] typeParamTags() {
|
||||
return wrapped.typeParamTags();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* Create a graphviz graph based on the classes in the specified java
|
||||
* source files.
|
||||
*
|
||||
* (C) Copyright 2002-2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.PackageDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
import com.sun.javadoc.SeeTag;
|
||||
import com.sun.javadoc.SourcePosition;
|
||||
import com.sun.javadoc.Tag;
|
||||
|
||||
/**
|
||||
* RootDoc wrapper that provides WrappedClassDoc instances instead of plain ClassDoc in order
|
||||
* to optimize the overall performance of UMLDoc.
|
||||
* @author wolf
|
||||
*/
|
||||
public class WrappedRootDoc implements RootDoc {
|
||||
RootDoc wrapped;
|
||||
WrappedClassDoc[] wrappedClassDocs;
|
||||
|
||||
public WrappedRootDoc(RootDoc wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
ClassDoc[] classes = wrapped.classes();
|
||||
wrappedClassDocs = new WrappedClassDoc[classes.length];
|
||||
for (int i = 0; i < classes.length; i++) {
|
||||
wrappedClassDocs[i] = new WrappedClassDoc(classes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public ClassDoc[] classes() {
|
||||
return wrappedClassDocs;
|
||||
}
|
||||
|
||||
public ClassDoc classNamed(String arg0) {
|
||||
return wrapped.classNamed(arg0);
|
||||
}
|
||||
|
||||
public String commentText() {
|
||||
return wrapped.commentText();
|
||||
}
|
||||
|
||||
public int compareTo(Object arg0) {
|
||||
return wrapped.compareTo(arg0);
|
||||
}
|
||||
|
||||
public Tag[] firstSentenceTags() {
|
||||
return wrapped.firstSentenceTags();
|
||||
}
|
||||
|
||||
public String getRawCommentText() {
|
||||
return wrapped.getRawCommentText();
|
||||
}
|
||||
|
||||
public Tag[] inlineTags() {
|
||||
return wrapped.inlineTags();
|
||||
}
|
||||
|
||||
public boolean isAnnotationType() {
|
||||
return wrapped.isAnnotationType();
|
||||
}
|
||||
|
||||
public boolean isAnnotationTypeElement() {
|
||||
return wrapped.isAnnotationTypeElement();
|
||||
}
|
||||
|
||||
public boolean isClass() {
|
||||
return wrapped.isClass();
|
||||
}
|
||||
|
||||
public boolean isConstructor() {
|
||||
return wrapped.isConstructor();
|
||||
}
|
||||
|
||||
public boolean isEnum() {
|
||||
return wrapped.isEnum();
|
||||
}
|
||||
|
||||
public boolean isEnumConstant() {
|
||||
return wrapped.isEnumConstant();
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return wrapped.isError();
|
||||
}
|
||||
|
||||
public boolean isException() {
|
||||
return wrapped.isException();
|
||||
}
|
||||
|
||||
public boolean isField() {
|
||||
return wrapped.isField();
|
||||
}
|
||||
|
||||
public boolean isIncluded() {
|
||||
return wrapped.isIncluded();
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return wrapped.isInterface();
|
||||
}
|
||||
|
||||
public boolean isMethod() {
|
||||
return wrapped.isMethod();
|
||||
}
|
||||
|
||||
public boolean isOrdinaryClass() {
|
||||
return wrapped.isOrdinaryClass();
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return wrapped.name();
|
||||
}
|
||||
|
||||
public String[][] options() {
|
||||
return wrapped.options();
|
||||
}
|
||||
|
||||
public PackageDoc packageNamed(String arg0) {
|
||||
return wrapped.packageNamed(arg0);
|
||||
}
|
||||
|
||||
public SourcePosition position() {
|
||||
return wrapped.position();
|
||||
}
|
||||
|
||||
public void printError(SourcePosition arg0, String arg1) {
|
||||
wrapped.printError(arg0, arg1);
|
||||
}
|
||||
|
||||
public void printError(String arg0) {
|
||||
wrapped.printError(arg0);
|
||||
}
|
||||
|
||||
public void printNotice(SourcePosition arg0, String arg1) {
|
||||
wrapped.printNotice(arg0, arg1);
|
||||
}
|
||||
|
||||
public void printNotice(String arg0) {
|
||||
wrapped.printNotice(arg0);
|
||||
}
|
||||
|
||||
public void printWarning(SourcePosition arg0, String arg1) {
|
||||
wrapped.printWarning(arg0, arg1);
|
||||
}
|
||||
|
||||
public void printWarning(String arg0) {
|
||||
wrapped.printWarning(arg0);
|
||||
}
|
||||
|
||||
public SeeTag[] seeTags() {
|
||||
return wrapped.seeTags();
|
||||
}
|
||||
|
||||
public void setRawCommentText(String arg0) {
|
||||
wrapped.setRawCommentText(arg0);
|
||||
}
|
||||
|
||||
public ClassDoc[] specifiedClasses() {
|
||||
return wrapped.specifiedClasses();
|
||||
}
|
||||
|
||||
public PackageDoc[] specifiedPackages() {
|
||||
return wrapped.specifiedPackages();
|
||||
}
|
||||
|
||||
public Tag[] tags() {
|
||||
return wrapped.tags();
|
||||
}
|
||||
|
||||
public Tag[] tags(String arg0) {
|
||||
return wrapped.tags(arg0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* UmlGraph class diagram testing framework
|
||||
*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* UmlGraph regression tests
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public class BasicTest {
|
||||
|
||||
static String testSourceFolder = "testdata/java";
|
||||
|
||||
static String testDestFolder = "testdata/dot-out";
|
||||
|
||||
static String testRefFolder = "testdata/dot-ref";
|
||||
|
||||
static PrintWriter pw = new PrintWriter(System.out);
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
List<String> differences = new ArrayList<String>();
|
||||
|
||||
File outFolder = new File(testDestFolder);
|
||||
if (!outFolder.exists())
|
||||
outFolder.mkdirs();
|
||||
|
||||
TestUtils.cleanFolder(outFolder, true);
|
||||
|
||||
// don't use windows specific fonts
|
||||
System.setProperty("os.name", "generic");
|
||||
|
||||
// run tests
|
||||
performBasicTests(differences);
|
||||
performViewTests(differences, outFolder);
|
||||
if (differences.size() > 0) {
|
||||
pw.println("ERROR, some files are not structurally equal or some files are missing:");
|
||||
for (String className : differences) {
|
||||
pw.println(className);
|
||||
}
|
||||
} else {
|
||||
pw.println("GOOD, all files are structurally equal");
|
||||
}
|
||||
pw.println();
|
||||
pw.println();
|
||||
pw.flush();
|
||||
}
|
||||
|
||||
private static void performViewTests(List<String> differences, File outFolder)
|
||||
throws IOException {
|
||||
String[] options = new String[] { "-docletpath", "build", "-private", "-d",
|
||||
outFolder.getAbsolutePath(), "-sourcepath", "testdata/java", "-compact",
|
||||
"-subpackages", "gr.spinellis", "-views" };
|
||||
runDoclet(options);
|
||||
|
||||
List<String> viewFiles = new ArrayList<String>();
|
||||
viewFiles.addAll(getViewList(new File(testSourceFolder, "gr/spinellis/basic/views")));
|
||||
viewFiles.addAll(getViewList(new File(testSourceFolder, "gr/spinellis/context/views")));
|
||||
viewFiles.addAll(getViewList(new File(testSourceFolder, "gr/spinellis/iface/views")));
|
||||
viewFiles.addAll(getViewList(new File(testSourceFolder, "gr/spinellis/subclass/views")));
|
||||
for (String fileName : viewFiles) {
|
||||
String viewName = fileName.substring(0, fileName.length() - 5);
|
||||
File dotFile = new File(testDestFolder, viewName + ".dot");
|
||||
File refFile = new File(testRefFolder, viewName + ".dot");
|
||||
if (viewName.contains("Abstract")) {
|
||||
// make sure abstract views are not generated
|
||||
if (dotFile.exists()) {
|
||||
pw.println("Error, abstract view " + viewName + " has been generated");
|
||||
differences.add(dotFile.getName() + " should not be there");
|
||||
}
|
||||
} else {
|
||||
compare(differences, dotFile, refFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> getViewList(File viewFolder) {
|
||||
if (!viewFolder.exists())
|
||||
throw new RuntimeException("The folder " + viewFolder.getAbsolutePath()
|
||||
+ " does not exists.");
|
||||
else if (!viewFolder.isDirectory())
|
||||
throw new RuntimeException(viewFolder.getAbsolutePath() + " is not a folder!.");
|
||||
else if (!viewFolder.canRead())
|
||||
throw new RuntimeException("The folder " + viewFolder.getAbsolutePath()
|
||||
+ " cannot be read.");
|
||||
|
||||
return Arrays.asList(viewFolder.list(new SimpleFileFilter(".java")));
|
||||
}
|
||||
|
||||
private static boolean performBasicTests(List<String> differences) throws IOException {
|
||||
String[] javaFiles = new File(testSourceFolder).list(new SimpleFileFilter(".java"));
|
||||
boolean equal = true;
|
||||
for (int i = 0; i < javaFiles.length; i++) {
|
||||
String javaFileName = javaFiles[i].substring(0, javaFiles[i].length() - 5);
|
||||
String outFileName = javaFileName + ".dot";
|
||||
File dotFile = new File(testDestFolder, outFileName);
|
||||
dotFile.delete();
|
||||
File refFile = new File(testRefFolder, outFileName);
|
||||
String javaPath = new File(testSourceFolder, javaFiles[i]).getAbsolutePath();
|
||||
String[] options = new String[] { "-docletpath", "build", "-hide", "Hidden",
|
||||
"-compact", "-private", "-d", testDestFolder, "-output", outFileName, javaPath };
|
||||
|
||||
runDoclet(options);
|
||||
compare(differences, dotFile, refFile);
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
|
||||
private static void runDoclet(String[] options) {
|
||||
com.sun.tools.javadoc.Main.execute("UMLGraph test", pw, pw, pw,
|
||||
"gr.spinellis.umlgraph.doclet.UmlGraph", options);
|
||||
}
|
||||
|
||||
private static void compare(List<String> differences, File dotFile, File refFile)
|
||||
throws IOException {
|
||||
if (!dotFile.exists()) {
|
||||
pw.println("Error, output file " + dotFile + " has not been generated");
|
||||
differences.add(dotFile.getName() + " has not been generated");
|
||||
} else if (!refFile.exists()) {
|
||||
pw.println("Error, reference file " + refFile + " is not available");
|
||||
differences.add(refFile.getName() + " reference is not available");
|
||||
} else if (!TestUtils.dotFilesEqual(pw, dotFile.getAbsolutePath(), refFile
|
||||
.getAbsolutePath())) {
|
||||
differences.add(dotFile.getName() + " is different from the reference");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,308 +0,0 @@
|
|||
/*
|
||||
* UmlGraph class diagram testing framework
|
||||
*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StreamTokenizer;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DotDiff {
|
||||
|
||||
private List<DotNode> nodes1 = new ArrayList<DotNode>();
|
||||
|
||||
private List<DotNode> nodes2 = new ArrayList<DotNode>();
|
||||
|
||||
private List<DotArc> arcs1 = new ArrayList<DotArc>();
|
||||
|
||||
private List<DotArc> arcs2 = new ArrayList<DotArc>();
|
||||
|
||||
private List<String> extraLines1 = new ArrayList<String>();
|
||||
|
||||
private List<String> extraLines2 = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* Builds a dot differ on the two files
|
||||
*
|
||||
* @param dotFirst
|
||||
* @param dotSecond
|
||||
* @throws IOException
|
||||
*/
|
||||
public DotDiff(File dotFirst, File dotSecond) throws IOException {
|
||||
// gather the lines
|
||||
List<String> lines1 = readGraphLines(dotFirst);
|
||||
List<String> lines2 = readGraphLines(dotSecond);
|
||||
|
||||
// parse the lines
|
||||
extraLines1 = parseLines(lines1, nodes1, arcs1);
|
||||
extraLines2 = parseLines(lines2, nodes2, arcs2);
|
||||
|
||||
// diff extra lines
|
||||
for (Iterator<String> it = extraLines1.iterator(); it.hasNext();) {
|
||||
if (extraLines2.remove(it.next()))
|
||||
it.remove();
|
||||
}
|
||||
|
||||
// diff nodes
|
||||
for (Iterator<DotNode> it = nodes1.iterator(); it.hasNext();) {
|
||||
if (nodes2.remove(it.next()))
|
||||
it.remove();
|
||||
}
|
||||
|
||||
// diff arcs
|
||||
for (Iterator<DotArc> it = arcs1.iterator(); it.hasNext();) {
|
||||
if (arcs2.remove(it.next()))
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the dot files are structurally equal, that is, if every
|
||||
* non comment and non header line of the first file appears in the second,
|
||||
* and otherwise.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean graphEquals() {
|
||||
return (extraLines1.size() + extraLines2.size() + nodes1.size() + nodes2.size()
|
||||
+ arcs1.size() + arcs2.size()) == 0;
|
||||
}
|
||||
|
||||
public List<DotArc> getArcs1() {
|
||||
return arcs1;
|
||||
}
|
||||
|
||||
public List<DotArc> getArcs2() {
|
||||
return arcs2;
|
||||
}
|
||||
|
||||
public List<String> getExtraLines1() {
|
||||
return extraLines1;
|
||||
}
|
||||
|
||||
public List<String> getExtraLines2() {
|
||||
return extraLines2;
|
||||
}
|
||||
|
||||
public List<DotNode> getNodes1() {
|
||||
return nodes1;
|
||||
}
|
||||
|
||||
public List<DotNode> getNodes2() {
|
||||
return nodes2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all relevant lines from the dot file
|
||||
*
|
||||
* @param dotFile
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private List<String> readGraphLines(File dotFile) throws IOException {
|
||||
List<String> lines = new ArrayList<String>();
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader(dotFile));
|
||||
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
line = line.trim();
|
||||
if (graphDefinitionLine(line))
|
||||
lines.add(line);
|
||||
}
|
||||
} finally {
|
||||
if (br != null)
|
||||
br.close();
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if a line is relevant or not (unrelevant lines are headers,
|
||||
* comments, "digraf G {" and the closing "}" (to simplify matters we assume
|
||||
* the file is properly structured).
|
||||
*
|
||||
* @param line
|
||||
* @return
|
||||
*/
|
||||
private boolean graphDefinitionLine(String line) {
|
||||
return !(line.startsWith("#") || line.startsWith("//") || line.equals("digraph G {") || line
|
||||
.equals("}"));
|
||||
}
|
||||
|
||||
private List<String> parseLines(List<String> lines, List<DotNode> nodeList, List<DotArc> arcs)
|
||||
throws IOException {
|
||||
List<String> extraLines = new ArrayList<String>();
|
||||
List<String> arcLines = new ArrayList<String>();
|
||||
Map<String, DotNode> nodes = new HashMap<String, DotNode>();
|
||||
for (String line : lines) {
|
||||
int openBrackedIdx = line.indexOf('[');
|
||||
int closedBracketIdx = line.lastIndexOf(']');
|
||||
int arrowIdx = line.indexOf("->");
|
||||
if (openBrackedIdx < 0 && closedBracketIdx < 0 || line.startsWith("edge")
|
||||
|| line.startsWith("node"))
|
||||
extraLines.add(line);
|
||||
else if (arrowIdx > 0 && arrowIdx < openBrackedIdx) { // that's an arc
|
||||
arcLines.add(line);
|
||||
} else { // that's a node
|
||||
String attributes = line.substring(openBrackedIdx + 1, closedBracketIdx);
|
||||
Map<String, String> attMap = parseAttributes(attributes);
|
||||
String name = line.substring(0, openBrackedIdx - 1).trim();
|
||||
String label = attMap.get("label");
|
||||
DotNode node = new DotNode(name, label, attMap, line);
|
||||
nodes.put(name, node);
|
||||
nodeList.add(node);
|
||||
}
|
||||
}
|
||||
for (String line : arcLines) {
|
||||
int openBrackedIdx = line.indexOf('[');
|
||||
int closedBracketIdx = line.lastIndexOf(']');
|
||||
String attributes = line.substring(openBrackedIdx + 1, closedBracketIdx);
|
||||
String[] names = line.substring(0, openBrackedIdx).split("->");
|
||||
DotNode from = nodes.get(names[0].trim());
|
||||
DotNode to = nodes.get(names[1].trim());
|
||||
if (from == null) {
|
||||
from = new DotNode(names[0], "", new HashMap<String, String>(), "");
|
||||
}
|
||||
if (to == null) {
|
||||
to = new DotNode(names[1], "", new HashMap<String, String>(), "");
|
||||
}
|
||||
arcs.add(new DotArc(from, to, parseAttributes(attributes), line));
|
||||
}
|
||||
return extraLines;
|
||||
}
|
||||
|
||||
private Map<String, String> parseAttributes(String attributes) throws IOException {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
|
||||
StreamTokenizer st = new StreamTokenizer(new StringReader(attributes));
|
||||
st.wordChars('_', '_');
|
||||
st.wordChars('\\', '\\');
|
||||
st.wordChars('\'', '\'');
|
||||
int tokenType;
|
||||
boolean isValue = false;
|
||||
String attName = null;
|
||||
String token = null;
|
||||
while ((tokenType = st.nextToken()) != StreamTokenizer.TT_EOF) {
|
||||
switch (tokenType) {
|
||||
case StreamTokenizer.TT_NUMBER:
|
||||
token = "" + st.nval;
|
||||
break;
|
||||
case StreamTokenizer.TT_WORD:
|
||||
case '"':
|
||||
case '\'':
|
||||
token = st.sval;
|
||||
break;
|
||||
}
|
||||
tokenType = st.nextToken();
|
||||
|
||||
if (isValue) {
|
||||
map.put(attName, token);
|
||||
isValue = false;
|
||||
} else {
|
||||
attName = token;
|
||||
isValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
private static class DotNode {
|
||||
String name;
|
||||
|
||||
String label;
|
||||
|
||||
Map<String, String> attributes;
|
||||
|
||||
String line;
|
||||
|
||||
public DotNode(String name, String label, Map<String, String> attributes, String line) {
|
||||
this.name = name;
|
||||
this.label = label.replace("\n", "\\n");
|
||||
this.attributes = attributes;
|
||||
this.line = line.replace("\n", "\\n");
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof DotNode))
|
||||
return false;
|
||||
|
||||
DotNode on = (DotNode) other;
|
||||
if (label == null) // anonymous node
|
||||
return on.label == null && on.name.equals(name) && on.attributes.equals(attributes);
|
||||
else
|
||||
return on.label.equals(label) && on.attributes.equals(attributes);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return name.hashCode() + 17 * attributes.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Node: " + label + "; " + line;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DotArc {
|
||||
DotNode from;
|
||||
|
||||
DotNode to;
|
||||
|
||||
Map<String, String> attributes;
|
||||
|
||||
String line;
|
||||
|
||||
public DotArc(DotNode from, DotNode to, Map<String, String> attributes, String line) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.attributes = attributes;
|
||||
this.line = line.replace("\n", "\\n");
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof DotArc))
|
||||
return false;
|
||||
|
||||
DotArc oa = (DotArc) other;
|
||||
return oa.from.equals(from) && oa.to.equals(to) && oa.attributes.equals(attributes);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return from.hashCode() + 17 * (to.hashCode() + 17 * attributes.hashCode());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Arc: " + from.label + " -> " + to.label + "; " + line;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* UmlGraph class diagram testing framework
|
||||
*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class RunDoc {
|
||||
|
||||
static String sourcesFolder = "src";
|
||||
|
||||
static String docFolder = "javadoc";
|
||||
|
||||
static PrintWriter pw = new PrintWriter(System.out);
|
||||
|
||||
public static void main(String[] args) {
|
||||
File outFolder = new File(docFolder);
|
||||
if (!outFolder.exists())
|
||||
outFolder.mkdirs();
|
||||
String[] options = new String[] { "-docletpath", "build", "-private", "-d", docFolder,
|
||||
"-sourcepath", sourcesFolder, "-subpackages", "gr.spinellis" };
|
||||
runDoclet(options);
|
||||
}
|
||||
|
||||
private static void runDoclet(String[] options) {
|
||||
com.sun.tools.javadoc.Main.execute("UMLGraph test", pw, pw, pw,
|
||||
"gr.spinellis.umlgraph.doclet.UmlGraphDoc", options);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* UmlGraph class diagram testing framework
|
||||
*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class RunOne {
|
||||
|
||||
static String testSourceFolder = "testdata/java/";
|
||||
|
||||
static String testDestFolder = "testdata/dot-out";
|
||||
|
||||
static PrintWriter pw = new PrintWriter(System.out);
|
||||
|
||||
public static void main(String[] args) {
|
||||
File outFolder = new File(testDestFolder);
|
||||
if (!outFolder.exists())
|
||||
outFolder.mkdirs();
|
||||
|
||||
// runView("gr.spinellis.views.ViewChildEmpty");
|
||||
runSingleClass("TestHiddenOp");
|
||||
}
|
||||
|
||||
public static void runView(String viewClass) {
|
||||
String[] options = new String[] { "-docletpath", "build", "-private", "-d",
|
||||
testDestFolder, "-sourcepath", "testdata/java", "-subpackages",
|
||||
"gr.spinellis", "-view", viewClass};
|
||||
runDoclet(options);
|
||||
}
|
||||
|
||||
public static void runSingleClass(String className) {
|
||||
String[] options = new String[] { "-docletpath", "build", "-hide", "Hidden",
|
||||
"-private", "-d", testDestFolder, "-output", className + ".dot", testSourceFolder + className + ".java"};
|
||||
runDoclet(options);
|
||||
}
|
||||
|
||||
private static void runDoclet(String[] options) {
|
||||
com.sun.tools.javadoc.Main.execute("UMLGraph test", pw, pw, pw, "gr.spinellis.umlgraph.doclet.UmlGraph", options);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* UmlGraph class diagram testing framework
|
||||
*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
package gr.spinellis.umlgraph.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
|
||||
class SimpleFileFilter implements FilenameFilter {
|
||||
protected String extension;
|
||||
|
||||
public SimpleFileFilter(String ext) {
|
||||
this.extension = ext;
|
||||
}
|
||||
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(extension);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
* UmlGraph class diagram testing framework
|
||||
*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
package gr.spinellis.umlgraph.test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Collection of utility methods used by the test classes
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public class TestUtils {
|
||||
|
||||
/**
|
||||
* Simple text file diffing: will tell you if two text files are line by
|
||||
* line equals, and will stop at the first difference found.
|
||||
* @throws IOException
|
||||
*/
|
||||
public static boolean textFilesEquals(PrintWriter pw, File refTextFile, File outTextFile)
|
||||
throws IOException {
|
||||
BufferedReader refReader = null, outReader = null;
|
||||
String refLine = null, outFile = null;
|
||||
try {
|
||||
pw.println("Performing diff:");
|
||||
pw.println("out: " + outTextFile.getAbsolutePath());
|
||||
pw.println("ref: " + refTextFile.getAbsolutePath());
|
||||
|
||||
refReader = new BufferedReader(new FileReader(refTextFile));
|
||||
outReader = new BufferedReader(new FileReader(outTextFile));
|
||||
|
||||
// line by line scan, exit when one file ends or lines are not
|
||||
// equal (and pass over the "Generated by javadoc ..." comments)
|
||||
for (;;) {
|
||||
refLine = refReader.readLine();
|
||||
outFile = outReader.readLine();
|
||||
if (refLine == null || outFile == null) {
|
||||
break;
|
||||
} else if (refLine.startsWith("<!-- Generated by javadoc ")) {
|
||||
if (!outFile.startsWith("<!-- Generated by javadoc "))
|
||||
break;
|
||||
} else if (!refLine.equals(outFile)) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} finally {
|
||||
if (refReader != null)
|
||||
refReader.close();
|
||||
if (outReader != null)
|
||||
outReader.close();
|
||||
}
|
||||
// they were equals if both files ended at the same time
|
||||
boolean equal = refLine == null && outFile == null;
|
||||
if (equal)
|
||||
pw.print("File contents are equal");
|
||||
else
|
||||
pw.println("Differences found\nref: " + refLine + "\nout: " + outFile);
|
||||
pw.println();
|
||||
pw.println();
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
public static boolean dotFilesEqual(PrintWriter pw, String dotPath, String refPath)
|
||||
throws IOException {
|
||||
pw.println("Performing diff:\nout:" + dotPath + "\nref:" + refPath);
|
||||
DotDiff differ = new DotDiff(new File(dotPath), new File(refPath));
|
||||
boolean equal = differ.graphEquals();
|
||||
if (equal) {
|
||||
pw.println("File contents are structurally equal");
|
||||
} else {
|
||||
pw.println("File contents are structurally not equal");
|
||||
printList(pw, "# Lines in out but not in ref", differ.getExtraLines1());
|
||||
printList(pw, "# Lines in ref but not in out", differ.getExtraLines2());
|
||||
printList(pw, "# Nodes in out but not in ref", differ.getNodes1());
|
||||
printList(pw, "# Nodes in ref but not in out", differ.getNodes2());
|
||||
printList(pw, "# Arcs in out but not in ref", differ.getArcs1());
|
||||
printList(pw, "# Arcs in ref but not in out", differ.getArcs2());
|
||||
}
|
||||
pw.println("\n\n");
|
||||
return equal;
|
||||
}
|
||||
|
||||
public static void printList(PrintWriter pw, String message, List extraOut) {
|
||||
if (extraOut.size() > 0) {
|
||||
pw.println(message);
|
||||
for (Object o : extraOut) {
|
||||
pw.println(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the content of the folder, eventually in a recursive way (but
|
||||
* avoids deleting eventual .cvsignore files and CVS folders)
|
||||
*/
|
||||
public static void cleanFolder(File folder, boolean recurse) {
|
||||
for (File f : folder.listFiles()) {
|
||||
if (f.isDirectory() && !f.getName().equals("CVS")) {
|
||||
if (recurse) {
|
||||
cleanFolder(f, true);
|
||||
if (f.list().length == 0)
|
||||
f.delete();
|
||||
}
|
||||
} else if (!f.getName().equals(".cvsignore")) {
|
||||
f.delete();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
* UmlGraph class diagram testing framework
|
||||
*
|
||||
* Contibuted by Andrea Aime
|
||||
* (C) Copyright 2005 Diomidis Spinellis
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
package gr.spinellis.umlgraph.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* UmlGraphDoc doclet regression tests
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public class UmlDocTest {
|
||||
|
||||
static final String testSourceFolder = "testdata/umldoc-src";
|
||||
|
||||
static final String testDestFolder = "testdata/umldoc-out";
|
||||
|
||||
static final String testRefFolder = "testdata/umldoc-ref";
|
||||
static final String doclet = "gr.spinellis.umlgraph.doclet.UmlGraphDoc";
|
||||
|
||||
static PrintWriter pw = new PrintWriter(System.out);
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
List<String> differences = new ArrayList<String>();
|
||||
|
||||
File outFolder = new File(testDestFolder);
|
||||
if (!outFolder.exists())
|
||||
outFolder.mkdirs();
|
||||
|
||||
TestUtils.cleanFolder(outFolder, true);
|
||||
|
||||
// don't use windows specific fonts
|
||||
System.setProperty("os.name", "generic");
|
||||
|
||||
// run tests
|
||||
runTest(differences);
|
||||
if (differences.size() > 0) {
|
||||
pw.println("ERROR, some files are not structurally equal or some files are missing:");
|
||||
for (String className : differences) {
|
||||
pw.println(className);
|
||||
}
|
||||
} else {
|
||||
pw.println("GOOD, all files are structurally equal");
|
||||
}
|
||||
pw.println();
|
||||
pw.println();
|
||||
pw.flush();
|
||||
}
|
||||
|
||||
private static void runTest(List<String> differences) throws IOException {
|
||||
File outFolder = new File(testDestFolder);
|
||||
String[] options = new String[] { "-docletpath", "build", "-private", "-d",
|
||||
outFolder.getAbsolutePath(), "-sourcepath", testSourceFolder, "-compact",
|
||||
"-subpackages", "gr.spinellis", "-inferrel", "-inferdep", "-qualify",
|
||||
"-postfixpackage", "-collpackages", "java.util.*" };
|
||||
runDoclet(options);
|
||||
|
||||
compareDocletOutputs(differences, new File(testRefFolder), new File(testDestFolder));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that reference and output have the same contents in terms of:
|
||||
* <ul>
|
||||
* <li> html files </li>
|
||||
* <li> dot files </li>
|
||||
* <li> folders </li>
|
||||
* </ul>
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void compareDocletOutputs(List<String> differences, File refFolder,
|
||||
File outFolder) throws IOException {
|
||||
if(refFolder.getName().equals("CVS"))
|
||||
return;
|
||||
|
||||
if (!refFolder.exists() || !refFolder.isDirectory())
|
||||
throw new IllegalArgumentException("Reference does not exists or is not a folder: "
|
||||
+ refFolder.getAbsolutePath());
|
||||
if (!outFolder.exists() || !outFolder.isDirectory())
|
||||
throw new IllegalArgumentException("Output does not exists or is not a folder: "
|
||||
+ outFolder.getAbsolutePath());
|
||||
|
||||
// get elements and sort
|
||||
String[] refFiles = refFolder.list();
|
||||
String[] outFiles = refFolder.list();
|
||||
Arrays.sort(refFiles);
|
||||
Arrays.sort(outFiles);
|
||||
|
||||
// parallel scan (mergesort inspired)
|
||||
int i = 0, j = 0;
|
||||
while (i < refFiles.length && j < outFiles.length) {
|
||||
File ref = new File(refFolder, refFiles[i]);
|
||||
File out = new File(outFolder, outFiles[j]);
|
||||
int compare = refFiles[i].compareTo(outFiles[i]);
|
||||
if (compare == 0) {
|
||||
String refName = ref.getName().toLowerCase();
|
||||
if (ref.isDirectory()) {
|
||||
compareDocletOutputs(differences, ref, out);
|
||||
} else if (refName.endsWith(".dot")) {
|
||||
if (!TestUtils.dotFilesEqual(pw, ref.getAbsolutePath(), out.getAbsolutePath()))
|
||||
differences.add(out.getName() + " is different from the reference");
|
||||
|
||||
} else {
|
||||
if (!TestUtils.textFilesEquals(pw, ref, out))
|
||||
differences.add(out.getName() + " is different from the reference");
|
||||
}
|
||||
i++;
|
||||
j++;
|
||||
} else if (compare < 0) {
|
||||
differences.add("Reference file/folder not found in output: "
|
||||
+ ref.getAbsolutePath());
|
||||
i++;
|
||||
} else {
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
// all ref files remaining are missing ones
|
||||
while (i < refFiles.length) {
|
||||
File ref = new File(refFolder, refFiles[i]);
|
||||
differences.add("Reference file/folder not found in output: " + ref.getAbsolutePath());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the UmlGraphDoc doclet
|
||||
* @param options
|
||||
*/
|
||||
private static void runDoclet(String[] options) {
|
||||
pw.print("Run javadoc -doclet " + doclet);
|
||||
for (String o : options)
|
||||
pw.print(o + " ");
|
||||
pw.println();
|
||||
com.sun.tools.javadoc.Main.execute("UMLDoc test", pw, pw, pw,
|
||||
doclet, options);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue